2016-06-28 01:25:00 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
|
|
/* 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/dom/GamepadPlatformService.h"
|
|
|
|
|
|
|
|
#include "mozilla/dom/GamepadEventChannelParent.h"
|
2020-10-28 15:29:56 +03:00
|
|
|
#include "mozilla/dom/GamepadMonitoring.h"
|
2020-10-07 20:25:26 +03:00
|
|
|
#include "mozilla/dom/GamepadTestChannelParent.h"
|
2016-06-28 01:25:00 +03:00
|
|
|
#include "mozilla/ipc/BackgroundParent.h"
|
|
|
|
#include "mozilla/Mutex.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2016-06-28 01:25:00 +03:00
|
|
|
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsHashKeys.h"
|
|
|
|
|
|
|
|
using namespace mozilla::ipc;
|
|
|
|
|
2020-11-04 20:04:01 +03:00
|
|
|
namespace mozilla::dom {
|
2016-06-28 01:25:00 +03:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// This is the singleton instance of GamepadPlatformService, can be called
|
|
|
|
// by both background and monitor thread.
|
2020-12-03 01:36:35 +03:00
|
|
|
static StaticRefPtr<GamepadPlatformService> gGamepadPlatformServiceSingleton;
|
2016-06-28 01:25:00 +03:00
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
2020-12-03 01:32:30 +03:00
|
|
|
// static
|
|
|
|
GamepadMonitoringState& GamepadMonitoringState::GetSingleton() {
|
|
|
|
static GamepadMonitoringState sInstance{};
|
|
|
|
return sInstance;
|
2020-10-07 20:25:26 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:32:30 +03:00
|
|
|
void GamepadMonitoringState::AddObserver(GamepadTestChannelParent* aParent) {
|
2020-10-07 20:25:26 +03:00
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(aParent);
|
2020-12-03 01:32:30 +03:00
|
|
|
MOZ_ALWAYS_TRUE(mObservers.append(aParent));
|
2020-10-07 20:25:26 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:32:30 +03:00
|
|
|
void GamepadMonitoringState::RemoveObserver(GamepadTestChannelParent* aParent) {
|
2020-10-07 20:25:26 +03:00
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(aParent);
|
2020-12-03 01:32:30 +03:00
|
|
|
|
|
|
|
WeakPtr<GamepadTestChannelParent>* observer = nullptr;
|
|
|
|
|
|
|
|
for (auto& item : mObservers) {
|
|
|
|
if (item == aParent) {
|
|
|
|
observer = &item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(
|
|
|
|
observer,
|
|
|
|
"Attempted to remove a GamepadTestChannelParent that was never added");
|
|
|
|
|
|
|
|
std::swap(*observer, mObservers.back());
|
|
|
|
mObservers.popBack();
|
2020-10-07 20:25:26 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:32:30 +03:00
|
|
|
bool GamepadMonitoringState::IsMonitoring() const {
|
2020-10-07 20:25:26 +03:00
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
return mIsMonitoring;
|
|
|
|
}
|
|
|
|
|
2020-12-03 01:32:30 +03:00
|
|
|
void GamepadMonitoringState::Set(bool aIsMonitoring) {
|
2020-10-07 20:25:26 +03:00
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
|
|
|
|
if (mIsMonitoring != aIsMonitoring) {
|
|
|
|
mIsMonitoring = aIsMonitoring;
|
|
|
|
for (auto& observer : mObservers) {
|
2020-10-09 19:42:53 +03:00
|
|
|
// Since each GamepadTestChannelParent removes itself in its dtor, this
|
|
|
|
// should never be nullptr
|
|
|
|
MOZ_RELEASE_ASSERT(observer);
|
2020-10-07 20:25:26 +03:00
|
|
|
observer->OnMonitoringStateChanged(aIsMonitoring);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
// This class is created to service one-or-more event channels
|
|
|
|
// This implies an invariant - There is always at-least one event channel while
|
|
|
|
// this class is alive. It should be created with a channel, and it should be
|
|
|
|
// destroyed when the last channel is to be removed.
|
|
|
|
GamepadPlatformService::GamepadPlatformService(
|
|
|
|
RefPtr<GamepadEventChannelParent> aParent)
|
|
|
|
: mNextGamepadServiceId(1), mMutex("mozilla::dom::GamepadPlatformService") {
|
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
mChannelParents.AppendElement(std::move(aParent));
|
|
|
|
MOZ_ASSERT(mChannelParents.Length() == 1);
|
|
|
|
}
|
2016-06-28 01:25:00 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
GamepadPlatformService::~GamepadPlatformService() {
|
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(mChannelParents.Length() == 1);
|
|
|
|
}
|
2016-06-28 01:25:00 +03:00
|
|
|
|
|
|
|
// static
|
2016-06-28 01:27:00 +03:00
|
|
|
already_AddRefed<GamepadPlatformService>
|
2016-06-28 01:25:00 +03:00
|
|
|
GamepadPlatformService::GetParentService() {
|
|
|
|
// GamepadPlatformService can only be accessed in parent process
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MOZ_RELEASE_ASSERT(
|
|
|
|
gGamepadPlatformServiceSingleton,
|
|
|
|
"Impossible for monitor thread to be running with no platform service");
|
|
|
|
|
|
|
|
return RefPtr<GamepadPlatformService>(gGamepadPlatformServiceSingleton)
|
|
|
|
.forget();
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NotifyGamepadChange(
|
|
|
|
uint32_t aServiceId, const T& aInfo, const MutexAutoLock& aProofOfLock) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// This method is called by monitor populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2020-12-03 01:36:35 +03:00
|
|
|
aProofOfLock.AssertOwns(mMutex);
|
2016-06-28 01:25:00 +03:00
|
|
|
|
2017-07-17 06:44:39 +03:00
|
|
|
GamepadChangeEventBody body(aInfo);
|
2020-12-03 01:36:35 +03:00
|
|
|
GamepadChangeEvent e(aServiceId, GamepadServiceType::Standard, body);
|
2016-10-23 20:32:00 +03:00
|
|
|
|
2016-06-28 01:25:00 +03:00
|
|
|
for (uint32_t i = 0; i < mChannelParents.Length(); ++i) {
|
|
|
|
mChannelParents[i]->DispatchUpdateEvent(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t GamepadPlatformService::AddGamepad(
|
|
|
|
const char* aID, GamepadMappingType aMapping, GamepadHand aHand,
|
2019-05-30 01:15:23 +03:00
|
|
|
uint32_t aNumButtons, uint32_t aNumAxes, uint32_t aHaptics,
|
|
|
|
uint32_t aNumLightIndicator, uint32_t aNumTouchEvents) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
uint32_t serviceId = mNextGamepadServiceId++;
|
2017-07-17 06:44:39 +03:00
|
|
|
|
2017-07-14 11:55:52 +03:00
|
|
|
// Only VR controllers has displayID, we give 0 to the general gamepads.
|
2017-07-17 06:44:39 +03:00
|
|
|
GamepadAdded a(NS_ConvertUTF8toUTF16(nsDependentCString(aID)), aMapping,
|
2019-05-30 01:15:23 +03:00
|
|
|
aHand, 0, aNumButtons, aNumAxes, aHaptics, aNumLightIndicator,
|
|
|
|
aNumTouchEvents);
|
2017-02-02 09:33:18 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
mGamepadAdded.emplace(serviceId, a);
|
|
|
|
NotifyGamepadChange<GamepadAdded>(serviceId, a, autoLock);
|
|
|
|
|
|
|
|
return serviceId;
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::RemoveGamepad(uint32_t aServiceId) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2017-07-17 06:44:39 +03:00
|
|
|
GamepadRemoved a;
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
NotifyGamepadChange<GamepadRemoved>(aServiceId, a, autoLock);
|
|
|
|
mGamepadAdded.erase(aServiceId);
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NewButtonEvent(uint32_t aServiceId,
|
|
|
|
uint32_t aButton, bool aPressed,
|
|
|
|
bool aTouched, double aValue) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2017-07-17 06:44:39 +03:00
|
|
|
GamepadButtonInformation a(aButton, aValue, aPressed, aTouched);
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
NotifyGamepadChange<GamepadButtonInformation>(aServiceId, a, autoLock);
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NewButtonEvent(uint32_t aServiceId,
|
|
|
|
uint32_t aButton, bool aPressed,
|
|
|
|
double aValue) {
|
2019-07-15 10:36:36 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
// When only a digital button is available the value will be synthesized.
|
2020-12-03 01:36:35 +03:00
|
|
|
NewButtonEvent(aServiceId, aButton, aPressed, aPressed, aValue);
|
2019-07-15 10:36:36 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NewButtonEvent(uint32_t aServiceId,
|
|
|
|
uint32_t aButton, bool aPressed,
|
|
|
|
bool aTouched) {
|
2017-04-07 04:35:13 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
// When only a digital button is available the value will be synthesized.
|
2020-12-03 01:36:35 +03:00
|
|
|
NewButtonEvent(aServiceId, aButton, aPressed, aTouched,
|
|
|
|
aPressed ? 1.0L : 0.0L);
|
2017-04-07 04:35:13 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NewButtonEvent(uint32_t aServiceId,
|
|
|
|
uint32_t aButton, bool aPressed) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
// When only a digital button is available the value will be synthesized.
|
2020-12-03 01:36:35 +03:00
|
|
|
NewButtonEvent(aServiceId, aButton, aPressed, aPressed,
|
|
|
|
aPressed ? 1.0L : 0.0L);
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NewAxisMoveEvent(uint32_t aServiceId,
|
|
|
|
uint32_t aAxis, double aValue) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2017-07-17 06:44:39 +03:00
|
|
|
GamepadAxisInformation a(aAxis, aValue);
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
NotifyGamepadChange<GamepadAxisInformation>(aServiceId, a, autoLock);
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2019-05-30 01:15:23 +03:00
|
|
|
void GamepadPlatformService::NewLightIndicatorTypeEvent(
|
2020-12-03 01:36:35 +03:00
|
|
|
uint32_t aServiceId, uint32_t aLight, GamepadLightIndicatorType aType) {
|
2019-05-30 01:15:23 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
GamepadLightIndicatorTypeInformation a(aLight, aType);
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
NotifyGamepadChange<GamepadLightIndicatorTypeInformation>(aServiceId, a,
|
|
|
|
autoLock);
|
2019-05-30 01:15:23 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::NewPoseEvent(uint32_t aServiceId,
|
2019-05-30 01:15:23 +03:00
|
|
|
const GamepadPoseState& aState) {
|
2017-02-02 10:00:51 +03:00
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2019-05-30 01:15:23 +03:00
|
|
|
GamepadPoseInformation a(aState);
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
NotifyGamepadChange<GamepadPoseInformation>(aServiceId, a, autoLock);
|
2017-02-02 10:00:51 +03:00
|
|
|
}
|
|
|
|
|
2019-05-30 01:15:23 +03:00
|
|
|
void GamepadPlatformService::NewMultiTouchEvent(
|
2020-12-03 01:36:35 +03:00
|
|
|
uint32_t aServiceId, uint32_t aTouchArrayIndex,
|
2019-05-30 01:15:23 +03:00
|
|
|
const GamepadTouchState& aState) {
|
|
|
|
// This method is called by monitor thread populated in
|
|
|
|
// platform-dependent backends
|
|
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
|
|
|
|
|
|
|
GamepadTouchInformation a(aTouchArrayIndex, aState);
|
2020-12-03 01:36:35 +03:00
|
|
|
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
NotifyGamepadChange<GamepadTouchInformation>(aServiceId, a, autoLock);
|
2019-05-30 01:15:23 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
void GamepadPlatformService::AddChannelParentInternal(
|
|
|
|
const RefPtr<GamepadEventChannelParent>& aParent) {
|
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
|
|
|
|
MOZ_ASSERT(!mChannelParents.Contains(aParent));
|
|
|
|
mChannelParents.AppendElement(aParent);
|
|
|
|
|
|
|
|
// Inform the new channel of all the gamepads that have already been added
|
|
|
|
for (const auto& evt : mGamepadAdded) {
|
|
|
|
GamepadChangeEventBody body(evt.second);
|
|
|
|
GamepadChangeEvent e(evt.first, GamepadServiceType::Standard, body);
|
|
|
|
aParent->DispatchUpdateEvent(e);
|
|
|
|
}
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
bool GamepadPlatformService::RemoveChannelParentInternal(
|
2016-06-28 01:25:00 +03:00
|
|
|
GamepadEventChannelParent* aParent) {
|
2020-12-03 01:36:35 +03:00
|
|
|
MutexAutoLock autoLock(mMutex);
|
|
|
|
|
|
|
|
MOZ_ASSERT(mChannelParents.Contains(aParent));
|
|
|
|
|
|
|
|
// If there is only one channel left, we destroy the singleton instead of
|
|
|
|
// unregistering the channel
|
|
|
|
if (mChannelParents.Length() == 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mChannelParents.RemoveElement(aParent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
void GamepadPlatformService::AddChannelParent(
|
|
|
|
const RefPtr<GamepadEventChannelParent>& aParent) {
|
2016-06-28 01:25:00 +03:00
|
|
|
// mChannelParents can only be modified once GamepadEventChannelParent
|
|
|
|
// is created or removed in Background thread
|
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(aParent);
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
if (gGamepadPlatformServiceSingleton) {
|
|
|
|
gGamepadPlatformServiceSingleton->AddChannelParentInternal(aParent);
|
|
|
|
return;
|
Bug 1660660 - Fix deadlock in gamepad initialization code. r=cmartin
StartGamepadMonitoring() can end up in AddGamepad, and acquire the lock
again on the same thread, effectively dead-locking.
This is a regression from bug 1657404. Relevant stack:
(gdb) bt
#0 0x00007fd19bace801 in clock_nanosleep@GLIBC_2.2.5 () at /lib64/libc.so.6
#1 0x00007fd19bad4157 in nanosleep () at /lib64/libc.so.6
#2 0x00007fd19bad408e in sleep () at /lib64/libc.so.6
#3 0x00007fd195233e87 in ah_crap_handler(int) (signum=11) at /home/emilio/src/moz/gecko-4/toolkit/xre/nsSigHandlers.cpp:95
#4 0x00007fd1952165c4 in nsProfileLock::FatalSignalHandler(int, siginfo_t*, void*) (signo=11, info=0x7fd14abb9db0, context=0x7fd14abb9c80) at /home/emilio/src/moz/gecko-4/toolkit/profile/nsProfileLock.cpp:177
#5 0x00007fd1964973b2 in WasmTrapHandler(int, siginfo_t*, void*) (signum=11, info=<optimized out>, context=<optimized out>) at /home/emilio/src/moz/gecko-4/js/src/wasm/WasmSignalHandlers.cpp:978
#6 0x00007fd19bf3ca90 in <signal handler called> () at /lib64/libpthread.so.0
#7 mozilla::detail::MutexImpl::mutexLock() (this=<optimized out>) at /home/emilio/src/moz/gecko-4/mozglue/misc/Mutex_posix.cpp:118
#8 mozilla::detail::MutexImpl::lock() (this=<optimized out>) at /home/emilio/src/moz/gecko-4/mozglue/misc/Mutex_posix.cpp:142
#9 0x00007fd190cc795a in mozilla::OffTheBooksMutex::Lock() (this=0x7fd136649398) at /home/emilio/src/moz/gecko-4/xpcom/threads/BlockingResourceBase.cpp:318
#10 0x00007fd19326e65e in mozilla::detail::BaseAutoLock<mozilla::Mutex&>::BaseAutoLock(mozilla::Mutex&) (this=<optimized out>, aLock=...) at /home/emilio/src/moz/gecko-4/obj-debug-no-sccache/dist/include/mozilla/Mutex.h:159
#11 mozilla::dom::GamepadPlatformService::NotifyGamepadChange<mozilla::dom::GamepadAdded>(unsigned int, mozilla::dom::GamepadAdded const&) (this=0x7fd136649380, aIndex=1, aInfo=...)
at /home/emilio/src/moz/gecko-4/dom/gamepad/GamepadPlatformService.cpp:65
#12 0x00007fd193269178 in mozilla::dom::GamepadPlatformService::AddGamepad(char const*, mozilla::dom::GamepadMappingType, mozilla::dom::GamepadHand, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
(this=0x7fd136649380, aID=<optimized out>, aMapping=mozilla::dom::GamepadMappingType::_empty, aHand=mozilla::dom::GamepadHand::_empty, aNumButtons=11, aNumAxes=8, aHaptics=0, aNumLightIndicator=0, aNumTouchEvents=0)
at /home/emilio/src/moz/gecko-4/dom/gamepad/GamepadPlatformService.cpp:96
#13 0x00007fd19326de4a in (anonymous namespace)::LinuxGamepadService::AddDevice(mozilla::udev_device*) (this=<optimized out>, dev=<optimized out>) at /home/emilio/src/moz/gecko-4/dom/gamepad/linux/LinuxGamepad.cpp:139
#14 0x00007fd19326a156 in (anonymous namespace)::LinuxGamepadService::ScanForDevices() (this=<optimized out>) at /home/emilio/src/moz/gecko-4/dom/gamepad/linux/LinuxGamepad.cpp:188
#15 (anonymous namespace)::LinuxGamepadService::Startup() (this=<optimized out>) at /home/emilio/src/moz/gecko-4/dom/gamepad/linux/LinuxGamepad.cpp:233
#16 mozilla::dom::StartGamepadMonitoring() () at /home/emilio/src/moz/gecko-4/dom/gamepad/linux/LinuxGamepad.cpp:334
#17 0x00007fd193269c6b in mozilla::dom::GamepadPlatformService::AddChannelParent(mozilla::dom::GamepadEventChannelParent*) (this=<optimized out>, aParent=<optimized out>)
at /home/emilio/src/moz/gecko-4/dom/gamepad/GamepadPlatformService.cpp:225
#18 0x00007fd19326d175 in mozilla::dom::GamepadEventChannelParent::Init() (this=0x7fd136e76a00) at /home/emilio/src/moz/gecko-4/dom/gamepad/ipc/GamepadEventChannelParent.cpp:50
#19 0x00007fd1913ba3a6 in mozilla::ipc::BackgroundParentImpl::RecvPGamepadEventChannelConstructor(mozilla::dom::PGamepadEventChannelParent*) (this=0x7fd13f888000, aActor=0x0)
at /home/emilio/src/moz/gecko-4/ipc/glue/BackgroundParentImpl.cpp:1109
#20 0x00007fd1917c7da1 in mozilla::ipc::PBackgroundParent::OnMessageReceived(IPC::Message const&) (this=0x7fd13f888000, msg__=...) at PBackgroundParent.cpp:4967
#21 0x00007fd1913ea71d in mozilla::ipc::MessageChannel::DispatchAsyncMessage(mozilla::ipc::ActorLifecycleProxy*, IPC::Message const&) (this=0x7fd13f8880f8, aProxy=0x7fd13ff48140, aMsg=...)
Differential Revision: https://phabricator.services.mozilla.com/D87967
2020-08-24 20:06:58 +03:00
|
|
|
}
|
2020-08-07 16:32:17 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
gGamepadPlatformServiceSingleton =
|
|
|
|
RefPtr<GamepadPlatformService>(new GamepadPlatformService{aParent});
|
2020-10-07 20:25:26 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
StartGamepadMonitoring();
|
2020-12-03 01:32:30 +03:00
|
|
|
GamepadMonitoringState::GetSingleton().Set(true);
|
2016-10-23 20:32:00 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
// static
|
2016-06-28 01:25:00 +03:00
|
|
|
void GamepadPlatformService::RemoveChannelParent(
|
|
|
|
GamepadEventChannelParent* aParent) {
|
|
|
|
// mChannelParents can only be modified once GamepadEventChannelParent
|
|
|
|
// is created or removed in Background thread
|
|
|
|
AssertIsOnBackgroundThread();
|
|
|
|
MOZ_ASSERT(aParent);
|
2020-12-03 01:36:35 +03:00
|
|
|
MOZ_ASSERT(gGamepadPlatformServiceSingleton);
|
2016-06-28 01:25:00 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
// RemoveChannelParentInternal will refuse to remove the last channel
|
|
|
|
// In that case, we should destroy the singleton
|
|
|
|
if (gGamepadPlatformServiceSingleton->RemoveChannelParentInternal(aParent)) {
|
|
|
|
return;
|
2020-08-07 16:32:17 +03:00
|
|
|
}
|
|
|
|
|
2020-12-03 01:32:30 +03:00
|
|
|
GamepadMonitoringState::GetSingleton().Set(false);
|
2020-08-07 16:27:55 +03:00
|
|
|
StopGamepadMonitoring();
|
2016-06-28 01:25:00 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
// At this point, any monitor threads should be stopped and the only
|
|
|
|
// reference to the singleton should be the global one
|
|
|
|
MOZ_RELEASE_ASSERT(gGamepadPlatformServiceSingleton->mRefCnt.get() == 1);
|
2016-06-28 01:25:00 +03:00
|
|
|
|
2020-12-03 01:36:35 +03:00
|
|
|
gGamepadPlatformServiceSingleton = nullptr;
|
2016-06-28 01:25:00 +03:00
|
|
|
}
|
|
|
|
|
2020-11-04 20:04:01 +03:00
|
|
|
} // namespace mozilla::dom
|