summaryrefslogtreecommitdiffstats
path: root/dom/media/systemservices/MediaSystemResourceManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/systemservices/MediaSystemResourceManager.cpp')
-rw-r--r--dom/media/systemservices/MediaSystemResourceManager.cpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/dom/media/systemservices/MediaSystemResourceManager.cpp b/dom/media/systemservices/MediaSystemResourceManager.cpp
new file mode 100644
index 0000000000..414ef8e81d
--- /dev/null
+++ b/dom/media/systemservices/MediaSystemResourceManager.cpp
@@ -0,0 +1,358 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/TaskQueue.h"
+
+#include "MediaSystemResourceManagerChild.h"
+#include "MediaSystemResourceClient.h"
+
+#include "mozilla/layers/ImageBridgeChild.h"
+
+#include "MediaSystemResourceManager.h"
+
+namespace mozilla {
+
+using namespace mozilla::ipc;
+using namespace mozilla::layers;
+
+/* static */
+StaticRefPtr<MediaSystemResourceManager> MediaSystemResourceManager::sSingleton;
+
+/* static */
+MediaSystemResourceManager* MediaSystemResourceManager::Get() {
+ if (sSingleton) {
+ return sSingleton;
+ }
+ MediaSystemResourceManager::Init();
+ return sSingleton;
+}
+
+/* static */
+void MediaSystemResourceManager::Shutdown() {
+ MOZ_ASSERT(InImageBridgeChildThread());
+ if (sSingleton) {
+ sSingleton->CloseIPC();
+ sSingleton = nullptr;
+ }
+}
+
+/* static */
+void MediaSystemResourceManager::Init() {
+ RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
+ if (!imageBridge) {
+ NS_WARNING("ImageBridge does not exist");
+ return;
+ }
+
+ if (InImageBridgeChildThread()) {
+ if (!sSingleton) {
+#ifdef DEBUG
+ static int timesCreated = 0;
+ timesCreated++;
+ MOZ_ASSERT(timesCreated == 1);
+#endif
+ sSingleton = new MediaSystemResourceManager();
+ }
+ return;
+ }
+
+ ReentrantMonitor barrier MOZ_UNANNOTATED("MediaSystemResourceManager::Init");
+ ReentrantMonitorAutoEnter mainThreadAutoMon(barrier);
+ bool done = false;
+
+ RefPtr<Runnable> runnable =
+ NS_NewRunnableFunction("MediaSystemResourceManager::Init", [&]() {
+ if (!sSingleton) {
+ sSingleton = new MediaSystemResourceManager();
+ }
+ ReentrantMonitorAutoEnter childThreadAutoMon(barrier);
+ done = true;
+ barrier.NotifyAll();
+ });
+
+ imageBridge->GetThread()->Dispatch(runnable.forget());
+
+ // should stop the thread until done.
+ while (!done) {
+ barrier.Wait();
+ }
+}
+
+MediaSystemResourceManager::MediaSystemResourceManager()
+ : mReentrantMonitor("MediaSystemResourceManager.mReentrantMonitor"),
+ mShutDown(false),
+ mChild(nullptr) {
+ MOZ_ASSERT(InImageBridgeChildThread());
+ OpenIPC();
+}
+
+MediaSystemResourceManager::~MediaSystemResourceManager() {
+ MOZ_ASSERT(IsIpcClosed());
+}
+
+void MediaSystemResourceManager::OpenIPC() {
+ MOZ_ASSERT(InImageBridgeChildThread());
+ MOZ_ASSERT(!mChild);
+
+ media::PMediaSystemResourceManagerChild* child =
+ ImageBridgeChild::GetSingleton()
+ ->SendPMediaSystemResourceManagerConstructor();
+ mChild = static_cast<media::MediaSystemResourceManagerChild*>(child);
+ mChild->SetManager(this);
+}
+
+void MediaSystemResourceManager::CloseIPC() {
+ MOZ_ASSERT(InImageBridgeChildThread());
+
+ if (!mChild) {
+ return;
+ }
+ mChild->Destroy();
+ mChild = nullptr;
+ mShutDown = true;
+}
+
+void MediaSystemResourceManager::OnIpcClosed() { mChild = nullptr; }
+
+bool MediaSystemResourceManager::IsIpcClosed() { return mChild ? true : false; }
+
+void MediaSystemResourceManager::Register(MediaSystemResourceClient* aClient) {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MOZ_ASSERT(aClient);
+ MOZ_ASSERT(!mResourceClients.Contains(aClient->mId));
+
+ mResourceClients.InsertOrUpdate(aClient->mId, aClient);
+}
+
+void MediaSystemResourceManager::Unregister(
+ MediaSystemResourceClient* aClient) {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MOZ_ASSERT(aClient);
+ MOZ_ASSERT(mResourceClients.Contains(aClient->mId));
+ MOZ_ASSERT(mResourceClients.Get(aClient->mId) == aClient);
+
+ mResourceClients.Remove(aClient->mId);
+}
+
+bool MediaSystemResourceManager::SetListener(
+ MediaSystemResourceClient* aClient,
+ MediaSystemResourceReservationListener* aListener) {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MOZ_ASSERT(aClient);
+
+ MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
+ MOZ_ASSERT(client);
+
+ if (!client) {
+ return false;
+ }
+ // State Check
+ if (aClient->mResourceState !=
+ MediaSystemResourceClient::RESOURCE_STATE_START) {
+ return false;
+ }
+ aClient->mListener = aListener;
+ return true;
+}
+
+void MediaSystemResourceManager::Acquire(MediaSystemResourceClient* aClient) {
+ MOZ_ASSERT(aClient);
+ MOZ_ASSERT(!InImageBridgeChildThread());
+
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
+ MOZ_ASSERT(client);
+ MOZ_ASSERT(client == aClient);
+
+ aClient->mIsSync = false; // async request
+
+ if (!client) {
+ HandleAcquireResult(aClient->mId, false);
+ return;
+ }
+ // State Check
+ if (aClient->mResourceState !=
+ MediaSystemResourceClient::RESOURCE_STATE_START) {
+ HandleAcquireResult(aClient->mId, false);
+ return;
+ }
+ aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
+ ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
+ NewRunnableMethod<uint32_t>("MediaSystemResourceManager::DoAcquire", this,
+ &MediaSystemResourceManager::DoAcquire,
+ aClient->mId));
+}
+
+bool MediaSystemResourceManager::AcquireSyncNoWait(
+ MediaSystemResourceClient* aClient) {
+ MOZ_ASSERT(aClient);
+ MOZ_ASSERT(!InImageBridgeChildThread());
+
+ ReentrantMonitor barrier MOZ_UNANNOTATED(
+ "MediaSystemResourceManager::AcquireSyncNoWait");
+ ReentrantMonitorAutoEnter autoMon(barrier);
+ bool done = false;
+ {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
+ MOZ_ASSERT(client);
+ MOZ_ASSERT(client == aClient);
+
+ aClient->mIsSync = true; // sync request
+
+ if (InImageBridgeChildThread()) {
+ HandleAcquireResult(aClient->mId, false);
+ return false;
+ }
+ if (!client || client != aClient) {
+ HandleAcquireResult(aClient->mId, false);
+ return false;
+ }
+ // State Check
+ if (aClient->mResourceState !=
+ MediaSystemResourceClient::RESOURCE_STATE_START) {
+ HandleAcquireResult(aClient->mId, false);
+ return false;
+ }
+ // Hold barrier Monitor until acquire task end.
+ aClient->mAcquireSyncWaitMonitor = &barrier;
+ aClient->mAcquireSyncWaitDone = &done;
+ aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_WAITING;
+ }
+
+ ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
+ NewRunnableMethod<uint32_t>("MediaSystemResourceManager::DoAcquire", this,
+ &MediaSystemResourceManager::DoAcquire,
+ aClient->mId));
+
+ // should stop the thread until done.
+ while (!done) {
+ barrier.Wait();
+ }
+
+ {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ if (aClient->mResourceState !=
+ MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED) {
+ return false;
+ }
+ return true;
+ }
+}
+
+void MediaSystemResourceManager::DoAcquire(uint32_t aId) {
+ MOZ_ASSERT(InImageBridgeChildThread());
+ if (mShutDown || !mChild) {
+ HandleAcquireResult(aId, false);
+ return;
+ }
+ {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MediaSystemResourceClient* client = mResourceClients.Get(aId);
+ MOZ_ASSERT(client);
+
+ if (!client || client->mResourceState !=
+ MediaSystemResourceClient::RESOURCE_STATE_WAITING) {
+ HandleAcquireResult(aId, false);
+ return;
+ }
+ MOZ_ASSERT(aId == client->mId);
+ bool willWait = !client->mAcquireSyncWaitMonitor ? true : false;
+ mChild->SendAcquire(client->mId, client->mResourceType, willWait);
+ }
+}
+
+void MediaSystemResourceManager::ReleaseResource(
+ MediaSystemResourceClient* aClient) {
+ MOZ_ASSERT(aClient);
+ {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MediaSystemResourceClient* client = mResourceClients.Get(aClient->mId);
+ MOZ_ASSERT(client);
+ MOZ_ASSERT(client == aClient);
+
+ if (!client || client != aClient ||
+ aClient->mResourceState ==
+ MediaSystemResourceClient::RESOURCE_STATE_START ||
+ aClient->mResourceState ==
+ MediaSystemResourceClient::RESOURCE_STATE_END) {
+ aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
+ return;
+ }
+
+ aClient->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_END;
+
+ ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
+ NewRunnableMethod<uint32_t>(
+ "MediaSystemResourceManager::DoRelease", this,
+ &MediaSystemResourceManager::DoRelease, aClient->mId));
+ }
+}
+
+void MediaSystemResourceManager::DoRelease(uint32_t aId) {
+ MOZ_ASSERT(InImageBridgeChildThread());
+ if (mShutDown || !mChild) {
+ return;
+ }
+ mChild->SendRelease(aId);
+}
+
+void MediaSystemResourceManager::RecvResponse(uint32_t aId, bool aSuccess) {
+ HandleAcquireResult(aId, aSuccess);
+}
+
+void MediaSystemResourceManager::HandleAcquireResult(uint32_t aId,
+ bool aSuccess) {
+ if (!InImageBridgeChildThread()) {
+ ImageBridgeChild::GetSingleton()->GetThread()->Dispatch(
+ NewRunnableMethod<uint32_t, bool>(
+ "MediaSystemResourceManager::HandleAcquireResult", this,
+ &MediaSystemResourceManager::HandleAcquireResult, aId, aSuccess));
+ return;
+ }
+
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ MediaSystemResourceClient* client = mResourceClients.Get(aId);
+ if (!client) {
+ // Client was already unregistered.
+ return;
+ }
+ if (client->mResourceState !=
+ MediaSystemResourceClient::RESOURCE_STATE_WAITING) {
+ return;
+ }
+
+ // Update state
+ if (aSuccess) {
+ client->mResourceState = MediaSystemResourceClient::RESOURCE_STATE_ACQUIRED;
+ } else {
+ client->mResourceState =
+ MediaSystemResourceClient::RESOURCE_STATE_NOT_ACQUIRED;
+ }
+
+ if (client->mIsSync) {
+ if (client->mAcquireSyncWaitMonitor) {
+ // Notify AcquireSync() complete
+ MOZ_ASSERT(client->mAcquireSyncWaitDone);
+ ReentrantMonitorAutoEnter autoMon(*client->mAcquireSyncWaitMonitor);
+ *client->mAcquireSyncWaitDone = true;
+ client->mAcquireSyncWaitMonitor->NotifyAll();
+ client->mAcquireSyncWaitMonitor = nullptr;
+ client->mAcquireSyncWaitDone = nullptr;
+ }
+ } else {
+ // Notify Acquire() result
+ if (client->mListener) {
+ if (aSuccess) {
+ client->mListener->ResourceReserved();
+ } else {
+ client->mListener->ResourceReserveFailed();
+ }
+ }
+ }
+}
+
+} // namespace mozilla