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