mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Resolved the issue to monitor lock/unlock in platform SDK
PiperOrigin-RevId: 552655345
This commit is contained in:
committed by
Copybara-Service
parent
9d2cfc19c9
commit
868d3ce046
@@ -11,6 +11,7 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
cc_library(
|
||||
@@ -95,6 +96,7 @@ cc_library(
|
||||
"mutex.h",
|
||||
"scheduled_executor.h",
|
||||
"server_sync.h",
|
||||
"session_manager.h",
|
||||
"submittable_executor.h",
|
||||
"thread_pool.h",
|
||||
"webrtc.h",
|
||||
@@ -166,6 +168,7 @@ cc_library(
|
||||
"preferences_repository.cc",
|
||||
"preferences_repository.h",
|
||||
"scheduled_executor.cc",
|
||||
"session_manager.cc",
|
||||
"submittable_executor.cc",
|
||||
"system_clock.cc",
|
||||
"thread_pool.cc",
|
||||
|
||||
@@ -23,11 +23,14 @@
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/base/bluetooth_address.h"
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
#include "internal/platform/implementation/windows/session_manager.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "winrt/Windows.Foundation.Collections.h"
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
@@ -49,89 +52,10 @@ using IVectorView = winrt::Windows::Foundation::Collections::IVectorView<T>;
|
||||
template <typename T>
|
||||
using IAsyncOperation = winrt::Windows::Foundation::IAsyncOperation<T>;
|
||||
|
||||
constexpr char window_class_name[] = "NearbySharingDLL_MessageWindowClass";
|
||||
constexpr char window_name[] = "NearbySharingDLL_MessageWindow";
|
||||
constexpr char logs_relative_path[] = "Google\\Nearby\\Sharing\\Logs";
|
||||
constexpr char crash_dumps_relative_path[] =
|
||||
"Google\\Nearby\\Sharing\\CrashDumps";
|
||||
|
||||
namespace {
|
||||
// This WindowProc method must be static for the successful initialization of
|
||||
// WNDCLASS
|
||||
// window_class.lpfnWndProc = (WNDPROC) &DeviceInfo::WindowProc;
|
||||
// where a WNDPROC typed function pointer is expected
|
||||
// typedef LRESULT (CALLBACK* WNDPROC)(HWND,UINT,WPARAM,LPARAM)
|
||||
// the calling convention used here CALLBACK is a macro defined as
|
||||
// #define CALLBACK __stdcall
|
||||
//
|
||||
// If WindProc is not static and defined as a member function, it uses the
|
||||
// __thiscall calling convention instead
|
||||
// https://docs.microsoft.com/en-us/cpp/cpp/thiscall?view=msvc-170
|
||||
// https://isocpp.org/wiki/faq/pointers-to-members
|
||||
// https://en.cppreference.com/w/cpp/language/pointer
|
||||
//
|
||||
// This is problematic because the function pointer now looks like this
|
||||
// typedef LRESULT (CALLBACK* DeviceInfo_WNDPROC)(DeviceInfo*
|
||||
// this,HWND,UINT,WPARAM,LPARAM)
|
||||
// which causes casting errors
|
||||
LRESULT CALLBACK WindowProc(HWND window_handle, UINT message, WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
DeviceInfo* self = reinterpret_cast<DeviceInfo*>(
|
||||
GetWindowLongPtr(window_handle, GWLP_USERDATA));
|
||||
CREATESTRUCT* create_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
||||
LONG_PTR result = 0L;
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
self = reinterpret_cast<DeviceInfo*>(create_struct->lpCreateParams);
|
||||
self->message_window_handle_ = window_handle;
|
||||
|
||||
// Store pointer to the self to the window's user data.
|
||||
SetLastError(0);
|
||||
result = SetWindowLongPtr(window_handle, GWLP_USERDATA,
|
||||
reinterpret_cast<LONG_PTR>(self));
|
||||
if (result == 0 && GetLastError() != 0) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Error connecting message window to Nearby Sharing DLL.";
|
||||
}
|
||||
break;
|
||||
case WM_WTSSESSION_CHANGE:
|
||||
if (self) {
|
||||
switch (wparam) {
|
||||
case WTS_SESSION_LOCK:
|
||||
for (auto& listener : self->screen_locked_listeners_) {
|
||||
listener.second(api::DeviceInfo::ScreenStatus::
|
||||
kLocked); // Trigger registered callbacks
|
||||
}
|
||||
break;
|
||||
case WTS_SESSION_UNLOCK:
|
||||
for (auto& listener : self->screen_locked_listeners_) {
|
||||
listener.second(api::DeviceInfo::ScreenStatus::
|
||||
kUnlocked); // Trigger registered callbacks
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WM_DESTROY:
|
||||
SetLastError(0);
|
||||
result = SetWindowLongPtr(window_handle, GWLP_USERDATA, NULL);
|
||||
if (result == 0 && GetLastError() != 0) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Error disconnecting message window to Nearby Sharing DLL.";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(window_handle, message, wparam, lparam);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
DeviceInfo::~DeviceInfo() {
|
||||
UnregisterClass(MAKEINTATOM(registered_class_), instance_);
|
||||
}
|
||||
|
||||
std::optional<std::u16string> DeviceInfo::GetOsDeviceName() const {
|
||||
DWORD size = 0;
|
||||
|
||||
@@ -404,78 +328,29 @@ std::optional<std::filesystem::path> DeviceInfo::GetCrashDumpPath() const {
|
||||
}
|
||||
|
||||
bool DeviceInfo::IsScreenLocked() const {
|
||||
DWORD session_id = WTSGetActiveConsoleSessionId();
|
||||
WTS_INFO_CLASS wts_info_class = WTSSessionInfoEx;
|
||||
LPTSTR session_info_buffer = nullptr;
|
||||
DWORD session_info_buffer_size_bytes = 0;
|
||||
|
||||
WTSINFOEXW* wts_info = nullptr;
|
||||
LONG session_state = WTS_SESSIONSTATE_UNKNOWN;
|
||||
|
||||
if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
|
||||
wts_info_class, &session_info_buffer,
|
||||
&session_info_buffer_size_bytes)) {
|
||||
if (session_info_buffer_size_bytes > 0) {
|
||||
wts_info = (WTSINFOEXW*)session_info_buffer;
|
||||
if (wts_info->Level == 1) {
|
||||
session_state = wts_info->Data.WTSInfoExLevel1.SessionFlags;
|
||||
}
|
||||
}
|
||||
WTSFreeMemory(session_info_buffer);
|
||||
session_info_buffer = nullptr;
|
||||
}
|
||||
|
||||
return (session_state == WTS_SESSIONSTATE_LOCK);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
return session_manager_.IsScreenLocked();
|
||||
}
|
||||
|
||||
void DeviceInfo::RegisterScreenLockedListener(
|
||||
absl::string_view listener_name,
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> callback) {
|
||||
if (message_window_handle_ == nullptr) {
|
||||
instance_ = (HINSTANCE)GetModuleHandle(NULL);
|
||||
|
||||
WNDCLASS window_class;
|
||||
window_class.style = 0;
|
||||
window_class.lpfnWndProc = (WNDPROC)&WindowProc;
|
||||
window_class.cbClsExtra = 0;
|
||||
window_class.cbWndExtra = 0;
|
||||
window_class.hInstance = instance_;
|
||||
window_class.hIcon = nullptr;
|
||||
window_class.hCursor = nullptr;
|
||||
window_class.hbrBackground = nullptr;
|
||||
window_class.lpszMenuName = nullptr;
|
||||
window_class.lpszClassName = window_class_name;
|
||||
|
||||
registered_class_ = RegisterClass(&window_class);
|
||||
|
||||
message_window_handle_ = CreateWindow(
|
||||
MAKEINTATOM(registered_class_), // class atom from RegisterClass
|
||||
window_name, // window name
|
||||
0, // window style
|
||||
0, // initial x position of window
|
||||
0, // initial y position of window
|
||||
0, // width
|
||||
0, // height
|
||||
HWND_MESSAGE, // handle to the parent of window
|
||||
// (message-only window in this case)
|
||||
nullptr, // handle to a menu
|
||||
instance_, // handle to the instance of the module
|
||||
// associated to the window
|
||||
this); // pointer to be passed to the window for additional data
|
||||
|
||||
if (!message_window_handle_) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< __func__
|
||||
<< ": Failed to create message window for Nearby Sharing DLL.";
|
||||
}
|
||||
}
|
||||
|
||||
screen_locked_listeners_.emplace(listener_name, callback);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
session_manager_.RegisterSessionListener(
|
||||
listener_name,
|
||||
[callback = std::move(callback)](SessionManager::SessionState state) {
|
||||
if (state == SessionManager::SessionState::kLock) {
|
||||
callback(api::DeviceInfo::ScreenStatus::kLocked);
|
||||
} else if (state == SessionManager::SessionState::kUnlock) {
|
||||
callback(api::DeviceInfo::ScreenStatus::kUnlocked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void DeviceInfo::UnregisterScreenLockedListener(
|
||||
absl::string_view listener_name) {
|
||||
screen_locked_listeners_.erase(listener_name);
|
||||
absl::MutexLock lock(&mutex_);
|
||||
session_manager_.UnregisterSessionListener(listener_name);
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Google LLC
|
||||
// Copyright 2021-2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -15,25 +15,21 @@
|
||||
#ifndef PLATFORM_IMPL_WINDOWS_DEVICE_INFO_H_
|
||||
#define PLATFORM_IMPL_WINDOWS_DEVICE_INFO_H_
|
||||
|
||||
#include <guiddef.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/base/thread_annotations.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/device_info.h"
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
#include "internal/platform/implementation/windows/session_manager.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
class DeviceInfo : public api::DeviceInfo {
|
||||
public:
|
||||
~DeviceInfo() override;
|
||||
~DeviceInfo() override = default;
|
||||
|
||||
std::optional<std::u16string> GetOsDeviceName() const override;
|
||||
api::DeviceInfo::DeviceType GetDeviceType() const override;
|
||||
@@ -55,13 +51,10 @@ class DeviceInfo : public api::DeviceInfo {
|
||||
absl::string_view listener_name,
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> callback) override;
|
||||
void UnregisterScreenLockedListener(absl::string_view listener_name) override;
|
||||
absl::flat_hash_map<std::string,
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)>>
|
||||
screen_locked_listeners_;
|
||||
|
||||
HINSTANCE instance_ = nullptr;
|
||||
ATOM registered_class_ = NULL;
|
||||
HWND message_window_handle_ = nullptr;
|
||||
private:
|
||||
mutable absl::Mutex mutex_;
|
||||
SessionManager session_manager_ ABSL_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -77,61 +77,6 @@ TEST(DeviceInfo, DISABLED_IsScreenLocked) {
|
||||
EXPECT_FALSE(DeviceInfo().IsScreenLocked());
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_RegisterScreenLockedListener) {
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> listener_1 =
|
||||
[](api::DeviceInfo::ScreenStatus) {};
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> listener_2 =
|
||||
[](api::DeviceInfo::ScreenStatus) {};
|
||||
|
||||
DeviceInfo device_info;
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 0);
|
||||
|
||||
device_info.RegisterScreenLockedListener("listener_1", listener_1);
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 1);
|
||||
|
||||
device_info.RegisterScreenLockedListener("listener_2", listener_2);
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 2);
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_UnregisterScreenLockedListener) {
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> listener_1 =
|
||||
[](api::DeviceInfo::ScreenStatus) {};
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> listener_2 =
|
||||
[](api::DeviceInfo::ScreenStatus) {};
|
||||
|
||||
DeviceInfo device_info;
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 0);
|
||||
|
||||
device_info.RegisterScreenLockedListener("listener_1", listener_1);
|
||||
device_info.RegisterScreenLockedListener("listener_2", listener_2);
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 2);
|
||||
|
||||
device_info.UnregisterScreenLockedListener("listener_1");
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 1);
|
||||
|
||||
device_info.UnregisterScreenLockedListener("listener_2");
|
||||
EXPECT_EQ(device_info.screen_locked_listeners_.size(), 0);
|
||||
}
|
||||
|
||||
TEST(DeviceInfo, DISABLED_UpdateScreenLockedListener) {
|
||||
absl::Notification notification;
|
||||
|
||||
api::DeviceInfo::ScreenStatus screen_locked_tracker =
|
||||
api::DeviceInfo::ScreenStatus::kUndetermined;
|
||||
|
||||
std::function<void(api::DeviceInfo::ScreenStatus)> listener =
|
||||
[&screen_locked_tracker,
|
||||
¬ification](api::DeviceInfo::ScreenStatus status) {
|
||||
screen_locked_tracker = api::DeviceInfo::ScreenStatus::kLocked;
|
||||
notification.Notify();
|
||||
};
|
||||
|
||||
DeviceInfo device_info;
|
||||
device_info.RegisterScreenLockedListener("listener", listener);
|
||||
EXPECT_TRUE(notification.WaitForNotificationWithTimeout(absl::Seconds(5)));
|
||||
EXPECT_EQ(screen_locked_tracker, api::DeviceInfo::ScreenStatus::kLocked);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "internal/platform/implementation/windows/session_manager.h"
|
||||
|
||||
#include <Windows.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/base/attributes.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
#include "internal/platform/implementation/windows/submittable_executor.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
namespace {
|
||||
|
||||
constexpr char kMessageWindowClass[] = "Nearby Message Window Class";
|
||||
constexpr char kMessageWindowTitle[] = "Nearby Message Dummy Window";
|
||||
|
||||
// Define global static variables.
|
||||
ABSL_CONST_INIT absl::Mutex kSessionMutex(absl::kConstInit);
|
||||
HWND kSessionHwnd = nullptr;
|
||||
SubmittableExecutor* kSessionThread = nullptr;
|
||||
absl::flat_hash_map<std::string,
|
||||
absl::AnyInvocable<void(SessionManager::SessionState)>>*
|
||||
kSessionCallbacks = nullptr;
|
||||
|
||||
LRESULT CALLBACK NearbyWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
switch (uMsg) {
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
return 0;
|
||||
case WM_WTSSESSION_CHANGE:
|
||||
if (wParam == WTS_SESSION_LOCK) {
|
||||
absl::MutexLock lock(&kSessionMutex);
|
||||
for (auto& it : *kSessionCallbacks) {
|
||||
it.second(SessionManager::SessionState::kLock);
|
||||
}
|
||||
} else if (wParam == WTS_SESSION_UNLOCK) {
|
||||
absl::MutexLock lock(&kSessionMutex);
|
||||
for (auto& it : *kSessionCallbacks) {
|
||||
it.second(SessionManager::SessionState::kUnlock);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
default:
|
||||
return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
||||
}
|
||||
}
|
||||
|
||||
HWND CreateNearbyWindow() {
|
||||
HINSTANCE instance = (HINSTANCE)GetModuleHandle(nullptr);
|
||||
|
||||
WNDCLASS window_class = {};
|
||||
window_class.lpfnWndProc = NearbyWindowProc;
|
||||
window_class.hInstance = instance;
|
||||
window_class.lpszClassName = kMessageWindowClass;
|
||||
|
||||
RegisterClass(&window_class);
|
||||
|
||||
HWND hwnd =
|
||||
CreateWindowA(kMessageWindowClass, kMessageWindowTitle, /*dwStyle=*/0,
|
||||
/*X=*/0, /*Y=*/0, /*nWidth=*/0, /*nHeight=*/0, HWND_MESSAGE,
|
||||
/*hMenu=*/nullptr, instance,
|
||||
/*lpParam=*/nullptr);
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SessionManager::~SessionManager() { StopSession(); }
|
||||
|
||||
bool SessionManager::RegisterSessionListener(
|
||||
absl::string_view listener_name,
|
||||
absl::AnyInvocable<void(SessionState)> callback) {
|
||||
absl::MutexLock lock(&kSessionMutex);
|
||||
|
||||
// Create session thread if no running thread.
|
||||
if (kSessionThread == nullptr) {
|
||||
absl::Notification notification;
|
||||
kSessionThread = new SubmittableExecutor();
|
||||
kSessionCallbacks = new absl::flat_hash_map<
|
||||
std::string, absl::AnyInvocable<void(SessionManager::SessionState)>>();
|
||||
kSessionThread->Execute(
|
||||
[this, ¬ification]() { StartSession(notification); });
|
||||
notification.WaitForNotification();
|
||||
if (kSessionThread == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (kSessionCallbacks->contains(listener_name) ||
|
||||
listeners_.contains(listener_name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
kSessionCallbacks->emplace(listener_name, std::move(callback));
|
||||
listeners_.emplace(listener_name);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionManager::UnregisterSessionListener(
|
||||
absl::string_view listener_name) {
|
||||
absl::MutexLock lock(&kSessionMutex);
|
||||
if (kSessionThread == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": No running listener.";
|
||||
return false;
|
||||
}
|
||||
if (!kSessionCallbacks->contains(listener_name) ||
|
||||
!listeners_.contains(listener_name)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": No listener with name:" << listener_name;
|
||||
return false;
|
||||
}
|
||||
kSessionCallbacks->erase(listener_name);
|
||||
listeners_.erase(listener_name);
|
||||
|
||||
if (!kSessionCallbacks->empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CleanUp();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SessionManager::IsScreenLocked() const {
|
||||
DWORD session_id = WTSGetActiveConsoleSessionId();
|
||||
WTS_INFO_CLASS wts_info_class = WTSSessionInfoEx;
|
||||
LPTSTR session_info_buffer = nullptr;
|
||||
DWORD session_info_buffer_size_bytes = 0;
|
||||
|
||||
WTSINFOEXW* wts_info = nullptr;
|
||||
LONG session_state = WTS_SESSIONSTATE_UNKNOWN;
|
||||
|
||||
if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_id,
|
||||
wts_info_class, &session_info_buffer,
|
||||
&session_info_buffer_size_bytes)) {
|
||||
if (session_info_buffer_size_bytes > 0) {
|
||||
wts_info = (WTSINFOEXW*)session_info_buffer;
|
||||
if (wts_info->Level == 1) {
|
||||
session_state = wts_info->Data.WTSInfoExLevel1.SessionFlags;
|
||||
}
|
||||
}
|
||||
WTSFreeMemory(session_info_buffer);
|
||||
session_info_buffer = nullptr;
|
||||
}
|
||||
|
||||
return (session_state == WTS_SESSIONSTATE_LOCK);
|
||||
}
|
||||
|
||||
void SessionManager::StartSession(absl::Notification& notification) {
|
||||
kSessionHwnd = CreateNearbyWindow();
|
||||
if (kSessionHwnd == nullptr) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to create session Window.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!WTSRegisterSessionNotification(kSessionHwnd, NOTIFY_FOR_THIS_SESSION)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ":Failed to register session notification.";
|
||||
return;
|
||||
}
|
||||
|
||||
notification.Notify();
|
||||
|
||||
// Main message loop
|
||||
MSG msg = {};
|
||||
while (GetMessage(&msg, nullptr, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
|
||||
if (!WTSUnRegisterSessionNotification(kSessionHwnd)) {
|
||||
NEARBY_LOGS(ERROR) << __func__
|
||||
<< ": Failed to register session notification.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UnregisterClassA(/*lpClassName=*/kMessageWindowClass,
|
||||
/*hInstance=*/(HINSTANCE)GetModuleHandle(nullptr))) {
|
||||
NEARBY_LOGS(ERROR) << __func__ << ": Failed to unregister window class.";
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Completed Message loop.";
|
||||
}
|
||||
|
||||
void SessionManager::StopSession() {
|
||||
absl::MutexLock lock(&kSessionMutex);
|
||||
if (kSessionThread == nullptr) {
|
||||
return;
|
||||
}
|
||||
for (const auto& it : listeners_) {
|
||||
kSessionCallbacks->erase(it);
|
||||
}
|
||||
|
||||
listeners_.clear();
|
||||
if (!kSessionCallbacks->empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
void SessionManager::CleanUp() {
|
||||
if (kSessionHwnd != nullptr) {
|
||||
// Send message to destroy message window.
|
||||
PostMessageA(kSessionHwnd, WM_DESTROY, 0, 0);
|
||||
}
|
||||
|
||||
kSessionThread->Shutdown();
|
||||
delete kSessionThread;
|
||||
delete kSessionCallbacks;
|
||||
kSessionThread = nullptr;
|
||||
kSessionCallbacks = nullptr;
|
||||
kSessionHwnd = nullptr;
|
||||
}
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_SESSION_MANAGER_H_
|
||||
#define THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_SESSION_MANAGER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/functional/any_invocable.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/synchronization/notification.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace windows {
|
||||
|
||||
// SessionManager provides methods to access/control platform session.
|
||||
class SessionManager {
|
||||
public:
|
||||
enum class SessionState { kLock, kUnlock };
|
||||
~SessionManager();
|
||||
|
||||
// Setups session listener.
|
||||
// listener_name - Listener name. it should be unique in the SDK level.
|
||||
// callback - It will be called when session state changed, such as
|
||||
// lock/unlock screen.
|
||||
bool RegisterSessionListener(absl::string_view listener_name,
|
||||
absl::AnyInvocable<void(SessionState)> callback);
|
||||
|
||||
// Removes session listener by its name.
|
||||
bool UnregisterSessionListener(absl::string_view listener_name);
|
||||
|
||||
bool IsScreenLocked() const;
|
||||
|
||||
private:
|
||||
void StartSession(absl::Notification& notification);
|
||||
void StopSession();
|
||||
void CleanUp();
|
||||
|
||||
absl::flat_hash_set<std::string> listeners_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_INTERNAL_PLATFORM_IMPLEMENTATION_WINDOWS_SESSION_MANAGER_H_
|
||||
Reference in New Issue
Block a user