Coverage Report

Created: 2018-09-25 14:53

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