Skip to content

Commit

Permalink
Fix/ Postpone application activation if registration is not complete …
Browse files Browse the repository at this point in the history
…yet (#3557)

* Postpone application activation if registration is not complete yet

* fixup! Postpone application activation if registration is not complete yet

* fixup! Postpone application activation if registration is not complete yet

Co-authored-by: Andrii Kalinich <[email protected]>
  • Loading branch information
Ira Lytvynenko (GitHub) and AKalinich-Luxoft authored Oct 29, 2020
1 parent ba3a66a commit 3eb6d6b
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,7 @@ class ApplicationManagerImpl
* @brief Closes all registered applications
*/
void UnregisterAllApplications();

bool ActivateApplication(ApplicationSharedPtr app) OVERRIDE;

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (c) 2020, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of the Ford Motor Company nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifndef SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POSTPONED_ACTIVATION_CONTROLLER_H_
#define SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POSTPONED_ACTIVATION_CONTROLLER_H_

#include "application.h"

namespace application_manager {

/**
* @brief AppToActivateSet is a map of application ids expected to be
* activated after the registration is completed (default hmi level is assigned)
* and correlation_ids of the SDLActivateApp requests
*/
typedef std::map<uint32_t, uint32_t> AppToActivate;

class PostponedActivationController {
public:
PostponedActivationController();

/**
* @brief AddAppToActivate adds app_id to app_to_activate_ map
* @param app_id id of the app that should be activated
* @param corr_id correlation_id of the SDLActivateApp request
*/
void AddAppToActivate(uint32_t app_id, uint32_t corr_id);

/**
* @brief GetPendingActivationCorrId gets the pending
* activation correlation id
* @param app_id application id
* @return correlation id of the SDLActivateApp requests
*/
uint32_t GetPendingActivationCorrId(uint32_t app_id) const;

/**
* @brief RemoveAppToActivate removes app_id from app_to_activate_ map
* @param app_id application id
*/
void RemoveAppToActivate(uint32_t app_id);

private:
AppToActivate app_to_activate_;
mutable std::shared_ptr<sync_primitives::Lock> activate_app_list_lock_ptr_;
};
} // namespace application_manager

#endif // SRC_COMPONENTS_APPLICATION_MANAGER_INCLUDE_APPLICATION_MANAGER_POSTPONED_ACTIVATION_CONTROLLER_H_
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ class StateControllerImpl : public event_engine::EventObserver,

void DropPostponedWindows(const uint32_t app_id) OVERRIDE;

PostponedActivationController& GetPostponedActivationController() OVERRIDE;

private:
int64_t RequestHMIStateChange(ApplicationConstSharedPtr app,
hmi_apis::Common_HMILevel::eType level,
Expand Down Expand Up @@ -434,6 +436,7 @@ class StateControllerImpl : public event_engine::EventObserver,
std::unordered_set<uint32_t> apps_with_pending_hmistatus_notification_;
mutable sync_primitives::Lock apps_with_pending_hmistatus_notification_lock_;
ApplicationManager& app_mngr_;
PostponedActivationController postponed_activation_controller_;
};
} // namespace application_manager

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ void SDLActivateAppRequest::Run() {

ApplicationConstSharedPtr app =
application_manager_.WaitingApplicationByID(app_id());

if (!app) {
app = application_manager_.application(app_id());
if (!app) {
SDL_LOG_WARN("Can't find application within waiting apps: " << app_id());
return;
}
}

if (application_manager_.state_controller().IsStateActive(
HmiState::STATE_ID_DEACTIVATE_HMI)) {
SDL_LOG_DEBUG(
Expand All @@ -139,6 +148,18 @@ void SDLActivateAppRequest::Run() {
application_manager_.connection_handler().ConnectToDevice(app->device());
} else {
const uint32_t application_id = app_id();
auto main_state =
app->CurrentHmiState(mobile_apis::PredefinedWindows::DEFAULT_WINDOW);
if (mobile_apis::HMILevel::INVALID_ENUM == main_state->hmi_level()) {
SDL_LOG_DEBUG(
"Application registration is not completed, HMI level hasn't set "
"yet, postpone activation");
auto& postponed_activation_ctrl = application_manager_.state_controller()
.GetPostponedActivationController();
postponed_activation_ctrl.AddAppToActivate(application_id,
correlation_id());
return;
}
policy_handler_.OnActivateApp(application_id, correlation_id());
}
}
Expand Down Expand Up @@ -186,6 +207,18 @@ void SDLActivateAppRequest::Run() {

if (app_to_activate->IsRegistered()) {
SDL_LOG_DEBUG("Application is registered. Activating.");
auto main_state = app_to_activate->CurrentHmiState(
mobile_apis::PredefinedWindows::DEFAULT_WINDOW);
if (mobile_apis::HMILevel::INVALID_ENUM == main_state->hmi_level()) {
SDL_LOG_DEBUG(
"Application registration is not completed, HMI level hasn't set "
"yet, postpone activation");
auto& postponed_activation_ctrl = application_manager_.state_controller()
.GetPostponedActivationController();
postponed_activation_ctrl.AddAppToActivate(application_id,
correlation_id());
return;
}
policy_handler_.OnActivateApp(application_id, correlation_id());
return;
} else if (app_to_activate->is_cloud_app()) {
Expand Down Expand Up @@ -269,6 +302,20 @@ void SDLActivateAppRequest::on_event(const event_engine::Event& event) {
"Application not found by HMI app id: " << hmi_application_id);
return;
}

auto main_state =
app->CurrentHmiState(mobile_apis::PredefinedWindows::DEFAULT_WINDOW);
if (mobile_apis::HMILevel::INVALID_ENUM == main_state->hmi_level()) {
SDL_LOG_DEBUG(
"Application registration is not completed, HMI level hasn't set "
"yet, postpone activation");
auto& postponed_activation_ctrl = application_manager_.state_controller()
.GetPostponedActivationController();
postponed_activation_ctrl.AddAppToActivate(app->app_id(),
correlation_id());
return;
}

policy_handler_.OnActivateApp(app->app_id(), correlation_id());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "application_manager/mock_message_helper.h"
#include "application_manager/mock_state_controller.h"
#include "application_manager/policies/mock_policy_handler_interface.h"
#include "application_manager/postponed_activation_controller.h"
#include "connection_handler/mock_connection_handler.h"
#include "gtest/gtest.h"
#include "hmi/sdl_activate_app_request.h"
Expand Down Expand Up @@ -139,13 +140,20 @@ TEST_F(SDLActivateAppRequestTest, Run_ActivateApp_SUCCESS) {
std::shared_ptr<SDLActivateAppRequest> command(
CreateCommand<SDLActivateAppRequest>(msg));

MockAppPtr mock_app(CreateMockApp());
EXPECT_CALL(app_mngr_, WaitingApplicationByID(kAppID))
.WillOnce(Return(ApplicationSharedPtr()));
EXPECT_CALL(app_mngr_, state_controller())
.WillOnce(ReturnRef(mock_state_controller_));
.WillOnce(Return(mock_app));
ON_CALL(app_mngr_, state_controller())
.WillByDefault(ReturnRef(mock_state_controller_));
EXPECT_CALL(mock_state_controller_,
IsStateActive(am::HmiState::StateID::STATE_ID_DEACTIVATE_HMI))
.WillOnce(Return(false));
am::HmiStatePtr state = std::make_shared<am::HmiState>(mock_app, app_mngr_);
state->set_hmi_level(mobile_apis::HMILevel::HMI_NONE);

EXPECT_CALL(*mock_app,
CurrentHmiState(mobile_apis::PredefinedWindows::DEFAULT_WINDOW))
.WillOnce(Return(state));

EXPECT_CALL(mock_policy_handler_, OnActivateApp(kAppID, kCorrelationID));

Expand Down Expand Up @@ -303,7 +311,7 @@ TEST_F(SDLActivateAppRequestTest, FirstAppActive_SUCCESS) {
command->Run();
}

TEST_F(SDLActivateAppRequestTest, FirstAppNotActive_SUCCESS) {
TEST_F(SDLActivateAppRequestTest, FirstAppNotActiveNONE_SUCCESS) {
MessageSharedPtr msg = CreateMessage();
SetCorrelationAndAppID(msg);

Expand All @@ -312,12 +320,18 @@ TEST_F(SDLActivateAppRequestTest, FirstAppNotActive_SUCCESS) {

MockAppPtr mock_app(CreateMockApp());
ON_CALL(app_mngr_, application(kAppID)).WillByDefault(Return(mock_app));
EXPECT_CALL(app_mngr_, state_controller())
.WillOnce(ReturnRef(mock_state_controller_));
ON_CALL(app_mngr_, state_controller())
.WillByDefault(ReturnRef(mock_state_controller_));
EXPECT_CALL(mock_state_controller_,
IsStateActive(am::HmiState::StateID::STATE_ID_DEACTIVATE_HMI))
.WillOnce(Return(false));
EXPECT_CALL(*mock_app, IsRegistered()).WillOnce(Return(true));
am::HmiStatePtr state = std::make_shared<am::HmiState>(mock_app, app_mngr_);
state->set_hmi_level(mobile_apis::HMILevel::HMI_NONE);

EXPECT_CALL(*mock_app,
CurrentHmiState(mobile_apis::PredefinedWindows::DEFAULT_WINDOW))
.WillOnce(Return(state));

EXPECT_CALL(mock_policy_handler_, OnActivateApp(kAppID, kCorrelationID));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2020, Ford Motor Company
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of the Ford Motor Company nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#include "application_manager/postponed_activation_controller.h"

namespace application_manager {

SDL_CREATE_LOG_VARIABLE("StateControllerImpl")

PostponedActivationController::PostponedActivationController()
: activate_app_list_lock_ptr_(std::make_shared<sync_primitives::Lock>()) {}

void PostponedActivationController::AddAppToActivate(uint32_t app_id,
uint32_t corr_id) {
SDL_LOG_AUTO_TRACE();
sync_primitives::AutoLock lock(activate_app_list_lock_ptr_);
app_to_activate_.insert(std::pair<uint32_t, uint32_t>(app_id, corr_id));
}

uint32_t PostponedActivationController::GetPendingActivationCorrId(
uint32_t app_id) const {
SDL_LOG_AUTO_TRACE();
sync_primitives::AutoLock lock(activate_app_list_lock_ptr_);
auto it = app_to_activate_.find(app_id);
if (app_to_activate_.end() == it) {
return 0;
}
return it->second;
}

void PostponedActivationController::RemoveAppToActivate(uint32_t app_id) {
SDL_LOG_AUTO_TRACE();
sync_primitives::AutoLock lock(activate_app_list_lock_ptr_);
app_to_activate_.erase(app_id);
}

} // namespace application_manager
22 changes: 21 additions & 1 deletion src/components/application_manager/src/state_controller_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ bool IsStateChanged(const HmiState& old_state, const HmiState& new_state) {
} // unnamed namespace

StateControllerImpl::StateControllerImpl(ApplicationManager& app_mngr)
: EventObserver(app_mngr.event_dispatcher()), app_mngr_(app_mngr) {
: EventObserver(app_mngr.event_dispatcher())
, app_mngr_(app_mngr)
, postponed_activation_controller_() {
subscribe_on_event(hmi_apis::FunctionID::BasicCommunication_OnAppActivated);
subscribe_on_event(hmi_apis::FunctionID::BasicCommunication_OnAppDeactivated);
subscribe_on_event(hmi_apis::FunctionID::TTS_Started);
Expand Down Expand Up @@ -959,6 +961,19 @@ void StateControllerImpl::OnStateChanged(ApplicationSharedPtr app,

app_mngr_.OnHMIStateChanged(app->app_id(), old_state, new_state);
app->usage_report().RecordHmiStateChanged(new_state->hmi_level());

if (mobile_apis::HMILevel::INVALID_ENUM == old_state->hmi_level()) {
const auto app_default_hmi_level = app_mngr_.GetDefaultHmiLevel(app);
if (app_default_hmi_level == new_state->hmi_level()) {
const uint32_t app_id = app->app_id();
const uint32_t corr_id =
postponed_activation_controller_.GetPendingActivationCorrId(app_id);
if (corr_id > 0) {
app_mngr_.GetPolicyHandler().OnActivateApp(app_id, corr_id);
postponed_activation_controller_.RemoveAppToActivate(app_id);
}
}
}
}

bool StateControllerImpl::IsTempStateActive(HmiState::StateID id) const {
Expand Down Expand Up @@ -1410,4 +1425,9 @@ mobile_apis::VideoStreamingState::eType StateControllerImpl::CalcVideoState(
return state;
}

PostponedActivationController&
StateControllerImpl::GetPostponedActivationController() {
return postponed_activation_controller_;
}

} // namespace application_manager
5 changes: 5 additions & 0 deletions src/components/include/application_manager/state_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@

#include "application_manager/application.h"
#include "application_manager/application_manager.h"
#include "application_manager/postponed_activation_controller.h"
#include "application_manager/request_controller_settings.h"
#include "stdint.h"

class PostponedActivationController;

namespace application_manager {
class StateController {
public:
Expand Down Expand Up @@ -246,6 +249,8 @@ class StateController {
* @param app_id id of application to check
*/
virtual void DropPostponedWindows(const uint32_t app_id) = 0;

virtual PostponedActivationController& GetPostponedActivationController() = 0;
};

} // namespace application_manager
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ class MockStateController : public am::StateController {
MOCK_METHOD2(DeactivateApp,
void(am::ApplicationSharedPtr app,
const am::WindowID window_id));
MOCK_METHOD0(GetPostponedActivationController,
application_manager::PostponedActivationController&());
};

} // namespace application_manager_test
Expand Down

0 comments on commit 3eb6d6b

Please sign in to comment.