// Copyright 2022-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_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_ #define THIRD_PARTY_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_ #include #include #include #include #include #include #include #include #include #include #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "absl/types/span.h" #include "internal/platform/clock.h" #include "internal/platform/device_info.h" #include "internal/platform/implementation/account_manager.h" #include "internal/platform/task_runner.h" #include "proto/sharing_enums.pb.h" #include "sharing/advertisement.h" #include "sharing/analytics/analytics_recorder.h" #include "sharing/attachment_container.h" #include "sharing/certificates/nearby_share_certificate_manager.h" #include "sharing/certificates/nearby_share_decrypted_public_certificate.h" #include "sharing/certificates/nearby_share_private_certificate.h" #include "sharing/common/nearby_share_enums.h" #include "sharing/fast_initiation/nearby_fast_initiation.h" #include "sharing/incoming_share_session.h" #include "sharing/internal/api/app_info.h" #include "sharing/internal/api/bluetooth_adapter.h" #include "sharing/internal/api/preference_manager.h" #include "sharing/internal/api/sharing_platform.h" #include "sharing/internal/api/sharing_rpc_client.h" #include "sharing/internal/public/connectivity_manager.h" #include "sharing/internal/public/context.h" #include "sharing/local_device_data/nearby_share_local_device_data_manager.h" #include "sharing/nearby_connection.h" #include "sharing/nearby_connections_manager.h" #include "sharing/nearby_connections_types.h" #include "sharing/nearby_file_handler.h" #include "sharing/nearby_sharing_service.h" #include "sharing/nearby_sharing_service_extension.h" #include "sharing/nearby_sharing_settings.h" #include "sharing/outgoing_share_session.h" #include "sharing/outgoing_targets_manager.h" #include "sharing/paired_key_verification_runner.h" #include "sharing/proto/enums.pb.h" #include "sharing/proto/wire_format.pb.h" #include "sharing/service_observers.h" #include "sharing/share_session.h" #include "sharing/share_target.h" #include "sharing/share_target_discovered_callback.h" #include "sharing/thread_timer.h" #include "sharing/transfer_metadata.h" #include "sharing/transfer_update_callback.h" #include "sharing/wrapped_share_target_discovered_callback.h" namespace nearby::sharing { class NearbyShareContactManager; namespace NearbySharingServiceUnitTests { class NearbySharingServiceImplTest_CreateShareTarget_Test; class NearbySharingServiceImplTest_RemoveIncomingPayloads_Test; }; // namespace NearbySharingServiceUnitTests // All methods should be called from the same sequence that created the service. class NearbySharingServiceImpl : public NearbySharingService, public NearbyShareSettings::Observer, public NearbyShareCertificateManager::Observer, public ::nearby::AccountManager::Observer, public NearbyFastInitiation::Observer, public sharing::api::BluetoothAdapter::Observer, public NearbyConnectionsManager::IncomingConnectionListener, public NearbyConnectionsManager::DiscoveryListener { FRIEND_TEST(NearbySharingServiceUnitTests::NearbySharingServiceImplTest, CreateShareTarget); FRIEND_TEST(NearbySharingServiceUnitTests::NearbySharingServiceImplTest, RemoveIncomingPayloads); public: NearbySharingServiceImpl( std::unique_ptr service_thread, Context* context, nearby::sharing::api::SharingPlatform& sharing_platform, std::unique_ptr nearby_connections_manager, analytics::AnalyticsRecorder* analytics_recorder); ~NearbySharingServiceImpl() override; // NearbySharingService void AddObserver(NearbySharingService::Observer* observer) override; void RemoveObserver(NearbySharingService::Observer* observer) override; void Shutdown( std::function status_codes_callback) override; void RegisterSendSurface( TransferUpdateCallback* transfer_callback, ShareTargetDiscoveredCallback* discovery_callback, SendSurfaceState state, Advertisement::BlockedVendorId blocked_vendor_id, bool disable_wifi_hotspot, std::function status_codes_callback) override; void UnregisterSendSurface( TransferUpdateCallback* transfer_callback, std::function status_codes_callback) override; void RegisterReceiveSurface( TransferUpdateCallback* transfer_callback, ReceiveSurfaceState state, Advertisement::BlockedVendorId vendor_id, std::function status_codes_callback) override; void UnregisterReceiveSurface( TransferUpdateCallback* transfer_callback, std::function status_codes_callback) override; void ClearForegroundReceiveSurfaces( std::function status_codes_callback) override; bool IsTransferring() const override; bool IsScanning() const override; bool IsBluetoothPresent() const override; bool IsBluetoothPowered() const override; bool IsExtendedAdvertisingSupported() const override; bool IsLanConnected() const override; std::string GetQrCodeUrl() const override; void SendAttachments( int64_t share_target_id, std::unique_ptr attachment_container, std::function status_codes_callback) override; void Accept(int64_t share_target_id, std::function status_codes_callback) override; void Reject(int64_t share_target_id, std::function status_codes_callback) override; void Cancel(int64_t share_target_id, std::function status_codes_callback) override; void SetVisibility( proto::DeviceVisibility visibility, absl::Duration expiration, absl::AnyInvocable callback) override; NearbyShareSettings* GetSettings() override; NearbyShareLocalDeviceDataManager* GetLocalDeviceDataManager() override; NearbyShareContactManager* GetContactManager() override; NearbyShareCertificateManager* GetCertificateManager() override; AccountManager* GetAccountManager() override; Clock& GetClock() override { return *context_->GetClock(); } void SetAlternateServiceUuidForDiscovery( uint16_t alternate_service_uuid) override { alternate_service_uuid_ = alternate_service_uuid; } // NearbyConnectionsManager::IncomingConnectionListener: void OnIncomingConnection(absl::string_view endpoint_id, absl::Span endpoint_info, NearbyConnection* connection) override; std::string Dump() const override; void UpdateFilePathsInProgress(bool update) override; private: // Internal implementation of methods to avoid using recursive mutex. StatusCodes InternalUnregisterSendSurface( TransferUpdateCallback* transfer_callback); StatusCodes InternalUnregisterReceiveSurface( TransferUpdateCallback* transfer_callback); // NearbyShareSettings::Observer: void OnSettingChanged(absl::string_view key, const Data& data) override; void OnIsFastInitiationHardwareSupportedChanged(bool is_supported) override {} void OnDeviceNameChanged(absl::string_view device_name); void OnDataUsageChanged(proto::DataUsage data_usage); void OnCustomSavePathChanged(absl::string_view custom_save_path); void OnVisibilityChanged(proto::DeviceVisibility visibility); // NearbyShareCertificateManager::Observer: void OnPublicCertificatesDownloaded() override; void OnPrivateCertificatesChanged() override; // AccountManager::Observer: void OnLoginSucceeded(absl::string_view account_id) override; void OnLogoutSucceeded(absl::string_view account_id, bool credential_error) override; // NearbyConnectionsManager::DiscoveryListener: void OnEndpointDiscovered(absl::string_view endpoint_id, absl::Span endpoint_info) override; void OnEndpointLost(absl::string_view endpoint_id) override; // Handle the state changes of screen lock. void OnLockStateChanged(bool locked); // Handle the state changes of bluetooth adapter. void AdapterPresentChanged(sharing::api::BluetoothAdapter* adapter, bool present) override; void AdapterPoweredChanged(sharing::api::BluetoothAdapter* adapter, bool powered) override; // Handle the hardware error reported that requires PC restart. void HardwareErrorReported(NearbyFastInitiation* fast_init) override; void SetupBluetoothAdapter(); absl::flat_hash_map& GetReceiveCallbacksMapFromState(ReceiveSurfaceState state); // Retrieves the current receiving vendor ID, defaulting to kNone if no // surface has been registered with a different vendor ID. This function will // always return one vendor ID, preferring a foreground surface vendor ID if // available. Advertisement::BlockedVendorId GetReceivingVendorId() const; // Retrieves the current sending vendor ID, defaulting to kNone if no // surface has been registered with a different vendor ID. This function will // always return one vendor ID, preferring a foreground surface vendor ID if // available. Advertisement::BlockedVendorId GetSendingVendorId() const; // Returns true if any foreground send surfaces has requested to disable wifi // hotspot. bool GetDisableWifiHotspotState() const; bool IsVisibleInBackground(proto::DeviceVisibility visibility); std::optional> CreateEndpointInfo( proto::DeviceVisibility visibility, const std::optional& device_name) const; void StartFastInitiationAdvertising(); void OnStartFastInitiationAdvertising(); void OnStartFastInitiationAdvertisingError(); void StopFastInitiationAdvertising(); void OnStopFastInitiationAdvertising(); // Processes endpoint discovered/lost events. We queue up the events to ensure // each discovered or lost event is fully handled before the next is run. For // example, we don't want to start processing an endpoint-lost event before // the corresponding endpoint-discovered event is finished. This is especially // important because of the asynchronous steps required to process an // endpoint-discovered event. void AddEndpointDiscoveryEvent(std::function event); void HandleEndpointDiscovered(absl::Time start_time, absl::string_view endpoint_id, absl::Span endpoint_info); void HandleEndpointLost(absl::string_view endpoint_id); void FinishEndpointDiscoveryEvent(); void OnOutgoingDecryptedCertificate( absl::string_view endpoint_id, absl::Span endpoint_info, const Advertisement& advertisement, std::optional certificate); void ScheduleCertificateDownloadDuringDiscovery(size_t attempt_count); void OnCertificateDownloadDuringDiscoveryTimerFired(size_t attempt_count); bool HasAvailableConnectionMediums(); void InvalidateSurfaceState(); void InvalidateSendSurfaceState(); void InvalidateScanningState(); void InvalidateFastInitiationAdvertising(); void InvalidateReceiveSurfaceState(); void InvalidateAdvertisingState(); void StopAdvertising(); void StartScanning(); StatusCodes StopScanning(); void StopAdvertisingAndInvalidateSurfaceState(); void InvalidateFastInitiationScanning(); void StartFastInitiationScanning(); void OnFastInitiationDevicesNotDetected(); void StopFastInitiationScanning(); void ScheduleRotateBackgroundAdvertisementTimer(); void OnRotateBackgroundAdvertisementTimerFired(); void OnTransferComplete(); void OnTransferStarted(bool is_incoming); void OnOutgoingConnection(int64_t share_target_id, absl::string_view endpoint_id, NearbyConnection* connection, Status status); void CreatePayloads( OutgoingShareSession& session, std::function callback); void OnCreatePayloads(std::vector endpoint_info, OutgoingShareSession& session, bool success); void Fail(IncomingShareSession& session, TransferMetadata::Status status); void OnIncomingAdvertisementDecoded( absl::string_view endpoint_id, IncomingShareSession& session, std::unique_ptr advertisement); void OnIncomingTransferUpdate(const IncomingShareSession& session, const TransferMetadata& metadata); void OnOutgoingTransferUpdate(OutgoingShareSession& session, const TransferMetadata& metadata); void CloseConnection(absl::string_view endpoint_id); void OnIncomingDecryptedCertificate( absl::string_view endpoint_id, const Advertisement& advertisement, int64_t placeholder_share_target_id, std::optional certificate); void OnIncomingConnectionKeyVerificationDone( int64_t share_target_id, PairedKeyVerificationRunner::PairedKeyVerificationResult result, ::location::nearby::proto::sharing::OSType share_target_os_type); void OnOutgoingConnectionKeyVerificationDone( int64_t share_target_id, PairedKeyVerificationRunner::PairedKeyVerificationResult result, ::location::nearby::proto::sharing::OSType share_target_os_type); void OnReceivedIntroduction( int64_t share_target_id, std::optional frame); void OnReceiveConnectionResponse( int64_t share_target_id, std::optional frame); void OnStorageCheckCompleted(IncomingShareSession& session); void OnFrameRead( int64_t share_target_id, std::optional frame); void OnConnectionDisconnected(int64_t share_target_id); void Cleanup(); std::optional CreateShareTarget( absl::string_view endpoint_id, const Advertisement& advertisement, const std::optional& certificate, bool is_incoming); void OnIncomingPayloadTransferUpdates(int64_t share_target_id); void OnOutgoingPayloadTransferUpdates(int64_t share_target_id); void RemoveIncomingPayloads(const IncomingShareSession& session); IncomingShareSession& CreateIncomingShareSession( const ShareTarget& share_target, absl::string_view endpoint_id, std::optional certificate); ShareSession* GetShareSession(int64_t share_target_id); IncomingShareSession* GetIncomingShareSession(int64_t share_target_id); std::optional> GetBluetoothMacAddressForShareTarget( OutgoingShareSession& session); void UnregisterShareTarget(int64_t share_target_id); void OnStartAdvertisingResult(bool used_device_name, Status status); void OnStopAdvertisingResult(Status status); void OnStartDiscoveryResult(Status status); void SetInHighVisibility(bool in_high_visibility); // Note: |share_target| is intentionally passed by value. A share target // reference could likely be invalidated by the owner during the multistep // cancellation process. void DoCancel( int64_t share_target_id, std::function status_codes_callback, bool is_initiator_of_cancellation); // Monitor connectivity changes. void OnNetworkChanged(nearby::ConnectivityManager::ConnectionType type); void OnLanConnectedChanged(bool connected); // Resets all settings of the nearby sharing service. // Resets user preferences to a valid logged out state when |logout| is true. // This will clear all preferences, but preserve onboarding state and revert // visibility to a state that is valid when logged out. For example: // `contacts` -> `off`. void ResetAllSettings(bool logout); // Runs API/task on the service thread to avoid UI block. void RunOnNearbySharingServiceThread(absl::string_view task_name, absl::AnyInvocable task); // Runs API/task on the service thread with delayed time. void RunOnNearbySharingServiceThreadDelayed(absl::string_view task_name, absl::Duration delay, absl::AnyInvocable task); // Update file path for the file attachment. void UpdateFilePath(AttachmentContainer& container); // Returns true if Shutdown() has been called. bool IsShuttingDown(); // Send initial adapter state to observer for each supported adapter. void SendInitialAdapterState(NearbySharingService::Observer* observer); bool OutgoingSessionAccept(OutgoingShareSession& session); void OnIncomingFilesMetadataUpdated(int64_t share_target_id, TransferMetadata metadata, bool success); // Notify all registered send surfaces of share target state changes. void NotifyShareTargetDiscovered(const ShareTarget& share_target); void NotifyShareTargetUpdated(const ShareTarget& share_target); void NotifyShareTargetLost(const ShareTarget& share_target); // Log analytics event of discovering share target. void LogShareTargetDiscovered(const ShareTarget& share_target); // Used to run nearby sharing service APIs. std::unique_ptr service_thread_; Context* const context_; nearby::DeviceInfo& device_info_; nearby::sharing::api::PreferenceManager& preference_manager_; AccountManager& account_manager_; // Used to create analytics events. analytics::AnalyticsRecorder& analytics_recorder_; std::unique_ptr nearby_connections_manager_; std::unique_ptr nearby_share_client_factory_; std::unique_ptr local_device_data_manager_; std::unique_ptr contact_manager_; std::unique_ptr certificate_manager_; std::unique_ptr nearby_fast_initiation_; // Used to maintain the settings of nearby sharing. std::unique_ptr settings_; // Accesses the extension methods to Nearby Sharing service. std::unique_ptr service_extension_; NearbyFileHandler file_handler_; bool is_screen_locked_ = false; std::unique_ptr rotate_background_advertisement_timer_; std::unique_ptr certificate_download_during_discovery_timer_; // A list of service observers. ServiceObservers service_observers_; // A map of foreground receiver callbacks -> vendor ID. absl::flat_hash_map foreground_receive_callbacks_map_; // A map of background receiver callbacks -> vendor ID. absl::flat_hash_map background_receive_callbacks_map_; // A mapping of foreground transfer callbacks to foreground send surface data. absl::flat_hash_map foreground_send_surface_map_; // A mapping of background transfer callbacks to background send surface data. absl::flat_hash_map background_send_surface_map_; // Registers the most recent TransferMetadata and ShareTarget used for // transitioning notifications between foreground surfaces and background // surfaces. Empty if no metadata is available. std::optional> last_incoming_metadata_; // The most recent outgoing TransferMetadata and ShareTarget. std::optional> last_outgoing_metadata_; // A map of ShareTarget id to IncomingShareSession. This lets us know which // Nearby Connections endpoint and public certificate are related to the // incoming share target. absl::flat_hash_map incoming_share_session_map_; // A map from endpoint ID to endpoint info from discovered, contact-based // advertisements that could not decrypt any available public certificates. // During discovery, if certificates are downloaded, we revisit this map and // retry certificate decryption. absl::flat_hash_map> discovered_advertisements_to_retry_map_; // If the discovered advertisements are retried when public certificates // downloaded, we put it in to the retry set. The retried endpoints will not // cause new download of public certificates. The purpose is to reduce the // unnecessary backend API call. absl::flat_hash_set discovered_advertisements_retried_set_; // The current advertising power level. PowerLevel::kUnknown while not // advertising. PowerLevel advertising_power_level_ = PowerLevel::kUnknown; // True if we are currently scanning for remote devices. std::atomic_bool is_scanning_{false}; // True if we're currently sending or receiving a file. std::atomic_bool is_transferring_{false}; // True if we're currently receiving a file. std::atomic_bool is_receiving_files_{false}; // True if we're currently sending a file. std::atomic_bool is_sending_files_{false}; // True if we're currently attempting to connect to a remote device. std::atomic_bool is_connecting_{false}; // The time scanning began. absl::Time scanning_start_timestamp_; // True when we are advertising with a device name visible to everyone. std::atomic_bool in_high_visibility_{false}; // Used to debounce OnNetworkChanged processing. std::unique_ptr on_network_changed_delay_timer_; // Used to prevent the "Device nearby is sharing" notification from appearing // immediately after a completed share. std::unique_ptr fast_initiation_scanner_cooldown_timer_; // A queue of endpoint-discovered and endpoint-lost events that ensures the // events are processed sequentially, in the order received from Nearby // Connections. An event is processed either immediately, if there are no // other events in the queue, or as soon as the previous event processing // finishes. When processing finishes, the event is removed from the queue. std::queue> endpoint_discovery_events_; // Shouldn't schedule new task after shutting down, and skip task if the // object is null. std::shared_ptr is_shutting_down_ = nullptr; // Used to identify current scanning session. int64_t scanning_session_id_ = 0; // Used to identify current advertising session. int64_t advertising_session_id_ = 0; // Used to track the time of screen unlock. absl::Time screen_unlock_time_; // Whether to update the file paths in transfer progress. bool update_file_paths_in_progress_ = false; // Used to track the time when share sheet activity starts absl::Time share_foreground_send_surface_start_timestamp_; std::unique_ptr app_info_; std::optional alternate_service_uuid_; // If true, a new endpoint id will be generated at the next advertisement. bool force_new_endpoint_id_ = false; OutgoingTargetsManager outgoing_targets_manager_; }; } // namespace nearby::sharing #endif // THIRD_PARTY_NEARBY_SHARING_NEARBY_SHARING_SERVICE_IMPL_H_