Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/ Postpone application activation if registration is not complete yet #3557

Merged
merged 3 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()) {
iCollin marked this conversation as resolved.
Show resolved Hide resolved
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);
iCollin marked this conversation as resolved.
Show resolved Hide resolved
postponed_activation_controller_.RemoveAppToActivate(app_id);
}
}
}
}

bool StateControllerImpl::IsTempStateActive(HmiState::StateID id) const {
Expand Down Expand Up @@ -1415,4 +1430,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