Bug 1603539 - Part 2: Sending telemetry via VR shared memory. r=kip,thomasmo,chutten

Differential Revision: https://phabricator.services.mozilla.com/D57378

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Daosheng Mu 2019-12-23 20:48:17 +00:00
parent 47d9630fe9
commit f61dc99e7b
9 changed files with 194 additions and 13 deletions

View File

@ -261,6 +261,13 @@ void VRManager::UpdateRequestedDevices() {
* at the VR display's native refresh rate.
**/
void VRManager::NotifyVsync(const TimeStamp& aVsyncTimestamp) {
#if defined(XP_WIN) && defined(NIGHTLY_BUILD)
// For Firefox Reality PC telemetry only.
if (PR_GetEnv("MOZ_FXR")) {
ProcessTelemetryEvent();
}
#endif
if (mState != VRManagerState::Active) {
return;
}
@ -420,6 +427,37 @@ void VRManager::Run100msTasks() {
CheckForShutdown();
}
void VRManager::ProcessTelemetryEvent() {
mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/);
MOZ_ASSERT(!shmem.HasExternalShmem());
if (shmem.JoinShMem()) {
mozilla::gfx::VRTelemetryState telemetryState = {0};
shmem.PullTelemetryState(telemetryState);
if (telemetryState.uid != 0) {
if (telemetryState.installedFrom) {
MOZ_ASSERT(telemetryState.installedFromValue <= 0x07,
"VRTelemetryId::INSTALLED_FROM only allows 3 bits.");
Telemetry::Accumulate(Telemetry::FXRPC_FF_INSTALLATION_FROM,
telemetryState.installedFromValue);
}
if (telemetryState.entryMethod) {
MOZ_ASSERT(telemetryState.entryMethodValue <= 0x07,
"VRTelemetryId::ENTRY_METHOD only allows 3 bits.");
Telemetry::Accumulate(Telemetry::FXRPC_ENTRY_METHOD,
telemetryState.entryMethodValue);
}
if (telemetryState.firstRun) {
Telemetry::ScalarSet(Telemetry::ScalarID::FXRPC_ISFIRSTRUN,
telemetryState.firstRunValue);
}
telemetryState = {0};
shmem.PushTelemetryState(telemetryState);
}
}
}
void VRManager::CheckForInactiveTimeout() {
// Shut down the VR devices when not in use
if (mVRDisplaysRequested || mVRDisplaysRequestedNonFocus ||

View File

@ -83,6 +83,7 @@ class VRManager : nsIObserver {
uint32_t GetOptimalTaskInterval();
void PullState(const std::function<bool()>& aWaitCondition = nullptr);
void PushState(const bool aNotifyCond = false);
void ProcessTelemetryEvent();
static uint32_t AllocateDisplayID();
void DispatchVRDisplayInfoUpdate();

View File

@ -629,6 +629,7 @@ void VRShMem::PushWindowState(VRWindowState& aState) {
}
#endif // defined(XP_WIN)
}
void VRShMem::PullWindowState(VRWindowState& aState) {
#if defined(XP_WIN)
if (!mExternalShmem) {
@ -645,6 +646,37 @@ void VRShMem::PullWindowState(VRWindowState& aState) {
#endif // defined(XP_WIN)
}
void VRShMem::PushTelemetryState(VRTelemetryState& aState) {
#if defined(XP_WIN)
if (!mExternalShmem) {
return;
}
bool status = true;
WaitForMutex lock(mMutex);
status = lock.GetStatus();
if (status) {
memcpy((void*)&(mExternalShmem->telemetryState), (void*)&aState,
sizeof(VRTelemetryState));
}
#endif // defined(XP_WIN)
}
void VRShMem::PullTelemetryState(VRTelemetryState& aState) {
#if defined(XP_WIN)
if (!mExternalShmem) {
return;
}
bool status = true;
WaitForMutex lock(mMutex);
status = lock.GetStatus();
if (status) {
memcpy((void*)&aState, (void*)&(mExternalShmem->telemetryState),
sizeof(VRTelemetryState));
}
#endif // defined(XP_WIN)
}
void VRShMem::SendEvent(uint64_t aWindowID,
mozilla::gfx::VRFxEventType aEventType,
mozilla::gfx::VRFxEventState aEventState) {

View File

@ -46,6 +46,9 @@ class VRShMem final {
void PushWindowState(VRWindowState& aState);
void PullWindowState(VRWindowState& aState);
void PushTelemetryState(VRTelemetryState& aState);
void PullTelemetryState(VRTelemetryState& aState);
void SendIMEState(uint64_t aWindowID, mozilla::gfx::VRFxEventState aImeState);
void SendFullscreenState(uint64_t aWindowID, bool aFullscreen);
void SendShutdowmState(uint64_t aWindowID);

View File

@ -47,8 +47,8 @@ namespace gfx {
// and mapped files if we have both release and nightlies
// running at the same time? Or...what if we have multiple
// release builds running on same machine? (Bug 1563232)
#define SHMEM_VERSION "0.0.6"
static const int32_t kVRExternalVersion = 13;
#define SHMEM_VERSION "0.0.7"
static const int32_t kVRExternalVersion = 14;
// We assign VR presentations to groups with a bitmask.
// Currently, we will only display either content or chrome.
@ -543,6 +543,41 @@ struct VRWindowState {
char signalName[32];
};
enum class VRTelemetryId : uint8_t {
NONE = 0,
INSTALLED_FROM = 1,
ENTRY_METHOD = 2,
FIRST_RUN = 3,
TOTAL = 4,
};
enum class VRTelemetryInstallFrom: uint8_t {
User = 0,
FxR = 1,
HTC = 2,
Valve = 3,
TOTAL = 4,
};
enum class VRTelemetryEntryMethod: uint8_t {
SystemBtn = 0,
Library = 1,
Gaze = 2,
TOTAL = 3,
};
struct VRTelemetryState {
uint32_t uid;
bool installedFrom : 1;
bool entryMethod : 1;
bool firstRun : 1;
uint8_t installedFromValue : 3;
uint8_t entryMethodValue : 3;
bool firstRunValue : 1;
};
struct VRExternalShmem {
int32_t version;
int32_t size;
@ -570,6 +605,7 @@ struct VRExternalShmem {
#endif // !defined(__ANDROID__)
#if defined(XP_WIN)
VRWindowState windowState;
VRTelemetryState telemetryState;
#endif
#ifdef MOZILLA_INTERNAL_API
void Clear() volatile {

View File

@ -12,3 +12,4 @@ EXPORTS
CloseVRWindow PRIVATE
SendUIMessageToVRWindow PRIVATE
WaitForVREvent PRIVATE
SendVRTelemetry PRIVATE

View File

@ -13,9 +13,21 @@
#include <stdio.h>
#include <string.h>
#include <random>
#include <queue>
#include "windows.h"
class VRShmemInstance {
public:
VRShmemInstance() = delete;
VRShmemInstance(const VRShmemInstance& aRHS) = delete;
static mozilla::gfx::VRShMem& GetInstance() {
static mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/);
return shmem;
}
};
// VRWindowManager adds a level of indirection so that system HWND isn't exposed
// outside of these APIs
class VRWindowManager {
@ -85,6 +97,62 @@ class VRWindowManager {
};
VRWindowManager* VRWindowManager::Instance = nullptr;
class VRTelemetryManager {
public:
void SendTelemetry(uint32_t aTelemetryId, uint32_t aValue) {
if (!aTelemetryId) {
return;
}
mozilla::gfx::VRTelemetryState telemetryState = {0};
VRShmemInstance::GetInstance().PullTelemetryState(telemetryState);
if (telemetryState.uid == 0) {
telemetryState.uid = sUid;
}
switch (mozilla::gfx::VRTelemetryId(aTelemetryId)) {
case mozilla::gfx::VRTelemetryId::INSTALLED_FROM:
MOZ_ASSERT(aValue <= 0x07,
"VRTelemetryId::INSTALLED_FROM only allows 3 bits.");
telemetryState.installedFrom = true;
telemetryState.installedFromValue = aValue;
break;
case mozilla::gfx::VRTelemetryId::ENTRY_METHOD:
MOZ_ASSERT(aValue <= 0x07,
"VRTelemetryId::ENTRY_METHOD only allows 3 bits.");
telemetryState.entryMethod = true;
telemetryState.entryMethodValue = aValue;
break;
case mozilla::gfx::VRTelemetryId::FIRST_RUN:
MOZ_ASSERT(aValue <= 0x01,
"VRTelemetryId::FIRST_RUN only allows 1 bit.");
telemetryState.firstRun = true;
telemetryState.firstRunValue = aValue;
break;
default:
MOZ_CRASH("Undefined VR telemetry type.");
break;
}
VRShmemInstance::GetInstance().PushTelemetryState(telemetryState);
++sUid;
}
static VRTelemetryManager* GetManager() {
if (Instance == nullptr) {
Instance = new VRTelemetryManager();
}
return Instance;
}
private:
static VRTelemetryManager* Instance;
static uint32_t sUid; // It starts from 1, Zero means the data is read yet
// from VRManager.
};
uint32_t VRTelemetryManager::sUid = 1;
VRTelemetryManager* VRTelemetryManager::Instance = nullptr;
// Struct to send params to StartFirefoxThreadProc
struct StartFirefoxParams {
char* firefoxFolder;
@ -130,17 +198,6 @@ DWORD StartFirefoxThreadProc(_In_ LPVOID lpParameter) {
return 0;
}
class VRShmemInstance {
public:
VRShmemInstance() = delete;
VRShmemInstance(const VRShmemInstance& aRHS) = delete;
static mozilla::gfx::VRShMem& GetInstance() {
static mozilla::gfx::VRShMem shmem(nullptr, true /*aRequiresMutex*/);
return shmem;
}
};
// This export is responsible for starting up a new VR window in Firefox and
// returning data related to its creation back to the caller.
// See nsFxrCommandLineHandler::Handle for more details about the bootstrapping
@ -305,4 +362,13 @@ void SendUIMessageToVRWindow(uint32_t nVRWindowID, uint32_t msg,
break;
}
}
}
void SendVRTelemetry(uint32_t nVRWindowID, uint32_t telemetryId,
uint32_t value) {
HWND hwnd = VRWindowManager::GetManager()->GetHWND(nVRWindowID);
if (hwnd == nullptr) {
return;
}
VRTelemetryManager::GetManager()->SendTelemetry(telemetryId, value);
}

View File

@ -28,3 +28,6 @@ typedef void (*PFN_SENDUIMSG)(uint32_t nVRWindowID, uint32_t msg,
typedef void (*PFN_WAITFORVREVENT)(uint32_t& nVRWindowID, uint32_t& eventType,
uint32_t& eventData1, uint32_t& eventData2);
typedef void (*PFN_SENDVRTELEMETRY)(uint32_t nVRWindowID, uint32_t telemetryId,
uint32_t value);

View File

@ -14,6 +14,7 @@ EXPORTS
CloseVRWindow PRIVATE
SendUIMessageToVRWindow PRIVATE
WaitForVREvent PRIVATE
SendVRTelemetry PRIVATE
;+= Exports only available in Nightlies for testing
SampleExport PRIVATE