From 18696f2ad257cb96cf8271be11e9580864bb7633 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Fri, 9 Mar 2018 22:14:05 +0100 Subject: [PATCH] Fix background task usage when receiving a REFER to join a chatroom. Add a timeout, because on Android wake locks have no limit in time. The timeout will secure that whatever happens, the wake lock is always released after a reasonable time. --- src/call/call.cpp | 3 +- src/chat/chat-room/client-group-chat-room-p.h | 1 - src/chat/chat-room/client-group-chat-room.cpp | 21 ++++++------- .../file-transfer-chat-message-modifier.cpp | 5 ++- src/utils/background-task.cpp | 31 ++++++++++++++++--- src/utils/background-task.h | 23 ++++++++++---- 6 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/call/call.cpp b/src/call/call.cpp index 797eee31a..f7b915a54 100644 --- a/src/call/call.cpp +++ b/src/call/call.cpp @@ -198,7 +198,8 @@ void CallPrivate::onAckReceived (const shared_ptr &session, Linphon } void CallPrivate::onBackgroundTaskToBeStarted (const shared_ptr &session) { - bgTask.start(); + L_Q(); + bgTask.start(q->getCore(),30); } void CallPrivate::onBackgroundTaskToBeStopped (const shared_ptr &session) { diff --git a/src/chat/chat-room/client-group-chat-room-p.h b/src/chat/chat-room/client-group-chat-room-p.h index cb62f6800..e617b517d 100644 --- a/src/chat/chat-room/client-group-chat-room-p.h +++ b/src/chat/chat-room/client-group-chat-room-p.h @@ -53,7 +53,6 @@ private: ClientGroupChatRoom::CapabilitiesMask capabilities = ClientGroupChatRoom::Capabilities::Conference; bool deletionOnTerminationEnabled = false; BackgroundTask bgTask; - L_DECLARE_PUBLIC(ClientGroupChatRoom); }; diff --git a/src/chat/chat-room/client-group-chat-room.cpp b/src/chat/chat-room/client-group-chat-room.cpp index e40482457..370d2b4a9 100644 --- a/src/chat/chat-room/client-group-chat-room.cpp +++ b/src/chat/chat-room/client-group-chat-room.cpp @@ -139,8 +139,10 @@ void ClientGroupChatRoomPrivate::onCallSessionStateChanged ( if (q->getState() == ChatRoom::State::CreationPending) { IdentityAddress addr(session->getRemoteContactAddress()->asStringUriOnly()); q->onConferenceCreated(addr); - if (session->getRemoteContactAddress()->hasParam("isfocus")) + if (session->getRemoteContactAddress()->hasParam("isfocus")){ + bgTask.start(q->getCore(), 32); /*it will be stopped when receiving the first notify*/ qConference->getPrivate()->eventHandler->subscribe(q->getChatRoomId()); + } } else if (q->getState() == ChatRoom::State::TerminationPending) qConference->getPrivate()->focus->getPrivate()->getSession()->terminate(); } else if (newState == CallSession::State::Released) { @@ -179,15 +181,14 @@ ClientGroupChatRoom::ClientGroupChatRoom ( const string &subject ) : ChatRoom(*new ClientGroupChatRoomPrivate, core, ChatRoomId(IdentityAddress(), me)), RemoteConference(core, me, nullptr) { - L_D(); L_D_T(RemoteConference, dConference); - - d->bgTask.setName("Client group chat room refer received"); - + L_D(); + IdentityAddress focusAddr(uri); dConference->focus = make_shared(focusAddr); dConference->focus->getPrivate()->addDevice(focusAddr); RemoteConference::setSubject(subject); + d->bgTask.setName("Subscribe/notify of full state conference"); } ClientGroupChatRoom::ClientGroupChatRoom ( @@ -410,7 +411,6 @@ void ClientGroupChatRoom::join () { shared_ptr session = dConference->focus->getPrivate()->getSession(); if (!session && ((getState() == ChatRoom::State::Instantiated) || (getState() == ChatRoom::State::Terminated))) { - d->bgTask.start(); session = d->createSession(); } if (session) { @@ -424,7 +424,6 @@ void ClientGroupChatRoom::leave () { L_D(); L_D_T(RemoteConference, dConference); - d->bgTask.start(); dConference->eventHandler->unsubscribe(); shared_ptr session = dConference->focus->getPrivate()->getSession(); @@ -475,18 +474,19 @@ void ClientGroupChatRoom::onConferenceTerminated (const IdentityAddress &addr) { void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) { L_D(); d->setState(ChatRoom::State::Created); - + if (getParticipantCount() == 1) { ChatRoomId id(getParticipants().front()->getAddress(), getMe()->getAddress()); shared_ptr chatRoom = getCore()->findChatRoom(id); if (chatRoom && (chatRoom->getCapabilities() & ChatRoom::Capabilities::Basic)) { BasicToClientGroupChatRoom::migrate(getSharedFromThis(), chatRoom); - return; + goto end; } } d->chatRoomListener->onChatRoomInsertInDatabaseRequested(getSharedFromThis()); - +end: + d->bgTask.stop(); // TODO: Bug. Event is inserted many times. // Avoid this in the future. Deal with signals/slots system. #if 0 @@ -496,7 +496,6 @@ void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) { d->chatRoomId )); #endif - d->bgTask.stop(); } void ClientGroupChatRoom::onParticipantAdded (const shared_ptr &event, bool isFullState) { diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp index 44b1a3090..7f9d6dd39 100644 --- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp +++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp @@ -485,7 +485,10 @@ error: } void FileTransferChatMessageModifier::fileUploadBeginBackgroundTask () { - bgTask.start(); + shared_ptr message = chatMessage.lock(); + if (!message) + return; + bgTask.start(message->getCore()); } void FileTransferChatMessageModifier::fileUploadEndBackgroundTask () { diff --git a/src/utils/background-task.cpp b/src/utils/background-task.cpp index a83d1b14b..bca543c35 100644 --- a/src/utils/background-task.cpp +++ b/src/utils/background-task.cpp @@ -20,25 +20,41 @@ #include "background-task.h" #include "c-wrapper/internal/c-sal.h" #include "logger/logger.h" +#include "core/core-p.h" +#include "private.h" //to get access to the Sal // ============================================================================= LINPHONE_BEGIN_NAMESPACE -static void notifier (void *context) { +void BackgroundTask::sHandleTimeout(void *context) { static_cast(context)->handleTimeout(); } -void BackgroundTask::start () { +int BackgroundTask::sHandleSalTimeout(void *data, unsigned int events){ + static_cast(data)->handleSalTimeout(); + return BELLE_SIP_STOP; +} + +void BackgroundTask::handleSalTimeout(){ + lWarning() << "Background task [" << mId << "] with name : [" << mName << "] is now expiring."; + stop(); +} + +void BackgroundTask::start (const std::shared_ptr &core, int max_duration_seconds) { if (mName.empty()) { lError() << "No name was set on background task."; return; } - unsigned long newId = sal_begin_background_task(mName.c_str(), notifier, this); - lInfo() << "Starting background task [" << newId << "] with name : [" << mName << "]."; + unsigned long newId = sal_begin_background_task(mName.c_str(), sHandleTimeout, this); + lInfo() << "Starting background task [" << newId << "] with name : [" << mName << "] and expiration of ["< 0){ + mSal = core->getCCore()->sal; + mTimeout = mSal->create_timer(sHandleSalTimeout, this, (unsigned int) max_duration_seconds * 1000, mName.c_str()); + } } void BackgroundTask::stop () { @@ -47,11 +63,16 @@ void BackgroundTask::stop () { lInfo() << "Ending background task [" << mId << "] with name : [" << mName << "]."; sal_end_background_task(mId); + if (mTimeout){ + mSal->cancel_timer(mTimeout); + belle_sip_object_unref(mTimeout); + mTimeout = NULL; + } mId = 0; } void BackgroundTask::handleTimeout () { - lWarning() << "Background task [" << mId << "] with name : [" << mName << "] has expired before completion..."; + lWarning() << "Background task [" << mId << "] with name : [" << mName << "] is expiring from OS before completion..."; stop(); } diff --git a/src/utils/background-task.h b/src/utils/background-task.h index 45b2002fb..5aa7edb89 100644 --- a/src/utils/background-task.h +++ b/src/utils/background-task.h @@ -23,15 +23,19 @@ #include #include "linphone/utils/general.h" +#include "sal/sal.h" // ============================================================================= LINPHONE_BEGIN_NAMESPACE +class Sal; +class Core; + class BackgroundTask { public: - BackgroundTask () = default; - BackgroundTask (const std::string &name) : mName(name) {} + BackgroundTask() : mTimeout(NULL), mSal(NULL), mId(0){} + BackgroundTask (const std::string &name) : mTimeout(NULL), mSal(NULL), mName(name), mId(0) {} virtual ~BackgroundTask () { stop(); } @@ -39,19 +43,26 @@ public: void setName (const std::string &name) { mName = name; } - - void start (); - void stop (); + /** + * Start a long running task for at most max_duration_seconds, after which it is automatically terminated + */ + void start(const std::shared_ptr &core, int max_duration_seconds = 15*60); /*15 mn by default, like on iOS*/ + void stop(); const std::string &getName () const { return mName; } - +protected: virtual void handleTimeout (); private: + static int sHandleSalTimeout(void *data, unsigned int events); + static void sHandleTimeout(void *data); + belle_sip_source_t *mTimeout; + Sal *mSal; std::string mName; unsigned long mId = 0; + void handleSalTimeout(); }; LINPHONE_END_NAMESPACE