M .github/CODEOWNERS => .github/CODEOWNERS +1 -0
@@ 15,6 15,7 @@
# build system
/CMakeLists.txt @mudita/chapter-bsp
/third-party/CMakeLists.txt @mudita/chapter-bsp
+/module-utils/CMakeLists.txt @mudita/chapter-bsp
/cmake @mudita/chapter-bsp
/test/CMakeLists.txt @mudita/chapter-bsp
M .gitignore => .gitignore +2 -0
@@ 60,3 60,5 @@ update/
# often created by the visual studio code
/null.d
+
+test/test_env<
\ No newline at end of file
M .gitmodules => .gitmodules +10 -10
@@ 17,7 17,7 @@
branch = rt1051
shallow = true
[submodule "module-utils/protobuf"]
- path = module-utils/protobuf
+ path = third-party/protobuf/src
url = ../protobuf.git
branch = rt1051
shallow = true
@@ 36,12 36,8 @@
[submodule "module-utils/date"]
path = third-party/date
url = ../date.git
-[submodule "module-audio/Audio/decoder/minimp3"]
- path = module-audio/Audio/decoder/minimp3
- url = ../minimp3.git
- branch = RT1051
[submodule "module-utils/taglib"]
- path = module-utils/taglib
+ path = third-party/taglib
url = ../taglib.git
branch = rt1051
[submodule "module-bluetooth/lib/btstack"]
@@ 54,7 50,7 @@
path = third-party/magic_enum
url = https://github.com/Neargye/magic_enum.git
[submodule "module-utils/tinyexpr"]
- path = module-utils/tinyexpr
+ path = third-party/tinyexpr/src
url = https://github.com/codeplea/tinyexpr.git
[submodule "module-bsp/board/rt1051/bsp/usb"]
path = module-bsp/board/rt1051/bsp/usb
@@ 68,9 64,6 @@
[submodule "module-vfs/thirdparty/lfsfs/littlefs"]
path = module-vfs/thirdparty/lfsfs/littlefs
url = https://github.com/littlefs-project/littlefs.git
-[submodule "module-utils/parallel-hashmap"]
- path = module-utils/parallel-hashmap
- url = https://github.com/greg7mdp/parallel-hashmap.git
[submodule "module-utils/sml"]
path = third-party/sml/src
url = https://github.com/boost-ext/sml
@@ 84,3 77,10 @@
[submodule "module-utils/CrashDebug"]
path = module-utils/CrashDebug
url = https://github.com/adamgreen/CrashDebug.git
+[submodule "third-party/minimp3/minimp3"]
+ path = third-party/minimp3/minimp3
+ url = ../minimp3.git
+ branch = RT1051
+[submodule "third-party/parallel-hashmap/src"]
+ path = third-party/parallel-hashmap/src
+ url = https://github.com/greg7mdp/parallel-hashmap.git
M CMakeLists.txt => CMakeLists.txt +2 -2
@@ 150,6 150,8 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_INCLUDES})
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_BINARY_DIR})
+add_subdirectory(third-party)
+
if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
add_subdirectory(board/linux/libiosyscalls)
endif()
@@ 192,8 194,6 @@ add_subdirectory(module-bluetooth)
message("${PROJECT_NAME}: add_subdirectory module-lwip")
add_subdirectory(module-lwip)
-add_subdirectory(third-party)
-
add_subdirectory(image)
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES SUFFIX ".elf")
M Jenkinsfile => Jenkinsfile +2 -13
@@ 81,13 81,8 @@ popd'''
when {
changeRequest()
}
- parallel {
+ stages{
stage('Build RT1051') {
- agent {
- node {
- label 'jenkins-slave-ccache-ram'
- }
- }
steps {
sh '''#!/bin/bash -e
PATH="/usr/local/cmake-3.19.5-Linux-x86_64/bin:/usr/local/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH"
@@ 114,12 109,6 @@ ccache --show-stats'''
}
stage('Build Linux') {
- agent {
- node {
- label 'jenkins-slave-ccache-ram'
- }
- }
-
environment {
PATH="/usr/local/cmake-3.19.5-Linux-x86_64/bin:/usr/local/gcc-arm-none-eabi-10-2020-q4-major/bin:$PATH"
CCACHE_DIR="/ccache/Linux"
@@ 166,7 155,7 @@ popd
popd'''
}
}
- }
+ }
}
stage('master-jobs') {
when {
M Target_RT1051.cmake => Target_RT1051.cmake +1 -0
@@ 95,6 95,7 @@ set(BOARD_DIR_INCLUDES
${CMAKE_CURRENT_LIST_DIR}/board/rt1051/newlib/include
${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/include
${CMAKE_SOURCE_DIR}/module-utils/CrashDebug/CrashCatcher/Core/src
+ ${CMAKE_SOURCE_DIR}/module-vfs/include/internal
)
set(TARGET_LIBRARIES
M board/linux/libiosyscalls/CMakeLists.txt => board/linux/libiosyscalls/CMakeLists.txt +21 -13
@@ 5,22 5,21 @@ project(iosyscalls VERSION 1.0
set(SOURCES
- ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_stdio.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_scan_family.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix_dirent.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/src/iosyscalls.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_stdio.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_scan_family.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls_posix_dirent.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/iosyscalls.cpp
)
set(INCLUDES
- "${CMAKE_CURRENT_SOURCE_DIR}/include"
- "${CMAKE_SOURCE_DIR}/module-os/board/linux"
- "${CMAKE_SOURCE_DIR}/module-os/RTOSWrapper/include"
- "${CMAKE_SOURCE_DIR}/module-utils/parallel-hashmap"
- "${CMAKE_SOURCE_DIR}/module-utils"
- "${CMAKE_SOURCE_DIR}/module-vfs/include/user"
- "${CMAKE_SOURCE_DIR}/module-vfs/include/internal"
+ "${CMAKE_CURRENT_SOURCE_DIR}/include"
+ "${CMAKE_SOURCE_DIR}/module-os/board/linux"
+ "${CMAKE_SOURCE_DIR}/module-os/RTOSWrapper/include"
+ "${CMAKE_SOURCE_DIR}/module-utils"
+ "${CMAKE_SOURCE_DIR}/module-vfs/include/user"
+ "${CMAKE_SOURCE_DIR}/module-vfs/include/internal"
)
@@ 45,7 44,16 @@ target_link_options(${PROJECT_NAME} PRIVATE
)
target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDES} )
-target_link_libraries( ${PROJECT_NAME} dl )
+
+target_link_libraries(
+ ${PROJECT_NAME}
+ PUBLIC
+ dl
+ PRIVATE
+ phmap
+)
+
+
target_compile_definitions( ${PROJECT_NAME} PUBLIC TARGET_Linux )
if (${ENABLE_TESTS})
M board/rt1051/crashdump/crashdumpwriter_vfs.hpp => board/rt1051/crashdump/crashdumpwriter_vfs.hpp +1 -1
@@ 33,7 33,7 @@ namespace crashdump
{
std::time_t now;
std::time(&now);
- std::strftime(name.data(), name.size(), CrashDumpFileNameFormat, gmtime(&now));
+ std::strftime(name.data(), name.size(), CrashDumpFileNameFormat, std::localtime(&now));
}
int dumpFd{-1};
M board/rt1051/memwrap.c => board/rt1051/memwrap.c +0 -9
@@ 58,13 58,6 @@ void* calloc (size_t num, size_t size)
return memset(p, 0, total);
}
-/* struct tm * localtime(const time_t *t)
-{
- static struct tm y = {0};
- //RtcServiceGetCurrentDateTime(&tm);
- return &y;
-} */
-
void *realloc(void *aptr, size_t nbytes)
{
return userrealloc(aptr, nbytes);
@@ 104,5 97,3 @@ void _putchar(char character)
{
// Use of printf is banned
}
-
-
M cmake/modules/PureCoverage.cmake => cmake/modules/PureCoverage.cmake +1 -8
@@ 19,10 19,10 @@ if(COVERAGE_ENABLE)
.*/test/.*
.*/tests/.*
.*/thirdparty/.*
+ .*/third-party/.*
board/linux/libiosyscalls/.*
host-tools/.*
module-audio/Audio/decoder/dr_flac.h
- module-audio/Audio/decoder/minimp3/minimp3.h
module-bluetooth/Bluetooth/glucode/.*
module-bluetooth/lib/.*
module-db/Database/sqlite3.c
@@ 31,15 31,8 @@ if(COVERAGE_ENABLE)
module-utils/gsl/.*
module-utils/json/.*
module-utils/libphonenumber/.*
- module-utils/microtar/.*
- module-utils/parallel-hashmap/.*
- module-utils/protobuf/.*
- third-party/pugixml/.*
module-utils/re2/.*
module-utils/segger/.*
- module-utils/sml/.*
- module-utils/taglib/.*
- module-utils/tinyexpr/.*
source/main.cpp
test/.*
)
M doc/Doxyfile.in => doc/Doxyfile.in +2 -4
@@ 887,12 887,9 @@ RECURSIVE = YES
EXCLUDE = @PROJECT_SOURCE_DIR@/module-bluetooth/lib \
@PROJECT_SOURCE_DIR@/module-utils/tinyfsm \
- @PROJECT_SOURCE_DIR@/module-utils/microtar \
@PROJECT_SOURCE_DIR@/module-utils/segger \
- @PROJECT_SOURCE_DIR@/module-utils/crc32 \
@PROJECT_SOURCE_DIR@/module-utils/sbini \
@PROJECT_SOURCE_DIR@/module-utils/re2 \
- @PROJECT_SOURCE_DIR@/module-utils/protobuf \
@PROJECT_SOURCE_DIR@/module-utils/libphonenumber \
@PROJECT_SOURCE_DIR@/module-utils/test \
@PROJECT_SOURCE_DIR@/module-db/tests \
@@ 906,7 903,8 @@ EXCLUDE = @PROJECT_SOURCE_DIR@/module-bluetooth/lib \
@PROJECT_SOURCE_DIR@/module-vfs/tests \
@PROJECT_SOURCE_DIR@/module-vfs/board \
@PROJECT_SOURCE_DIR@/module-bsp/board/rt1051/common \
- @PROJECT_SOURCE_DIR@/module-audio/Audio/decoder/taglib
+ @PROJECT_SOURCE_DIR@/module-audio/Audio/decoder/taglib \
+ @PROJECT_SOURCE_DIR@/third-party
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
M enabled_unittests => enabled_unittests +5 -0
@@ 460,6 460,11 @@ TESTS_LIST["catch2-iosyscalls"]="
VFS linux support;
"
#---------
+TESTS_LIST["catch2-vfs-inotify"]="
+ Notifier base class test;
+ Filtering test;
+"
+#---------
TESTS_LIST["catch2-cellular-cmux"]="
TS0170 frame;
"
M image/assets/lang/English.json => image/assets/lang/English.json +7 -3
@@ 246,6 246,8 @@
"sim_setup_wrong_puk_last_attempt_warning": "<text>If the code is wrong this time, the<br></br>SIM card will be blocked and you'll<br></br>have to contact the operator.</text>",
"sim_card_pin_disabled": "SIM card pin disabled",
"sim_card_pin_enabled": "SIM card pin enabled",
+ "sim_card_cant_connect": "<text>Cannot connect to <token>$SIM</token> card.<br></br>Please insert card.</text>",
+ "sim_card_not_ready": "<text>Waiting for Modem to start.<br></br>This may take a moment.</text>",
"app_desktop_press_to_unlock": "<text font='gt_pressura' size='27'>Press <b>Unlock</b> and then <b>#</b></text>",
"app_desktop_unread_messages": "<text>Unread <b>messages</b></text>",
"app_desktop_missed_calls": "<text>Missed <b>calls</b></text>",
@@ 318,8 320,8 @@
"app_onboarding_title_configuration": "Configuration",
"app_onboarding_title_update_info": "MuditaOS update",
"app_onboarding_skip_confirm": "<text>Sim setup is required for network connection. Skip the setup anyway? </text>",
- "app_onboarding_configuration_successful": "<text>Your Pure was configured</text><br></br><text>successfully.</text>",
- "app_onboarding_no_configuration": "<text>Your Pure is not configured.</text><br></br><text>You can go to Settings to.</text><br></br><text>configure it.</text>",
+ "app_onboarding_configuration_successful": "<text>Your Mudita Pure<br></br>is ready to use.</text>",
+ "app_onboarding_no_configuration": "<text>Your Mudita Pure has not been<br></br>configured. You can go to<br></br>Settings to set it up.</text>",
"app_onboarding_update_info": "<text>New Mudita OS version is available.</text><br></br><text>To update your Pure Phone, please</text><br></br><text>visit: </text><text font='gt_pressura' weight='bold' size='27'>www.mudita.com/updateos</text><br></br><text>and follow the instructions.</text>",
"app_settings_title_main": "Advanced",
"app_settings_title_main_new": "Settings",
@@ 566,6 568,8 @@
"app_desktop_update_success": "MuditaOS has been updated to ver. $VERSION succesfully.",
"app_call_private_number": "Private number",
"tethering": "Tethering",
+ "tethering_turn_off_question": "Turn tethering off?",
"tethering_enable_question": "<text>You're connected to the computer.<br />Turn tethering on?<br /><text color='9'>(some functions may be disabled)</text></text>",
- "tethering_phone_mode_change_prohibited": "<text>Tethering is on.<br /><br />Other modes (Connected, DND,<br />Offline) are overriden by this mode<br />and are not working.</text>"
+ "tethering_phone_mode_change_prohibited": "<text>Tethering is on.<br /><br />Other modes (Connected, DND,<br />Offline) are overriden by this mode<br />and are not working.</text>",
+ "tethering_menu_access_decline": "<text>Tethering is on.<br /><br />To access menu,<br />turn tethering off.</text>"
}
M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +4 -4
@@ 19,7 19,7 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('gs_display_language', 'English'),
('gs_input_language', 'English'),
('gs_eula_accepted', '0'),
- ('gs_onboarding_done', '0'),
+ ('gs_onboarding_done', '1'),
('gs_usb_security', '1'),
('gs_usb_devices', ''),
('gs_os_update_version', '0.00.0'),
@@ 33,7 33,7 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
('off_connection_frequency', '0'),
('off_notifications_when_locked', '0'),
('off_calls_from_favorites', '0'),
- ('br_state', '0'),
- ('br_auto_mode', '0'),
- ('br_level', '50.0f'),
+ ('\EventManager\\br_state', '0'),
+ ('\EventManager\\br_auto_mode', '0'),
+ ('\EventManager\\br_level', '50.0f'),
('keypad_light_state', '0');
M image/user/db/sms_001.sql => image/user/db/sms_001.sql +0 -1
@@ 7,7 7,6 @@ CREATE TABLE IF NOT EXISTS sms
thread_id INTEGER,
contact_id INTEGER,
date INTEGER,
- date_send INTEGER,
error_code INTEGER,
body TEXT NOT_NULL,
type INTEGER,
M image/user/db/sms_003.sql => image/user/db/sms_003.sql +6 -6
@@ 1,12 1,12 @@
-- Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
BEGIN TRANSACTION;
-INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","date_send","error_code","body","type") VALUES (1,2,2,1547492320,3,0,'Thank you for today!' || CHAR(10) || 'You chose a fantastic place :)',8);
-INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","date_send","error_code","body","type") VALUES (2,2,2,1547492321,4,0,'It was great seeing you too :*',4);
-INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","date_send","error_code","body","type") VALUES (3,1,1,1618907731,3,2,'Hi! How are you today?',8);
-INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","date_send","error_code","body","type") VALUES (4,1,1,1618907732,3,2,'I hope you''re feeling better now...',8);
-INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","date_send","error_code","body","type") VALUES (5,1,1,1618907733,3,2,'Thanks :) Today is better than yesterday',4);
-INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","date_send","error_code","body","type") VALUES (6,1,1,1618907734,3,2,'I''m happy to hear that :)',8);
+INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (1,2,2,1547492320,0,'Thank you for today!' || CHAR(10) || 'You chose a fantastic place :)',8);
+INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (2,2,2,1547492321,0,'It was great seeing you too :*',4);
+INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (3,1,1,1618907731,2,'Hi! How are you today?',8);
+INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (4,1,1,1618907732,2,'I hope you''re feeling better now...',8);
+INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (5,1,1,1618907733,2,'Thanks :) Today is better than yesterday',4);
+INSERT OR REPLACE INTO "sms" ("_id","thread_id","contact_id","date","error_code","body","type") VALUES (6,1,1,1618907734,2,'I''m happy to hear that :)',8);
INSERT OR REPLACE INTO "templates" ("_id","text","lastUsageTimestamp") VALUES (1,'Thanks for reaching out. I can''t talk right now, I''ll call you later',4);
INSERT OR REPLACE INTO "templates" ("_id","text","lastUsageTimestamp") VALUES (2,'I''ll call you later',3);
INSERT OR REPLACE INTO "templates" ("_id","text","lastUsageTimestamp") VALUES (3,'I''ll be there in 15 minutes',2);
M module-apps/Application.cpp => module-apps/Application.cpp +6 -0
@@ 51,6 51,7 @@
#include <popups/lock-popups/PhoneLockChangeInfoWindow.hpp>
#include <popups/lock-popups/SimLockInputWindow.hpp>
#include <popups/lock-popups/SimInfoWindow.hpp>
+#include <popups/lock-popups/SimNotReadyWindow.hpp>
#include <popups/data/PopupData.hpp>
#include <popups/data/PopupRequestParams.hpp>
#include <popups/data/PhoneModeParams.hpp>
@@ 774,6 775,7 @@ namespace app
break;
case ID::PhoneLock:
case ID::PhoneLockInput:
+ case ID::PhoneLockInfo:
case ID::PhoneLockChangeInfo:
windowsFactory.attach(window::phone_lock_window, [](Application *app, const std::string &name) {
return std::make_unique<gui::PhoneLockedWindow>(app, window::phone_lock_window);
@@ 796,12 798,16 @@ namespace app
break;
case ID::SimLock:
case ID::SimInfo:
+ case ID::SimNotReady:
windowsFactory.attach(window::sim_unlock_window, [](Application *app, const std::string &name) {
return std::make_unique<gui::SimLockInputWindow>(app, window::sim_unlock_window);
});
windowsFactory.attach(window::sim_info_window, [](Application *app, const std::string &name) {
return std::make_unique<gui::SimInfoWindow>(app, window::sim_info_window);
});
+ windowsFactory.attach(window::sim_not_ready_window, [](Application *app, const std::string &name) {
+ return std::make_unique<gui::SimNotReadyWindow>(app, window::sim_not_ready_window);
+ });
break;
}
}
M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +1 -0
@@ 37,6 37,7 @@ set( SOURCES
"widgets/ActiveIconFactory.cpp"
"widgets/TextWithIconsWidget.cpp"
"widgets/DateWidget.cpp"
+ "widgets/IceBox.cpp"
"widgets/TimeWidget.cpp"
"widgets/WidgetsUtils.cpp"
"notifications/NotificationListItem.cpp"
M module-apps/application-calculator/CMakeLists.txt => module-apps/application-calculator/CMakeLists.txt +3 -1
@@ 18,4 18,6 @@ endif()
target_link_libraries(${PROJECT_NAME}
PRIVATE
- service-evtmgr)
+ service-evtmgr
+ tinyexpr::tinyexpr
+)
M module-apps/application-calculator/data/CalculatorUtility.cpp => module-apps/application-calculator/data/CalculatorUtility.cpp +1 -1
@@ 4,7 4,7 @@
#include "CalculatorUtility.hpp"
#include "application-calculator/data/CalculatorInputProcessor.hpp"
#include "application-calculator/widgets/CalculatorStyle.hpp"
-#include <module-utils/tinyexpr/tinyexpr.h>
+#include <tinyexpr.h>
#include <i18n/i18n.hpp>
#include <Utils.hpp>
#include <cmath>
M module-apps/application-calculator/tests/CMakeLists.txt => module-apps/application-calculator/tests/CMakeLists.txt +4 -2
@@ 10,8 10,10 @@ add_catch2_executable(
"${CMAKE_CURRENT_SOURCE_DIR}/CalculatorInput_tests.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/CalculatorUtility_tests.cpp"
LIBS
+ module-sys
+ iosyscalls
module-apps
module-utils
- module-vfs
- iosyscalls
+ DEPS
+ assets
)
M module-apps/application-calculator/windows/CalculatorMainWindow.hpp => module-apps/application-calculator/windows/CalculatorMainWindow.hpp +0 -1
@@ 8,7 8,6 @@
#include "application-calculator/data/CalculatorInputProcessor.hpp"
#include "application-calculator/widgets/MathOperationsBox.hpp"
#include <module-gui/gui/widgets/Text.hpp>
-#include <module-utils/tinyexpr/tinyexpr.h>
namespace gui
{
M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +2 -3
@@ 20,7 20,7 @@
#include <service-db/QueryMessage.hpp>
#include <service-db/DBNotificationMessage.hpp>
-#include <time/time_conversion.hpp>
+#include <ctime>
namespace app
{
@@ 98,8 98,7 @@ namespace app
sys::ReturnCodes ApplicationCalendar::InitHandler()
{
- utils::time::Timestamp timestamp;
- applicationStartTime = timestamp.getTime();
+ applicationStartTime = std::time(nullptr);
auto ret = Application::InitHandler();
createUserInterface();
return ret;
M module-apps/application-calendar/data/dateCommon.hpp => module-apps/application-calendar/data/dateCommon.hpp +3 -4
@@ 103,8 103,7 @@ inline time_t TimePointToTimeT(const TimePoint &tp)
inline TimePoint TimePointNow()
{
- utils::time::Timestamp timestamp;
- return TimePointFromTimeT(timestamp.getTime());
+ return TimePointFromTimeT(std::time(nullptr));
}
inline std::string TimePointToString(const TimePoint &tp)
@@ 130,7 129,7 @@ inline auto LocalizedHoursToUtcHours(int hour = 0)
{
std::tm tm = CreateTmStruct(unix_epoch_year, 1, 1, hour, 0, 0);
std::time_t basetime = std::mktime(&tm);
- basetime -= utils::time::Time::getTimeZoneOffset();
+ basetime -= GetDiffLocalWithUTCTime();
return TimePointToHour24H(TimePointFromTimeT(basetime));
}
@@ 304,7 303,7 @@ inline std::string createUID()
{
constexpr uint32_t bufferLimit = 16;
char Buffer[bufferLimit];
- utils::time::Timestamp timestamp;
+ utils::time::Timestamp timestamp = utils::time::getCurrentTimestamp();
std::string UID{timestamp.str("%Y%m%dT%H%M%S")};
UID += '-';
std::random_device rd;
M module-apps/application-call/ApplicationCall.cpp => module-apps/application-call/ApplicationCall.cpp +0 -3
@@ 91,9 91,6 @@ namespace app
return getState() == call::State::IDLE;
}
- // number of seconds after end call to switch back to previous application
- const inline utils::time::Duration delayToSwitchToPreviousApp = 3;
-
void ApplicationCall::CallAbortHandler()
{
manager::Controller::sendAction(this, manager::actions::Call, std::make_unique<app::CallAbortData>());
M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +5 -0
@@ 17,6 17,7 @@
#include "windows/MmiPushWindow.hpp"
#include "windows/MmiInternalMsgWindow.hpp"
#include <popups/presenter/PowerOffPresenter.hpp>
+#include <popups/TetheringOffPopup.hpp>
#include <windows/Dialog.hpp>
#include <windows/DialogMetadata.hpp>
#include <messages/DialogMetadataMessage.hpp>
@@ 262,6 263,9 @@ namespace app
windowsFactory.attach(gui::window::name::dialog_confirm, [](Application *app, const std::string &name) {
return std::make_unique<gui::DialogConfirm>(app, name);
});
+ windowsFactory.attach(gui::popup::window::tethering_off_window, [](Application *app, const std::string &name) {
+ return std::make_unique<gui::TetheringOffPopup>(app, gui::popup::window::tethering_off_window);
+ });
attachPopups({gui::popup::ID::Volume,
gui::popup::ID::Tethering,
@@ 329,4 333,5 @@ namespace app
osUpdateVersion = value;
settings->setValue(settings::SystemProperties::osUpdateVersion, value, settings::SettingsScope::Global);
}
+
} // namespace app
M module-apps/application-desktop/models/ActiveNotificationsModel.cpp => module-apps/application-desktop/models/ActiveNotificationsModel.cpp +2 -3
@@ 6,7 6,6 @@
#include <module-db/queries/notifications/QueryNotificationsClear.hpp>
#include <service-appmgr/Controller.hpp>
#include <application-call/data/CallSwitchData.hpp>
-#include <SystemManager/messages/TetheringStateRequest.hpp>
#include <queries/messages/threads/QueryThreadGetByNumber.hpp>
#include <application-messages/data/SMSdata.hpp>
#include <application-messages/Constants.hpp>
@@ 148,8 147,8 @@ namespace
void setTetheringActivatedCallback(NotificationListItem *item, app::Application *app)
{
item->activatedCallback = [app]([[maybe_unused]] gui::Item &_item) {
- return app->bus.sendUnicast(std::make_shared<sys::TetheringStateRequest>(sys::phone_modes::Tethering::Off),
- service::name::system_manager);
+ app->switchWindow(gui::popup::window::tethering_off_window);
+ return true;
};
}
M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +32 -6
@@ 13,6 13,9 @@
#include <service-time/ServiceTime.hpp>
#include <service-time/TimeMessage.hpp>
#include <notifications/NotificationsModel.hpp>
+#include <windows/Dialog.hpp>
+#include <windows/DialogMetadata.hpp>
+#include <messages/DialogMetadataMessage.hpp>
#include <log/log.hpp>
@@ 40,7 43,17 @@ namespace gui
dayText->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
activatedCallback = [this]([[maybe_unused]] Item &item) {
- application->switchWindow(app::window::name::desktop_menu);
+ if (notificationsModel->isTetheringOn()) {
+ showInformationPopup(
+ [this]() {
+ app::manager::Controller::sendAction(application, app::manager::actions::Home);
+ return true;
+ },
+ utils::translate("tethering_menu_access_decline"));
+ }
+ else {
+ application->switchWindow(app::window::name::desktop_menu);
+ }
return true;
};
@@ 196,13 209,14 @@ namespace gui
return;
}
bottomBar->setText(BottomBar::Side::CENTER, utils::translate("app_desktop_menu"));
- bottomBar->setText(BottomBar::Side::LEFT, utils::translate("app_desktop_calls"));
+ const auto tetheringNotActive = !notificationsModel->isTetheringOn();
+ bottomBar->setText(BottomBar::Side::LEFT, utils::translate("app_desktop_calls"), tetheringNotActive);
const auto hasDismissibleNotification = notificationsModel->hasDismissibleNotification();
bottomBar->setText(
BottomBar::Side::RIGHT, utils::translate("app_desktop_clear_all"), hasDismissibleNotification);
- inputCallback = [this, hasDismissibleNotification]([[maybe_unused]] Item &item,
- const InputEvent &inputEvent) -> bool {
+ inputCallback = [this, hasDismissibleNotification, tetheringNotActive]([[maybe_unused]] Item &item,
+ const InputEvent &inputEvent) -> bool {
if (!inputEvent.isShortRelease() || notificationsList->focus) {
return false;
}
@@ 211,7 225,7 @@ namespace gui
notificationsModel->dismissAll(inputEvent);
return true;
}
- if (inputEvent.is(gui::KeyCode::KEY_LF)) {
+ if (inputEvent.is(gui::KeyCode::KEY_LF) && tetheringNotActive) {
LOG_DEBUG("KEY_LF pressed to navigate to calls");
return app::manager::Controller::sendAction(application, app::manager::actions::ShowCallLog);
}
@@ 230,7 244,7 @@ namespace gui
{
using namespace utils::time;
auto ret = AppWindow::updateTime();
- auto timestamp = utils::time::Timestamp();
+ auto timestamp = utils::time::getCurrentTimestamp();
if (time != nullptr) {
auto fmt = utils::dateAndTimeSettings.isTimeFormat12()
? Locale::format(Locale::TimeFormat::FormatTime12HShort)
@@ 242,4 256,16 @@ namespace gui
}
return ret;
}
+
+ bool DesktopMainWindow::showInformationPopup(std::function<bool()> action, const std::string ¬ification)
+ {
+ DialogMetadata meta;
+ meta.icon = "info_big_circle_W_G";
+ meta.text = notification;
+ meta.action = std::move(action);
+ auto switchData = std::make_unique<DialogMetadataMessage>(std::move(meta));
+ application->switchWindow(window::name::dialog_confirm, std::move(switchData));
+ return true;
+ }
+
} /* namespace gui */
M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +1 -0
@@ 50,6 50,7 @@ namespace gui
bool updateTime() override;
private:
+ bool showInformationPopup(std::function<bool()> action, const std::string ¬ification);
void invalidate() noexcept;
std::string osUpdateVer;
std::string osCurrentVer;
M module-apps/application-desktop/windows/UpdateProgress.cpp => module-apps/application-desktop/windows/UpdateProgress.cpp +2 -1
@@ 27,6 27,7 @@ namespace gui
: AppWindow(app, app::window::name::desktop_update_progress)
{
buildInterface();
+ preventsAutoLock = true;
}
void UpdateProgressWindow::onBeforeShow(ShowMode mode, SwitchData *data)
@@ 37,7 38,7 @@ namespace gui
else {
auto *item = dynamic_cast<gui::UpdateSwitchData *>(data);
if (item != nullptr) {
- auto msg = item->getUpdateOsMessage();
+ const auto &msg = item->getUpdateOsMessage();
updateFile = msg.updateStats.updateFile;
auto updateVersion =
msg.updateStats.versionInformation[boot::json::os_version][boot::json::version_string]
M module-apps/application-messages/ApplicationMessages.cpp => module-apps/application-messages/ApplicationMessages.cpp +7 -8
@@ 32,10 32,10 @@
#include <module-db/queries/phonebook/QueryContactGetByID.hpp>
#include <service-cellular/CellularMessage.hpp>
+#include <messages/OptionsWindow.hpp>
#include <cassert>
-#include <time/time_conversion.hpp>
-#include <messages/OptionsWindow.hpp>
+#include <ctime>
namespace app
{
@@ 329,7 329,7 @@ namespace app
assert(!body.empty()); // precondition check.
record.body = body;
- record.date = utils::time::getCurrentTimestamp().getTime();
+ record.date = std::time(nullptr);
using db::query::SMSUpdate;
const auto [succeed, _] =
@@ 346,7 346,7 @@ namespace app
record.number = number;
record.body = body;
record.type = SMSType::DRAFT;
- record.date = utils::time::getCurrentTimestamp().getTime();
+ record.date = std::time(nullptr);
using db::query::SMSAdd;
const auto [success, _] =
@@ 372,7 372,7 @@ namespace app
record.number = number;
record.body = body;
record.type = SMSType::QUEUED;
- record.date = utils::time::getCurrentTimestamp().getTime();
+ record.date = std::time(nullptr);
using db::query::SMSAdd;
const auto [succeed, _] =
@@ 384,9 384,8 @@ namespace app
{
auto resendRecord = record;
resendRecord.type = SMSType::QUEUED;
- resendRecord.date =
- utils::time::getCurrentTimestamp().getTime(); // update date sent - it will display an old, failed sms at
- // the the bottom, but this is correct
+ resendRecord.date = std::time(nullptr); // update date sent - it will display an old, failed sms at
+ // the the bottom, but this is correct
using db::query::SMSUpdate;
const auto [succeed, _] =
M module-apps/application-notes/windows/NoteEditWindow.cpp => module-apps/application-notes/windows/NoteEditWindow.cpp +3 -2
@@ 14,11 14,12 @@
#include <module-apps/messages/OptionsWindow.hpp>
#include <i18n/i18n.hpp>
-#include <module-utils/time/time_conversion.hpp>
#include <module-gui/gui/widgets/BottomBar.hpp>
#include <module-gui/gui/widgets/TopBar.hpp>
+#include <ctime>
+
namespace app::notes
{
namespace
@@ 138,7 139,7 @@ namespace app::notes
void NoteEditWindow::saveNote()
{
- notesRecord->date = utils::time::getCurrentTimestamp().getTime();
+ notesRecord->date = std::time(nullptr);
notesRecord->snippet = edit->getText();
presenter->save(*notesRecord);
}
M module-apps/application-onboarding/ApplicationOnBoarding.cpp => module-apps/application-onboarding/ApplicationOnBoarding.cpp +32 -11
@@ 5,7 5,7 @@
#include "ApplicationOnBoarding.hpp"
-#include "windows/OnBoardingMainWindow.hpp"
+#include "data/OnBoardingMessages.hpp"
#include "windows/StartConfigurationWindow.hpp"
#include "windows/OnBoardingLanguagesWindow.hpp"
#include "windows/EULALicenseWindow.hpp"
@@ 23,6 23,8 @@
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-apps/application-settings-new/windows/ChangeTimeZone.hpp>
#include <module-apps/locks/data/PhoneLockMessages.hpp>
+#include <module-apps/locks/data/SimLockMessages.hpp>
+#include <service-appmgr/service-appmgr/model/ApplicationManager.hpp>
namespace app
{
@@ 42,6 44,7 @@ namespace app
bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
bus.channels.push_back(sys::BusChannel::PhoneLockChanges);
+ bus.channels.push_back(sys::BusChannel::ServiceCellularNotifications);
}
// Invoked upon receiving data message
@@ 85,12 88,27 @@ namespace app
return sys::msgHandled();
});
+ connect(typeid(cellular::msg::notification::SimReady), [&](sys::Message *msg) {
+ if (getCurrentWindow()->getName() == gui::window::name::onBoarding_sim_select) {
+ phoneLockSubject.setPhoneLock();
+ return sys::msgHandled();
+ }
+ return sys::msgNotHandled();
+ });
+
return ret;
}
void ApplicationOnBoarding::acceptEULA()
{
- settings->setValue(settings::SystemProperties::eulaAccepted, "1", settings::SettingsScope::Global);
+ settings->setValue(
+ settings::SystemProperties::eulaAccepted, utils::to_string(true), settings::SettingsScope::Global);
+ }
+
+ void ApplicationOnBoarding::finalizeOnBoarding()
+ {
+ bus.sendUnicast(std::make_shared<onBoarding::FinalizeOnBoarding>(),
+ app::manager::ApplicationManager::ServiceName);
}
sys::ReturnCodes ApplicationOnBoarding::DeinitHandler()
@@ 106,9 124,6 @@ namespace app
void ApplicationOnBoarding::createUserInterface()
{
windowsFactory.attach(gui::name::window::main_window, [](Application *app, const std::string &name) {
- return std::make_unique<app::onBoarding::OnBoardingMainWindow>(app);
- });
- windowsFactory.attach(gui::window::name::onBoarding_languages, [](Application *app, const std::string &name) {
return std::make_unique<app::onBoarding::OnBoardingLanguagesWindow>(app);
});
windowsFactory.attach(gui::window::name::onBoarding_start_configuration,
@@ 122,7 137,8 @@ namespace app
return std::make_unique<app::onBoarding::EULALicenseWindow>(app, std::move(presenter));
});
windowsFactory.attach(gui::window::name::onBoarding_sim_select, [](Application *app, const std::string &name) {
- return std::make_unique<gui::OnBoardingSimSelectWindow>(app, gui::window::name::onBoarding_sim_select);
+ return std::make_unique<app::onBoarding::OnBoardingSimSelectWindow>(
+ app, gui::window::name::onBoarding_sim_select);
});
windowsFactory.attach(gui::window::name::onBoarding_no_sim_selected,
[](Application *app, const std::string &name) {
@@ 136,8 152,10 @@ namespace app
[](Application *app, const std::string &name) {
return std::make_unique<app::onBoarding::NoConfigurationDialogWindow>(app);
});
- windowsFactory.attach(gui::window::name::onBoarding_update, [](Application *app, const std::string &name) {
- return std::make_unique<app::onBoarding::UpdateDialogWindow>(app);
+ windowsFactory.attach(gui::window::name::onBoarding_update, [&](Application *app, const std::string &name) {
+ auto presenter =
+ std::make_unique<app::onBoarding::OnBoardingFinalizeWindowPresenter>([&]() { finalizeOnBoarding(); });
+ return std::make_unique<app::onBoarding::UpdateDialogWindow>(app, std::move(presenter));
});
windowsFactory.attach(gui::window::name::onBoarding_skip, [](Application *app, const std::string &name) {
return std::make_unique<app::onBoarding::SkipDialogWindow>(app);
@@ 148,7 166,7 @@ namespace app
});
windowsFactory.attach(gui::window::name::onBoarding_change_date_and_time,
[](Application *app, const std::string &name) {
- return std::make_unique<gui::OnBoardingChangeDateAndTimeWindow>(app);
+ return std::make_unique<app::onBoarding::OnBoardingChangeDateAndTimeWindow>(app);
});
windowsFactory.attach(gui::window::name::change_time_zone, [](Application *app, const std::string &name) {
return std::make_unique<gui::ChangeTimeZone>(app);
@@ 157,8 175,11 @@ namespace app
return std::make_unique<gui::DialogConfirm>(app, gui::window::name::dialog_confirm);
});
- attachPopups(
- {gui::popup::ID::Volume, gui::popup::ID::Tethering, gui::popup::ID::PhoneModes, gui::popup::ID::PhoneLock});
+ attachPopups({gui::popup::ID::Volume,
+ gui::popup::ID::Tethering,
+ gui::popup::ID::PhoneModes,
+ gui::popup::ID::PhoneLock,
+ gui::popup::ID::SimLock});
}
void ApplicationOnBoarding::destroyUserInterface()
M module-apps/application-onboarding/ApplicationOnBoarding.hpp => module-apps/application-onboarding/ApplicationOnBoarding.hpp +1 -0
@@ 38,6 38,7 @@ namespace app
sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;
void acceptEULA();
+ void finalizeOnBoarding();
void createUserInterface() override;
void destroyUserInterface() override;
M module-apps/application-onboarding/CMakeLists.txt => module-apps/application-onboarding/CMakeLists.txt +3 -2
@@ 12,11 12,11 @@ target_sources(${PROJECT_NAME}
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/ApplicationOnBoarding.cpp"
- "${CMAKE_CURRENT_LIST_DIR}/windows/OnBoardingMainWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/StartConfigurationWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/OnBoardingLanguagesWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EULALicenseWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/presenter/EULALicenseWindowPresenter.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/presenter/OnBoardingFinalizeWindowPresenter.cpp"
"${CMAKE_CURRENT_LIST_DIR}/model/EULARepository.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/ConfigurationSuccessfulDialogWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/NoConfigurationDialogWindow.cpp"
@@ 28,12 28,13 @@ target_sources(${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/windows/NoSimSelectedDialogWindow.cpp"
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/ApplicationOnBoarding.hpp"
- "${CMAKE_CURRENT_LIST_DIR}/windows/OnBoardingMainWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/StartConfigurationWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/OnBoardingLanguagesWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/data/OnBoardingSwitchData.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/OnBoardingMessages.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/EULALicenseWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/presenter/EULALicenseWindowPresenter.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/presenter/OnBoardingFinalizeWindowPresenter.hpp"
"${CMAKE_CURRENT_LIST_DIR}/model/EULARepository.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/ConfigurationSuccessfulDialogWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/NoConfigurationDialogWindow.hpp"
A module-apps/application-onboarding/data/OnBoardingMessages.hpp => module-apps/application-onboarding/data/OnBoardingMessages.hpp +12 -0
@@ 0,0 1,12 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Service/Message.hpp>
+
+namespace app::onBoarding
+{
+ class FinalizeOnBoarding : public sys::DataMessage
+ {};
+} // namespace app::onBoarding
A module-apps/application-onboarding/presenter/OnBoardingFinalizeWindowPresenter.cpp => module-apps/application-onboarding/presenter/OnBoardingFinalizeWindowPresenter.cpp +17 -0
@@ 0,0 1,17 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "OnBoardingFinalizeWindowPresenter.hpp"
+
+namespace app::onBoarding
+{
+ OnBoardingFinalizeWindowPresenter::OnBoardingFinalizeWindowPresenter(Function finalizeOnBoarding)
+ : finalizeOnBoardingApp(std::move(finalizeOnBoarding))
+ {}
+
+ void OnBoardingFinalizeWindowPresenter::finalizeOnBoarding()
+ {
+ finalizeOnBoardingApp();
+ }
+
+} // namespace app::onBoarding
A module-apps/application-onboarding/presenter/OnBoardingFinalizeWindowPresenter.hpp => module-apps/application-onboarding/presenter/OnBoardingFinalizeWindowPresenter.hpp +41 -0
@@ 0,0 1,41 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "functional"
+#include "string"
+#include "BasePresenter.hpp"
+
+using Function = std::function<void()>;
+
+namespace app::onBoarding
+{
+ class OnBoardingFinalizeContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() noexcept = default;
+ };
+ class Presenter : public BasePresenter<OnBoardingFinalizeContract::View>
+ {
+ public:
+ ~Presenter() noexcept override = default;
+
+ virtual void finalizeOnBoarding() = 0;
+ };
+ };
+
+ class OnBoardingFinalizeWindowPresenter : public OnBoardingFinalizeContract::Presenter
+ {
+ public:
+ explicit OnBoardingFinalizeWindowPresenter(Function finalizeOnBoarding);
+
+ void finalizeOnBoarding() override;
+
+ private:
+ std::function<void()> finalizeOnBoardingApp;
+ };
+} // namespace app::onBoarding
M module-apps/application-onboarding/windows/ConfigurationSuccessfulDialogWindow.cpp => module-apps/application-onboarding/windows/ConfigurationSuccessfulDialogWindow.cpp +14 -3
@@ 3,12 3,14 @@
#include "ConfigurationSuccessfulDialogWindow.hpp"
-#include <i18n/i18n.hpp>
-#include <Style.hpp>
-
#include <module-apps/application-onboarding/ApplicationOnBoarding.hpp>
#include <module-apps/application-onboarding/data/OnBoardingSwitchData.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
+#include <widgets/IceBox.hpp>
+#include <service-appmgr/Controller.hpp>
+
+#include <i18n/i18n.hpp>
+#include <Style.hpp>
namespace app::onBoarding
{
@@ 17,6 19,8 @@ namespace app::onBoarding
{
bottomBar->setText(gui::BottomBar::Side::CENTER, utils::translate(style::strings::common::start));
bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);
+
+ new gui::IceBox(this);
}
bool ConfigurationSuccessfulDialogWindow::onInput(const gui::InputEvent &inputEvent)
@@ 37,6 41,13 @@ namespace app::onBoarding
if (inputEvent.is(gui::KeyCode::KEY_RF)) {
return true;
}
+
+ if (inputEvent.is(gui::KeyCode::KEY_LEFT)) {
+ app::manager::Controller::sendAction(application,
+ app::manager::actions::EmergencyDial,
+ std::make_unique<gui::SwitchData>(),
+ app::manager::OnSwitchBehaviour::RunInBackground);
+ }
}
return AppWindow::onInput(inputEvent);
}
M module-apps/application-onboarding/windows/NoConfigurationDialogWindow.cpp => module-apps/application-onboarding/windows/NoConfigurationDialogWindow.cpp +15 -3
@@ 3,12 3,14 @@
#include "NoConfigurationDialogWindow.hpp"
-#include <i18n/i18n.hpp>
-#include <Style.hpp>
-
#include <module-apps/application-onboarding/ApplicationOnBoarding.hpp>
#include <module-apps/application-onboarding/data/OnBoardingSwitchData.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
+#include <widgets/IceBox.hpp>
+#include <service-appmgr/Controller.hpp>
+
+#include <i18n/i18n.hpp>
+#include <Style.hpp>
namespace app::onBoarding
{
@@ 17,6 19,8 @@ namespace app::onBoarding
{
bottomBar->setText(gui::BottomBar::Side::CENTER, utils::translate(style::strings::common::start));
bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);
+
+ new gui::IceBox(this);
}
bool NoConfigurationDialogWindow::onInput(const gui::InputEvent &inputEvent)
@@ 37,6 41,14 @@ namespace app::onBoarding
if (inputEvent.is(gui::KeyCode::KEY_RF)) {
return true;
}
+
+ if (inputEvent.is(gui::KeyCode::KEY_LEFT)) {
+ app::manager::Controller::sendAction(application,
+ app::manager::actions::EmergencyDial,
+ std::make_unique<gui::SwitchData>(),
+ app::manager::OnSwitchBehaviour::RunInBackground);
+ return true;
+ }
}
return AppWindow::onInput(inputEvent);
}
M module-apps/application-onboarding/windows/OnBoardingChangeDateAndTimeWindow.cpp => module-apps/application-onboarding/windows/OnBoardingChangeDateAndTimeWindow.cpp +2 -2
@@ 5,7 5,7 @@
#include <module-apps/application-onboarding/ApplicationOnBoarding.hpp>
#include <InputEvent.hpp>
-namespace gui
+namespace app::onBoarding
{
OnBoardingChangeDateAndTimeWindow::OnBoardingChangeDateAndTimeWindow(app::Application *app)
: ChangeDateAndTimeWindow(app, gui::window::name::onBoarding_change_date_and_time)
@@ 22,4 22,4 @@ namespace gui
return ChangeDateAndTimeWindow::onInput(inputEvent);
}
-} /* namespace gui */
+} // namespace app::onBoarding
M module-apps/application-onboarding/windows/OnBoardingChangeDateAndTimeWindow.hpp => module-apps/application-onboarding/windows/OnBoardingChangeDateAndTimeWindow.hpp +4 -4
@@ 6,13 6,13 @@
#include <application-settings-new/windows/ChangeDateAndTimeWindow.hpp>
#include <application-settings-new/models/DateAndTimeModel.hpp>
-namespace gui
+namespace app::onBoarding
{
- class OnBoardingChangeDateAndTimeWindow : public ChangeDateAndTimeWindow
+ class OnBoardingChangeDateAndTimeWindow : public gui::ChangeDateAndTimeWindow
{
public:
explicit OnBoardingChangeDateAndTimeWindow(app::Application *app);
- bool onInput(const InputEvent &inputEvent) override;
+ bool onInput(const gui::InputEvent &inputEvent) override;
};
-} /* namespace gui */
+} // namespace app::onBoarding
M module-apps/application-onboarding/windows/OnBoardingDateAndTimeWindow.cpp => module-apps/application-onboarding/windows/OnBoardingDateAndTimeWindow.cpp +12 -2
@@ 8,11 8,13 @@
#include <module-gui/gui/input/InputEvent.hpp>
#include <module-apps/application-onboarding/data/OnBoardingSwitchData.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
-#include <module-apps/application-settings-new/data/ChangePasscodeData.hpp>
+#include <widgets/IceBox.hpp>
+#include <service-appmgr/Controller.hpp>
namespace app::onBoarding
{
- OnBoardingDateAndTimeWindow::OnBoardingDateAndTimeWindow(app::Application *app) : DateAndTimeMainWindow(app)
+ OnBoardingDateAndTimeWindow::OnBoardingDateAndTimeWindow(app::Application *app)
+ : DateAndTimeMainWindow(app, gui::window::name::onBoarding_date_and_time)
{
changeDateAndTimeWindow = gui::window::name::onBoarding_change_date_and_time;
}
@@ 25,6 27,7 @@ namespace app::onBoarding
void OnBoardingDateAndTimeWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data)
{
DateAndTimeMainWindow::onBeforeShow(mode, data);
+ new gui::IceBox(this);
bottomBar->setText(gui::BottomBar::Side::CENTER, utils::translate(style::strings::common::save));
bottomBar->setText(gui::BottomBar::Side::LEFT, utils::translate(style::strings::common::Switch));
@@ 48,6 51,13 @@ namespace app::onBoarding
std::move(metaData));
return true;
}
+ else if (inputEvent.isShortRelease(gui::KeyCode::KEY_LEFT)) {
+ app::manager::Controller::sendAction(application,
+ app::manager::actions::EmergencyDial,
+ std::make_unique<gui::SwitchData>(),
+ app::manager::OnSwitchBehaviour::RunInBackground);
+ return true;
+ }
else {
return DateAndTimeMainWindow::onInput(inputEvent);
}
M module-apps/application-onboarding/windows/OnBoardingLanguagesWindow.cpp => module-apps/application-onboarding/windows/OnBoardingLanguagesWindow.cpp +13 -2
@@ 1,9 1,12 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "application-onboarding/ApplicationOnBoarding.hpp"
#include "OnBoardingLanguagesWindow.hpp"
+#include <application-onboarding/ApplicationOnBoarding.hpp>
+
+#include <widgets/IceBox.hpp>
#include <module-gui/gui/input/InputEvent.hpp>
+#include <service-appmgr/Controller.hpp>
namespace app::onBoarding
{
@@ 14,6 17,7 @@ namespace app::onBoarding
void OnBoardingLanguagesWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data)
{
bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);
+ new gui::IceBox(this);
LanguagesWindow::onBeforeShow(mode, data);
}
@@ 23,8 27,15 @@ namespace app::onBoarding
if (inputEvent.isShortRelease(gui::KeyCode::KEY_RF)) {
return true;
}
+ else if (inputEvent.isShortRelease(gui::KeyCode::KEY_LEFT)) {
+ app::manager::Controller::sendAction(application,
+ app::manager::actions::EmergencyDial,
+ std::make_unique<gui::SwitchData>(),
+ app::manager::OnSwitchBehaviour::RunInBackground);
+ return true;
+ }
else {
return LanguagesWindow::onInput(inputEvent);
}
}
-} /* namespace gui */
+} // namespace app::onBoarding
D module-apps/application-onboarding/windows/OnBoardingMainWindow.cpp => module-apps/application-onboarding/windows/OnBoardingMainWindow.cpp +0 -52
@@ 1,52 0,0 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include <i18n/i18n.hpp>
-#include <Style.hpp>
-
-#include <InputEvent.hpp>
-
-#include <module-apps/application-onboarding/ApplicationOnBoarding.hpp>
-
-#include "module-apps/application-onboarding/data/OnBoardingSwitchData.hpp"
-#include "OnBoardingMainWindow.hpp"
-
-namespace app::onBoarding
-{
- OnBoardingMainWindow::OnBoardingMainWindow(app::Application *app) : AppWindow(app, gui::name::window::main_window)
- {
- buildInterface();
- }
-
- void OnBoardingMainWindow::buildInterface()
- {
- AppWindow::buildInterface();
-
- bottomBar->setActive(gui::BottomBar::Side::CENTER, true);
- bottomBar->setText(gui::BottomBar::Side::CENTER, utils::translate(::style::strings::common::start));
-
- new gui::Image(this, 0, 0, 0, 0, "logo");
- }
-
- gui::top_bar::Configuration OnBoardingMainWindow::configureTopBar(gui::top_bar::Configuration appConfiguration)
- {
- appConfiguration.setIndicator(gui::top_bar::Indicator::Time, false);
- appConfiguration.setIndicator(gui::top_bar::Indicator::Battery, false);
- appConfiguration.setIndicator(gui::top_bar::Indicator::SimCard, false);
- appConfiguration.setIndicator(gui::top_bar::Indicator::Signal, false);
- return appConfiguration;
- }
-
- bool OnBoardingMainWindow::onInput(const gui::InputEvent &inputEvent)
- {
- if (inputEvent.isShortRelease(gui::KeyCode::KEY_ENTER)) {
- application->switchWindow(gui::window::name::onBoarding_languages,
- gui::ShowMode::GUI_SHOW_INIT,
- std::make_unique<OnBoardingSwitchData>());
-
- return true;
- }
- return AppWindow::onInput(inputEvent);
- }
-
-} // namespace gui
M module-apps/application-onboarding/windows/OnBoardingSimSelectWindow.cpp => module-apps/application-onboarding/windows/OnBoardingSimSelectWindow.cpp +15 -9
@@ 7,9 7,11 @@
#include <application-onboarding/style/OnBoardingStyle.hpp>
#include <OptionSetting.hpp>
+#include <widgets/IceBox.hpp>
+#include <service-appmgr/Controller.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
-namespace gui
+namespace app::onBoarding
{
OnBoardingSimSelectWindow::OnBoardingSimSelectWindow(app::Application *app, std::string name)
: BaseSettingsWindow(app, std::move(name))
@@ 25,6 27,8 @@ namespace gui
bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::translate(::style::strings::common::back));
bottomBar->setText(gui::BottomBar::Side::LEFT, utils::translate(::style::strings::common::skip));
+ new gui::IceBox(this);
+
descriptionText = new gui::Text(this,
style::window::default_left_margin,
style::onboarding::sim_select::description_y,
@@ 33,17 37,12 @@ namespace gui
descriptionText->setFont(style::window::font::medium);
descriptionText->setAlignment(
gui::Alignment{gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top});
- descriptionText->setEdges(RectangleEdge::Top);
+ descriptionText->setEdges(gui::RectangleEdge::Top);
descriptionText->setPenWidth(style::window::default_border_rect_no_focus);
- descriptionText->setPadding(Padding(0, style::onboarding::sim_select::description_top_padding, 0, 0));
+ descriptionText->setPadding(gui::Padding(0, style::onboarding::sim_select::description_top_padding, 0, 0));
descriptionText->setRichText(utils::translate("app_onboarding_select_sim_description"));
}
- void OnBoardingSimSelectWindow::onBeforeShow(ShowMode mode, SwitchData *data)
- {
- refreshOptionsList();
- }
-
auto OnBoardingSimSelectWindow::buildOptionsList() -> std::list<gui::Option>
{
std::list<gui::Option> options;
@@ 97,6 96,13 @@ namespace gui
gui::window::name::onBoarding_skip, gui::ShowMode::GUI_SHOW_INIT, std::move(metaData));
return true;
}
+ else if (inputEvent.isShortRelease(gui::KeyCode::KEY_LEFT)) {
+ app::manager::Controller::sendAction(application,
+ app::manager::actions::EmergencyDial,
+ std::make_unique<gui::SwitchData>(),
+ app::manager::OnSwitchBehaviour::RunInBackground);
+ return true;
+ }
return AppWindow::onInput(inputEvent);
}
-} /* namespace gui */
+} // namespace app::onBoarding
M module-apps/application-onboarding/windows/OnBoardingSimSelectWindow.hpp => module-apps/application-onboarding/windows/OnBoardingSimSelectWindow.hpp +4 -5
@@ 6,9 6,9 @@
#include <application-settings-new/windows/BaseSettingsWindow.hpp>
#include <Text.hpp>
-namespace gui
+namespace app::onBoarding
{
- class OnBoardingSimSelectWindow : public BaseSettingsWindow
+ class OnBoardingSimSelectWindow : public gui::BaseSettingsWindow
{
public:
explicit OnBoardingSimSelectWindow(app::Application *app, std::string name);
@@ 17,8 17,7 @@ namespace gui
private:
gui::Text *descriptionText = nullptr;
- auto buildOptionsList() -> std::list<Option> override;
- void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ auto buildOptionsList() -> std::list<gui::Option> override;
bool onInput(const gui::InputEvent &inputEvent) override;
};
-} /* namespace gui */
+} // namespace app::onBoarding
M module-apps/application-onboarding/windows/StartConfigurationWindow.cpp => module-apps/application-onboarding/windows/StartConfigurationWindow.cpp +9 -0
@@ 8,6 8,8 @@
#include <module-apps/windows/DialogMetadata.hpp>
#include <module-apps/messages/DialogMetadataMessage.hpp>
+#include <widgets/IceBox.hpp>
+#include <service-appmgr/Controller.hpp>
#include <i18n/i18n.hpp>
#include <Style.hpp>
@@ 29,6 31,7 @@ namespace app::onBoarding
bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::translate(::style::strings::common::back));
bottomBar->setText(gui::BottomBar::Side::LEFT, utils::translate(::style::strings::common::skip));
+ new gui::IceBox(this);
new gui::Icon(this,
0,
0,
@@ 51,6 54,12 @@ namespace app::onBoarding
gui::ShowMode::GUI_SHOW_INIT,
std::make_unique<OnBoardingSwitchData>());
}
+ if (inputEvent.is(gui::KeyCode::KEY_LEFT)) {
+ app::manager::Controller::sendAction(application,
+ app::manager::actions::EmergencyDial,
+ std::make_unique<gui::SwitchData>(),
+ app::manager::OnSwitchBehaviour::RunInBackground);
+ }
if (inputEvent.is(gui::KeyCode::KEY_LF)) {
auto metaData = std::make_unique<gui::DialogMetadataMessage>(gui::DialogMetadata{
M module-apps/application-onboarding/windows/UpdateDialogWindow.cpp => module-apps/application-onboarding/windows/UpdateDialogWindow.cpp +7 -8
@@ 6,26 6,25 @@
#include <i18n/i18n.hpp>
#include <Style.hpp>
-#include <module-apps/application-onboarding/ApplicationOnBoarding.hpp>
-#include <module-apps/application-onboarding/data/OnBoardingSwitchData.hpp>
-#include <module-apps/messages/DialogMetadataMessage.hpp>
+#include <application-onboarding/ApplicationOnBoarding.hpp>
+#include <service-appmgr/service-appmgr/Controller.hpp>
namespace app::onBoarding
{
- UpdateDialogWindow::UpdateDialogWindow(app::Application *app)
- : gui::Dialog(app, gui::window::name::onBoarding_update)
+ UpdateDialogWindow::UpdateDialogWindow(app::Application *app,
+ std::unique_ptr<OnBoardingFinalizeContract::Presenter> &&windowPresenter)
+ : gui::Dialog(app, gui::window::name::onBoarding_update), presenter(std::move(windowPresenter))
{
bottomBar->setText(gui::BottomBar::Side::CENTER, utils::translate(style::strings::common::ok));
bottomBar->setActive(gui::BottomBar::Side::RIGHT, false);
+ presenter->attach(this);
}
bool UpdateDialogWindow::onInput(const gui::InputEvent &inputEvent)
{
if (inputEvent.isShortRelease()) {
if (inputEvent.is(gui::KeyCode::KEY_ENTER)) {
- application->switchWindow(gui::window::name::onBoarding_start_configuration,
- gui::ShowMode::GUI_SHOW_INIT,
- std::make_unique<OnBoardingSwitchData>());
+ presenter->finalizeOnBoarding();
return true;
}
if (inputEvent.is(gui::KeyCode::KEY_RF)) {
M module-apps/application-onboarding/windows/UpdateDialogWindow.hpp => module-apps/application-onboarding/windows/UpdateDialogWindow.hpp +8 -7
@@ 5,18 5,19 @@
#include "Dialog.hpp"
-#include <module-apps/application-onboarding/presenter/EULALicenseWindowPresenter.hpp>
-
-#include <module-gui/gui/widgets/Label.hpp>
-#include <module-gui/gui/widgets/Text.hpp>
-#include <module-gui/gui/input/InputEvent.hpp>
+#include <application-onboarding/presenter/EULALicenseWindowPresenter.hpp>
+#include <application-onboarding/presenter/OnBoardingFinalizeWindowPresenter.hpp>
namespace app::onBoarding
{
- class UpdateDialogWindow : public gui::Dialog
+ class UpdateDialogWindow : public gui::Dialog, public OnBoardingFinalizeContract::View
{
+ private:
+ std::unique_ptr<OnBoardingFinalizeContract::Presenter> presenter;
+
public:
- explicit UpdateDialogWindow(app::Application *app);
+ UpdateDialogWindow(app::Application *app,
+ std::unique_ptr<OnBoardingFinalizeContract::Presenter> &&windowPresenter);
bool onInput(const gui::InputEvent &inputEvent) override;
};
M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +12 -24
@@ 146,15 146,9 @@ namespace app
if (ret != sys::ReturnCodes::Success) {
return ret;
}
- connect(typeid(cellular::msg::notification::SimReady), [&](sys::Message *msg) {
- auto simReadyMsg = static_cast<cellular::msg::notification::SimReady *>(msg);
- selectedSim = Store::GSM::get()->selected;
- if (simReadyMsg->ready) {
- CellularServiceAPI::RequestForOwnNumber(this);
- }
- else {
- selectedSimNumber = {};
- }
+ connect(typeid(cellular::msg::notification::SimReady), [&](sys::Message *) {
+ selectedSim = Store::GSM::get()->selected;
+ CellularServiceAPI::RequestForOwnNumber(this);
auto currentWindow = getCurrentWindow();
if (gui::window::name::network == currentWindow->getName()) {
updateWindow(gui::window::name::network, nullptr);
@@ 446,7 440,7 @@ namespace app
return std::make_unique<gui::LanguagesWindow>(app);
});
windowsFactory.attach(gui::window::name::date_and_time, [](Application *app, const std::string &name) {
- return std::make_unique<gui::DateAndTimeMainWindow>(app);
+ return std::make_unique<gui::DateAndTimeMainWindow>(app, gui::window::name::date_and_time);
});
windowsFactory.attach(gui::window::name::about_your_pure, [](Application *app, const std::string &name) {
return std::make_unique<gui::AboutYourPureWindow>(app);
@@ 530,6 524,11 @@ namespace app
getSimLockSubject().setSim(arg);
}
+ void ApplicationSettingsNew::updateSim()
+ {
+ selectedSim = Store::GSM::get()->selected;
+ }
+
Store::GSM::SIM ApplicationSettingsNew::getSim()
{
return selectedSim;
@@ 591,7 590,7 @@ namespace app
return {};
}
- return {msgState->lightOn, msgState->mode, msgState->parameters};
+ return {msgState->isLightOn(), msgState->getMode(), msgState->getParams()};
}
return {};
@@ 599,10 598,8 @@ namespace app
void ApplicationSettingsNew::setBrightness(bsp::eink_frontlight::BrightnessPercentage value)
{
- screen_light_control::Parameters parameters{value};
- bus.sendUnicast(std::make_shared<sevm::ScreenLightSetParameters>(
- screen_light_control::ParameterizedAction::setManualModeBrightness, parameters),
- service::name::evt_manager);
+ screen_light_control::ManualModeParameters parameters{value};
+ bus.sendUnicast(std::make_shared<sevm::ScreenLightSetManualModeParams>(parameters), service::name::evt_manager);
}
void ApplicationSettingsNew::setMode(bool isAutoLightSwitchOn)
@@ 620,15 617,6 @@ namespace app
: screen_light_control::Action::turnOff),
service::name::evt_manager);
}
- void ApplicationSettingsNew::setBrightnessFunction()
- {
- screen_light_control::Parameters parameters;
- parameters.functionPoints = screen_light_control::functions::BrightnessFunction(
- {{0.0f, 70.0f}, {250.0f, 70.0f}, {450.0f, 40.0f}, {500.0f, 0.0f}});
- bus.sendUnicast(std::make_shared<sevm::ScreenLightSetParameters>(
- screen_light_control::ParameterizedAction::setAutomaticModeParameters, parameters),
- service::name::evt_manager);
- }
auto ApplicationSettingsNew::getKeypadBacklightState() -> bsp::keypad_backlight::State
{
M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +5 -5
@@ 90,6 90,7 @@ namespace app
public:
virtual ~SimParams() = default;
virtual void setSim(Store::GSM::SIM sim) = 0;
+ virtual void updateSim() = 0;
virtual Store::GSM::SIM getSim() = 0;
virtual std::string getNumber() = 0;
};
@@ 109,15 110,14 @@ namespace app
{
bool lightOn;
screen_light_control::ScreenLightMode mode;
- screen_light_control::Parameters parameters;
+ screen_light_control::ManualModeParameters parameters;
};
virtual ~ScreenLightSettings() = default;
virtual auto getCurrentValues() -> Values = 0;
- virtual void setBrightness(float brigtnessValue) = 0;
+ virtual void setBrightness(float brightnessValue) = 0;
virtual void setMode(bool isAutoLightSwitchOn) = 0;
virtual void setStatus(bool isDisplayLightSwitchOn) = 0;
- virtual void setBrightnessFunction() = 0;
};
class KeypdBacklightSettings
@@ 202,6 202,7 @@ namespace app
void createUserInterface() override;
void destroyUserInterface() override;
void setSim(Store::GSM::SIM sim) override;
+ void updateSim() override;
Store::GSM::SIM getSim() override;
std::string getNumber() override;
@@ 214,10 215,9 @@ namespace app
void setOsUpdateVersion(const std::string &value);
ScreenLightSettings::Values getCurrentValues() override;
- void setBrightness(float brigtnessValue) override;
+ void setBrightness(float brightnessValue) override;
void setMode(bool isAutoLightSwitchOn) override;
void setStatus(bool isDisplayLightSwitchOn) override;
- void setBrightnessFunction() override;
auto getKeypadBacklightState() -> bsp::keypad_backlight::State override;
void setKeypadBacklightState(bsp::keypad_backlight::State keypadLightState) override;
M module-apps/application-settings-new/windows/ChangeDateAndTimeWindow.cpp => module-apps/application-settings-new/windows/ChangeDateAndTimeWindow.cpp +4 -4
@@ 5,8 5,8 @@
#include <application-settings-new/ApplicationSettings.hpp>
#include <gui/input/InputEvent.hpp>
#include <ListView.hpp>
-#include <service-evtmgr/service-evtmgr/Constants.hpp>
-#include <service-evtmgr/service-evtmgr/EVMessages.hpp>
+#include <service-time/Constants.hpp>
+#include <service-time/service-time/TimeMessage.hpp>
#include <widgets/DateAndTimeStyle.hpp>
namespace gui
@@ 64,7 64,7 @@ namespace gui
void ChangeDateAndTimeWindow::sendRtcUpdateTimeMessage()
{
- auto msg = std::make_shared<sevm::RtcUpdateTimeMessage>(TimePointToTimeT(fromTillDate->from));
- application->bus.sendUnicast(std::move(msg), service::name::evt_manager);
+ auto msg = std::make_shared<stm::message::TimeChangeRequestMessage>(TimePointToTimeT(fromTillDate->from));
+ application->bus.sendUnicast(std::move(msg), service::name::service_time);
}
} /* namespace gui */
M module-apps/application-settings-new/windows/DateAndTimeMainWindow.cpp => module-apps/application-settings-new/windows/DateAndTimeMainWindow.cpp +2 -2
@@ 10,8 10,8 @@
namespace gui
{
- DateAndTimeMainWindow::DateAndTimeMainWindow(app::Application *app)
- : BaseSettingsWindow(app, window::name::date_and_time)
+ DateAndTimeMainWindow::DateAndTimeMainWindow(app::Application *app, std::string name)
+ : BaseSettingsWindow(app, std::move(name))
{
setTitle(utils::translate("app_settings_date_and_time"));
automaticDateAndTimeIsOn = utils::dateAndTimeSettings.isAutomaticDateAndTimeOn();
M module-apps/application-settings-new/windows/DateAndTimeMainWindow.hpp => module-apps/application-settings-new/windows/DateAndTimeMainWindow.hpp +1 -1
@@ 11,7 11,7 @@ namespace gui
class DateAndTimeMainWindow : public BaseSettingsWindow
{
public:
- explicit DateAndTimeMainWindow(app::Application *app);
+ DateAndTimeMainWindow(app::Application *app, std::string name);
protected:
auto buildOptionsList() -> std::list<Option> override;
M module-apps/application-settings-new/windows/DisplayLightWindow.cpp => module-apps/application-settings-new/windows/DisplayLightWindow.cpp +1 -3
@@ 23,8 23,6 @@ namespace gui
setTitle(utils::translate("app_settings_display_display_light"));
- screenLightSettings->setBrightnessFunction();
-
timerCallback = [this](Item &it, sys::Timer &task) { return onTimerTimeout(it, task); };
timerTask = app::GuiTimerFactory::createPeriodicTimer(
application, this, "AmbientLightTimer", std::chrono::milliseconds{gui::lighting::AMBIENT_LIGHT_TIMER_MS});
@@ 122,7 120,7 @@ namespace gui
auto spinner = std::make_unique<gui::SpinBoxOptionSettings>(
utils::translate("app_settings_display_light_brightness"),
std::ceil(brightnessValue / brightnessStep),
- std::ceil(screen_light_control::Parameters::MAX_BRIGHTNESS / brightnessStep),
+ std::ceil(screen_light_control::ManualModeParameters::MAX_BRIGHTNESS / brightnessStep),
setBrightness,
setBottomBarOnSpinnerFocus);
M module-apps/application-settings-new/windows/NetworkWindow.cpp => module-apps/application-settings-new/windows/NetworkWindow.cpp +6 -0
@@ 18,6 18,12 @@ namespace gui
operatorsSettings(operatorsSettings)
{}
+ void NetworkWindow::onBeforeShow(ShowMode mode, SwitchData *data)
+ {
+ simParams->updateSim();
+ BaseSettingsWindow::onBeforeShow(mode, data);
+ }
+
auto NetworkWindow::buildOptionsList() -> std::list<gui::Option>
{
std::list<gui::Option> optList;
M module-apps/application-settings-new/windows/NetworkWindow.hpp => module-apps/application-settings-new/windows/NetworkWindow.hpp +3 -1
@@ 23,7 23,7 @@ namespace gui
class NetworkWindow : public BaseSettingsWindow
{
private:
- auto buildOptionsList() -> std::list<Option>;
+ auto buildOptionsList() -> std::list<Option> override;
app::settingsInterface::SimParams *simParams;
app::settingsInterface::OperatorsSettings *operatorsSettings;
@@ 31,5 31,7 @@ namespace gui
NetworkWindow(app::Application *app,
app::settingsInterface::SimParams *simParams,
app::settingsInterface::OperatorsSettings *operatorsSettings);
+
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
};
} // namespace gui
M module-apps/application-settings/windows/DateTimeWindow.cpp => module-apps/application-settings/windows/DateTimeWindow.cpp +1 -1
@@ 58,7 58,7 @@ namespace gui
// create date widgets
uint32_t w = this->getWidth();
- utils::time::Timestamp time;
+ utils::time::Timestamp time = utils::time::getCurrentTimestamp();
// create date widgets
dateBody = new gui::HBox(this,
M module-apps/locks/data/LockStyle.hpp => module-apps/locks/data/LockStyle.hpp +0 -16
@@ 22,22 22,6 @@ namespace style::window::lock_input
constexpr inline auto top_margin = 30;
} // namespace pin_label
- namespace ice
- {
- constexpr inline auto x = style::window::default_left_margin;
- constexpr inline auto y = 60;
- constexpr inline auto w = 60;
- constexpr inline auto h = 50;
-
- constexpr inline auto margin = 3;
-
- namespace text
- {
- constexpr inline auto w = 40;
- }
-
- } // namespace ice
-
namespace primary_text
{
constexpr inline auto h = 60;
M module-apps/locks/data/PhoneLockMessages.hpp => module-apps/locks/data/PhoneLockMessages.hpp +37 -0
@@ 57,4 57,41 @@ namespace locks
return inputData;
}
};
+
+ class ExternalUnLockPhone : public UnLockPhoneInput
+ {
+ public:
+ explicit ExternalUnLockPhone(std::vector<unsigned int> inputData) : UnLockPhoneInput(std::move(inputData))
+ {}
+ };
+
+ class ExternalPhoneLockAvailabilityChange : public sys::DataMessage
+ {
+ private:
+ bool value = true;
+
+ public:
+ explicit ExternalPhoneLockAvailabilityChange(bool value) : value(value)
+ {}
+
+ [[nodiscard]] auto getAvailability() const noexcept
+ {
+ return value;
+ }
+ };
+
+ class ExternalUnLockPhoneInfo : public sys::DataMessage
+ {
+ private:
+ unsigned int attemptsLeft;
+
+ public:
+ explicit ExternalUnLockPhoneInfo(unsigned int attemptsLeft) : DataMessage{}, attemptsLeft(attemptsLeft)
+ {}
+
+ [[nodiscard]] auto getAttemptsLeft() const noexcept
+ {
+ return attemptsLeft;
+ }
+ };
} // namespace locks
M module-apps/locks/handlers/PhoneLockHandler.cpp => module-apps/locks/handlers/PhoneLockHandler.cpp +54 -6
@@ 66,6 66,10 @@ namespace locks
app::manager::Controller::sendAction(owner,
app::manager::actions::AbortPopup,
std::make_unique<gui::PopupRequestParams>(gui::popup::ID::PhoneLock));
+ app::manager::Controller::sendAction(
+ owner,
+ app::manager::actions::AbortPopup,
+ std::make_unique<gui::PopupRequestParams>(gui::popup::ID::PhoneLockInfo));
}
}
@@ 121,6 125,12 @@ namespace locks
gui::popup::ID::PhoneLockChangeInfo, lock, phoneLockInputTypeAction));
}
+ void PhoneLockHandler::phoneExternalUnlockInfoAction()
+ {
+ owner->bus.sendMulticast(std::make_shared<locks::ExternalUnLockPhoneInfo>(lock.getAttemptsLeft()),
+ sys::BusChannel::PhoneLockChanges);
+ }
+
void PhoneLockHandler::setPhoneLockInSettings()
{
phoneLockHash = getHash(storedInputData);
@@ 234,7 244,7 @@ namespace locks
phoneInputRequiredAction();
}
- sys::MessagePointer PhoneLockHandler::verifyPhoneLockInput(LockInput inputData)
+ sys::MessagePointer PhoneLockHandler::handlePhoneLockInput(LockInput inputData)
{
if (checkPhoneLockInputTypeAction(PhoneLockInputTypeAction::Enable) ||
checkPhoneLockInputTypeAction(PhoneLockInputTypeAction::Change) ||
@@ 246,7 256,7 @@ namespace locks
}
}
- sys::MessagePointer PhoneLockHandler::verifyPhoneUnlockInput(LockInput inputData)
+ void PhoneLockHandler::comparePhoneLockHashCode(LockInput inputData)
{
const uint32_t hash = getHash(inputData);
lock.attemptsLeft--;
@@ 254,8 264,6 @@ namespace locks
if (phoneLockHash == hash) {
lock.lockState = Lock::LockState::Unlocked;
lock.attemptsLeft = default_attempts;
- resolvePhoneLockAction();
- return sys::msgHandled();
}
else if (lock.attemptsLeft > 0) {
lock.lockState = Lock::LockState::InputInvalid;
@@ 263,8 271,18 @@ namespace locks
else {
lock.lockState = Lock::LockState::Blocked;
}
+ }
- phoneInputRequiredAction();
+ sys::MessagePointer PhoneLockHandler::verifyPhoneUnlockInput(LockInput inputData)
+ {
+ comparePhoneLockHashCode(inputData);
+
+ if (lock.isState(Lock::LockState::Unlocked)) {
+ resolvePhoneLockAction();
+ }
+ else {
+ phoneInputRequiredAction();
+ }
return sys::msgHandled();
}
@@ 287,7 305,37 @@ namespace locks
phoneInputRequiredAction();
- return sys::MessagePointer();
+ return sys::msgHandled();
+ }
+
+ sys::MessagePointer PhoneLockHandler::handleExternalUnlockRequest(LockInput inputData)
+ {
+ if (!phoneLockEnabled) {
+ phoneUnlockAction();
+ return sys::msgHandled();
+ }
+
+ if (lock.isState(Lock::LockState::Blocked)) {
+ phoneExternalUnlockInfoAction();
+ return sys::msgHandled();
+ }
+
+ comparePhoneLockHashCode(inputData);
+
+ if (lock.isState(Lock::LockState::Unlocked)) {
+ phoneUnlockAction();
+ }
+ else {
+ phoneExternalUnlockInfoAction();
+ }
+
+ return sys::msgHandled();
+ }
+
+ sys::MessagePointer PhoneLockHandler::handleExternalAvailabilityChange(bool value)
+ {
+ setPhoneLockAvailabilityInSettings(value);
+ return sys::msgHandled();
}
void PhoneLockHandler::resolvePhoneLockAction()
M module-apps/locks/handlers/PhoneLockHandler.hpp => module-apps/locks/handlers/PhoneLockHandler.hpp +5 -1
@@ 45,10 45,12 @@ namespace locks
void phoneInputRequiredAction();
void phoneUnlockPopupsCloseAction();
void phoneLockChangeInfoAction();
+ void phoneExternalUnlockInfoAction();
void checkNewPhoneLock();
void resolvePhoneLockAction();
+ void comparePhoneLockHashCode(LockInput inputData);
sys::MessagePointer verifyPhoneUnlockInput(LockInput inputData);
sys::MessagePointer verifyPhoneLockChangeInput(LockInput inputData);
@@ 63,7 65,9 @@ namespace locks
sys::MessagePointer handleChangePhoneLock();
sys::MessagePointer handleSetPhoneLock();
sys::MessagePointer handleSkipSetPhoneLock();
- sys::MessagePointer verifyPhoneLockInput(LockInput inputData);
+ sys::MessagePointer handlePhoneLockInput(LockInput inputData);
+ sys::MessagePointer handleExternalUnlockRequest(LockInput inputData);
+ sys::MessagePointer handleExternalAvailabilityChange(bool value);
void enablePhoneLock(bool _phoneLockEnabled);
void setPhoneLockHash(const std::string &value);
M module-apps/locks/handlers/SimLockHandler.cpp => module-apps/locks/handlers/SimLockHandler.cpp +58 -7
@@ 4,13 4,13 @@
#include "SimLockHandler.hpp"
#include <service-appmgr/service-appmgr/Controller.hpp>
-#include <locks/widgets/LockHash.hpp>
#include <Utils.hpp>
#include <memory>
#include <module-apps/popups/data/PopupRequestParams.hpp>
-#include <service-cellular-api>
#include <module-utils/common_data/EventStore.hpp>
+#include <module-sys/Timers/TimerFactory.hpp>
+#include <service-cellular-api>
namespace locks
{
@@ 22,6 22,11 @@ namespace locks
: owner(owner), lock(Lock::LockState::Unlocked, default_attempts)
{
lock.setInputSizeBounds(min_input_size, max_input_size);
+
+ simResponseTimer = sys::TimerFactory::createSingleShotTimer(
+ owner, simResponseTimerName, std::chrono::seconds{1}, [this](sys::Timer &) {
+ handleSimNotRespondingMessage();
+ });
}
void SimLockHandler::clearStoredInputs()
@@ 32,6 37,8 @@ namespace locks
void SimLockHandler::setSimInputTypeAction(SimInputTypeAction _simInputTypeAction)
{
+ simResponseTimer.stop();
+
if (simInputTypeAction != _simInputTypeAction) {
simInputTypeAction = _simInputTypeAction;
lock.lockState = Lock::LockState::Unlocked;
@@ 61,6 68,20 @@ namespace locks
std::make_unique<gui::PopupRequestParams>(gui::popup::ID::SimLock));
}
+ void SimLockHandler::simNotReadyAction()
+ {
+ app::manager::Controller::sendAction(owner,
+ app::manager::actions::ShowPopup,
+ std::make_unique<gui::PopupRequestParams>(gui::popup::ID::SimNotReady));
+ }
+
+ void SimLockHandler::simReadyAction()
+ {
+ app::manager::Controller::sendAction(owner,
+ app::manager::actions::AbortPopup,
+ std::make_unique<gui::PopupRequestParams>(gui::popup::ID::SimNotReady));
+ }
+
void SimLockHandler::simInfoAction()
{
app::manager::Controller::sendAction(
@@ 71,10 92,10 @@ namespace locks
void SimLockHandler::getSettingsSimSelect(const std::string &settingsSim)
{
- auto selectedSim = magic_enum::enum_cast<Store::GSM::SIM>(settingsSim);
- Store::GSM::get()->selected = selectedSim.value();
+ auto selectedSim = magic_enum::enum_cast<Store::GSM::SIM>(settingsSim);
- if ((selectedSim.value() == Store::GSM::SIM::SIM1 || selectedSim.value() == Store::GSM::SIM::SIM2)) {
+ if (selectedSim.has_value() &&
+ (selectedSim.value() == Store::GSM::SIM::SIM1 || selectedSim.value() == Store::GSM::SIM::SIM2)) {
setSim(static_cast<cellular::api::SimSlot>(selectedSim.value()));
}
else {
@@ 84,7 105,14 @@ namespace locks
void SimLockHandler::setSim(cellular::api::SimSlot simSlot)
{
- owner->bus.sendUnicast<cellular::msg::request::sim::SetActiveSim>(simSlot);
+ if (simReady) {
+ simResponseTimer.start();
+ Store::GSM::get()->selected = static_cast<Store::GSM::SIM>(simSlot);
+ owner->bus.sendUnicast<cellular::msg::request::sim::SetActiveSim>(simSlot);
+ }
+ else {
+ simNotReadyAction();
+ }
}
sys::MessagePointer SimLockHandler::handleSimPinRequest(unsigned int attempts)
@@ 147,7 175,7 @@ namespace locks
return sys::msgHandled();
}
- sys::MessagePointer SimLockHandler::handleSimChangedMessage()
+ sys::MessagePointer SimLockHandler::handleSimPinChangedMessage()
{
lock.lockState = Lock::LockState::Unlocked;
simInfoAction();
@@ 240,6 268,22 @@ namespace locks
return sys::msgHandled();
}
+ sys::MessagePointer SimLockHandler::handleSimReadyMessage()
+ {
+ simResponseTimer.stop();
+ return sys::msgHandled();
+ }
+
+ sys::MessagePointer SimLockHandler::handleSimNotRespondingMessage()
+ {
+ setSimInputTypeAction(SimInputTypeAction::Error);
+
+ lock.lockName = utils::enumToString(Store::GSM::get()->selected);
+ simInfoAction();
+
+ return sys::msgHandled();
+ }
+
sys::MessagePointer SimLockHandler::processLockWithNewInput(LockInput inputData)
{
if (lock.isState(Lock::LockState::InputRequired) || (lock.isState(Lock::LockState::InputInvalid))) {
@@ 289,6 333,12 @@ namespace locks
simUnlockBlockOnLockedPhone = true;
}
+ void SimLockHandler::setSimReady()
+ {
+ simReady = true;
+ simReadyAction();
+ }
+
sys::MessagePointer SimLockHandler::releaseSimUnlockBlockOnLockedPhone()
{
if (simUnlockBlockOnLockedPhone) {
@@ 351,4 401,5 @@ namespace locks
pinInputData);
return sys::msgHandled();
}
+
} // namespace locks
M module-apps/locks/handlers/SimLockHandler.hpp => module-apps/locks/handlers/SimLockHandler.hpp +13 -2
@@ 8,10 8,12 @@
#include <locks/data/LockData.hpp>
#include <module-sys/Service/Service.hpp>
+#include <Timers/TimerHandle.hpp>
namespace locks
{
- using StoredLockInput = std::vector<unsigned int>;
+ using StoredLockInput = std::vector<unsigned int>;
+ constexpr auto simResponseTimerName = "SimResponseTimer";
class SimLockHandler
{
@@ 22,9 24,12 @@ namespace locks
SimInputTypeAction simInputTypeAction = SimInputTypeAction::UnlockWithPin;
unsigned int storedErrorCode = 0;
bool simUnlockBlockOnLockedPhone = false;
+ bool simReady = false;
StoredLockInput storedFirstInput;
StoredLockInput storedSecondInput;
+ sys::TimerHandle simResponseTimer;
+
void clearStoredInputs();
void setSimInputTypeAction(SimInputTypeAction _simInputTypeAction);
@@ 32,6 37,8 @@ namespace locks
void simErrorAction(unsigned int errorCode);
void simUnlockAction();
void simInfoAction();
+ void simNotReadyAction();
+ void simReadyAction();
sys::MessagePointer unlockSimWithPin(LockInput pinInputData);
sys::MessagePointer processLockWithNewInput(LockInput inputData);
@@ 45,6 52,8 @@ namespace locks
explicit SimLockHandler(sys::Service *owner);
void setSimUnlockBlockOnLockedPhone();
+ void setSimReady();
+
sys::MessagePointer releaseSimUnlockBlockOnLockedPhone();
sys::MessagePointer verifySimLockInput(LockInput inputData);
@@ 58,8 67,10 @@ namespace locks
sys::MessagePointer handleSimBlockedRequest();
sys::MessagePointer handleCMEErrorRequest(unsigned int errorCode);
sys::MessagePointer handleSimUnlockedMessage();
- sys::MessagePointer handleSimChangedMessage();
+ sys::MessagePointer handleSimPinChangedMessage();
sys::MessagePointer handleSimAvailabilityMessage();
+ sys::MessagePointer handleSimReadyMessage();
+ sys::MessagePointer handleSimNotRespondingMessage();
void getSettingsSimSelect(const std::string &settingsSim);
void setSim(cellular::api::SimSlot simSlot);
M module-apps/locks/widgets/PhoneLockBox.cpp => module-apps/locks/widgets/PhoneLockBox.cpp +1 -1
@@ 36,7 36,7 @@ namespace gui
leftBottomBarState = false;
break;
case locks::PhoneLockInputTypeAction::Set:
- LockWindow->setTitleBar(true, false);
+ LockWindow->setTitleBar(true, true);
LockWindow->setText("phone_lock_configure", LockInputWindow::TextType::Title);
textForInputRequired = "phone_lock_current";
M module-apps/locks/windows/LockInputWindow.cpp => module-apps/locks/windows/LockInputWindow.cpp +7 -19
@@ 72,25 72,7 @@ namespace gui
void LockInputWindow::buildIceBox()
{
- using namespace style::window::lock_input;
-
- iceBox = new gui::HBox(this, ice::x, ice::y, ice::w, ice::h);
- iceBox->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
- iceBox->setEdges(RectangleEdge::None);
- iceBox->setVisible(false);
-
- auto arrow = new gui::Image("left_label_arrow");
- arrow->activeItem = false;
- arrow->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
- arrow->setMargins(Margins(0, 0, ice::margin, 0));
- iceBox->addWidget(arrow);
-
- auto iceText = new gui::Text(nullptr, 0, 0, ice::text::w, ice::h);
- iceText->activeItem = false;
- iceText->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
- iceText->setFont(style::window::font::verysmall);
- iceText->setText(utils::translate("app_desktop_emergency"));
- iceBox->addWidget(iceText);
+ iceBox = new gui::IceBox(this);
}
void LockInputWindow::buildPinBody()
@@ 232,6 214,11 @@ namespace gui
}
}
+ auto LockInputWindow::isIceVisible() const noexcept -> bool
+ {
+ return iceBox->visible;
+ }
+
auto LockInputWindow::isInInputState() const noexcept -> bool
{
return lock && (lock->isState(locks::Lock::LockState::InputRequired) ||
@@ 244,4 231,5 @@ namespace gui
return lock && (lock->isState(locks::Lock::LockState::InputInvalid) ||
lock->isState(locks::Lock::LockState::NewInputInvalid));
}
+
} // namespace gui
M module-apps/locks/windows/LockInputWindow.hpp => module-apps/locks/windows/LockInputWindow.hpp +3 -1
@@ 9,6 9,7 @@
#include <RichTextParser.hpp>
#include <Text.hpp>
#include <ImageBox.hpp>
+#include <widgets/IceBox.hpp>
namespace locks
{
@@ 62,10 63,11 @@ namespace gui
[[nodiscard]] auto isInInputState() const noexcept -> bool;
[[nodiscard]] auto isInInvalidInputState() const noexcept -> bool;
+ [[nodiscard]] auto isIceVisible() const noexcept -> bool;
private:
gui::VBox *body = nullptr;
- gui::HBox *iceBox = nullptr;
+ gui::IceBox *iceBox = nullptr;
gui::ImageBox *infoImage = nullptr;
gui::Text *primaryText = nullptr;
gui::Text *secondaryText = nullptr;
M module-apps/notifications/NotificationsModel.cpp => module-apps/notifications/NotificationsModel.cpp +17 -2
@@ 20,6 20,15 @@ namespace
item->setName(utils::translate(text), true);
}
}
+
+ bool hasTetheringNotification(app::manager::actions::NotificationsChangedParams *params)
+ {
+ const auto ¬ifications = params->getNotifications();
+ const auto it = std::find_if(std::begin(notifications), std::end(notifications), [](const auto ¬ification) {
+ return notification->getType() == notifications::NotificationType::Tethering;
+ });
+ return it != std::end(notifications);
+ }
} // namespace
unsigned int NotificationsModel::requestRecordsCount()
@@ 104,12 113,13 @@ void NotificationsModel::updateData(app::manager::actions::NotificationsChangedP
delete item;
}
};
+ tetheringOn = hasTetheringNotification(params);
for (const auto ¬ification : params->getNotifications()) {
- if (typeid(*notification) == typeid(notifications::NotSeenSMSNotification)) {
+ if (not tetheringOn && typeid(*notification) == typeid(notifications::NotSeenSMSNotification)) {
auto sms = static_cast<const notifications::NotSeenSMSNotification *>(notification.get());
internalData.push_back(create(sms));
}
- else if (typeid(*notification) == typeid(notifications::NotSeenCallNotification)) {
+ else if (not tetheringOn && typeid(*notification) == typeid(notifications::NotSeenCallNotification)) {
auto call = static_cast<const notifications::NotSeenCallNotification *>(notification.get());
internalData.push_back(create(call));
}
@@ 128,3 138,8 @@ void NotificationsModel::clearAll()
list->reset();
eraseInternalData();
}
+
+bool NotificationsModel::isTetheringOn() const noexcept
+{
+ return tetheringOn;
+}
M module-apps/notifications/NotificationsModel.hpp => module-apps/notifications/NotificationsModel.hpp +2 -0
@@ 22,6 22,7 @@ namespace gui
void requestRecords(uint32_t offset, uint32_t limit) final;
protected:
+ bool tetheringOn = false;
[[nodiscard]] virtual auto create(const notifications::NotSeenSMSNotification *notification)
-> NotificationListItem *;
[[nodiscard]] virtual auto create(const notifications::NotSeenCallNotification *notification)
@@ 32,6 33,7 @@ namespace gui
public:
[[nodiscard]] bool isEmpty() const noexcept;
[[nodiscard]] bool hasDismissibleNotification() const noexcept;
+ [[nodiscard]] bool isTetheringOn() const noexcept;
void updateData(app::manager::actions::NotificationsChangedParams *params);
void dismissAll(const InputEvent &event);
M => +3 -0
@@ 21,6 21,7 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/TetheringConfirmationPopup.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TetheringNotificationPopup.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TetheringPhoneModePopup.cpp"
"${CMAKE_CURRENT_LIST_DIR}/TetheringOffPopup.cpp"
"${CMAKE_CURRENT_LIST_DIR}/PowerOffWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/presenter/PowerOffPresenter.cpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockedInfoWindow.cpp"
@@ 29,6 30,7 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockChangeInfoWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/SimLockInputWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/SimInfoWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/SimNotReadyWindow.cpp"
PRIVATE
"${CMAKE_CURRENT_LIST_DIR}/Popups.hpp"
@@ 47,4 49,5 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/PhoneLockChangeInfoWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/SimLockInputWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/SimInfoWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/lock-popups/SimNotReadyWindow.hpp"
)
M => +4 -0
@@ 22,12 22,16 @@ namespace gui::popup
return gui::popup::window::phone_lock_window;
case ID::PhoneLockInput:
return gui::popup::window::phone_lock_input_window;
case ID::PhoneLockInfo:
return gui::popup::window::phone_lock_info_window;
case ID::PhoneLockChangeInfo:
return gui::popup::window::phone_lock_change_info_window;
case ID::SimLock:
return gui::popup::window::sim_unlock_window;
case ID::SimInfo:
return gui::popup::window::sim_info_window;
case ID::SimNotReady:
return gui::popup::window::sim_not_ready_window;
}
return {};
M => +4 -1
@@ 18,9 18,11 @@ namespace gui
TetheringPhoneModeChangeProhibited,
PhoneLock,
PhoneLockInput,
PhoneLockInfo,
PhoneLockChangeInfo,
SimLock,
SimInfo,
SimNotReady,
};
namespace window
@@ 30,6 32,7 @@ namespace gui
inline constexpr auto brightness_window = "BrightnessPopup";
inline constexpr auto tethering_confirmation_window = "TetheringConfirmationPopup";
inline constexpr auto tethering_phonemode_change_window = "TetheringPhoneModeChangeProhibitedPopup";
inline constexpr auto tethering_off_window = "TetheringOffPopup";
inline constexpr auto phone_lock_window = "PhoneLockPopup";
inline constexpr auto phone_lock_info_window = "PhoneLockInfoPopup";
inline constexpr auto phone_lock_input_window = "PhoneLockInputPopup";
@@ 37,7 40,7 @@ namespace gui
inline constexpr auto power_off_window = "PowerOffPopup";
inline constexpr auto sim_unlock_window = "SimUnlockPopup";
inline constexpr auto sim_info_window = "SimInfoPopup";
inline constexpr auto sim_not_ready_window = "SimNotReadyPopup";
} // namespace window
std::string resolveWindowName(ID id);
A => +45 -0
@@ 0,0 1,45 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "TetheringOffPopup.hpp"
#include <log/log.hpp>
#include <messages/DialogMetadataMessage.hpp>
#include <module-apps/Application.hpp>
#include <SystemManager/messages/TetheringStateRequest.hpp>
#include <service-appmgr/Controller.hpp>
namespace gui
{
TetheringOffPopup::TetheringOffPopup(app::Application *app, const std::string &name) : DialogYesNo{app, name}
{
topBar->configure(configureTopBar(application->getTopBarConfiguration()));
}
top_bar::Configuration TetheringOffPopup::configureTopBar(top_bar::Configuration appConfiguration)
{
appConfiguration.enable(top_bar::Indicator::Time);
appConfiguration.disable(top_bar::Indicator::Lock);
appConfiguration.disable(top_bar::Indicator::Battery);
appConfiguration.disable(top_bar::Indicator::Signal);
appConfiguration.disable(top_bar::Indicator::SimCard);
return appConfiguration;
}
void TetheringOffPopup::onBeforeShow(ShowMode mode, SwitchData *data)
{
DialogMetadata metadata;
metadata.action = [this]() {
application->bus.sendUnicast(std::make_shared<sys::TetheringStateRequest>(sys::phone_modes::Tethering::Off),
service::name::system_manager);
app::manager::Controller::sendAction(application, app::manager::actions::Home);
return true;
};
metadata.title = utils::translate("tethering");
metadata.text = utils::translate("tethering_turn_off_question");
metadata.icon = "tethering_icon";
auto msg = std::make_unique<DialogMetadataMessage>(std::move(metadata));
DialogYesNo::onBeforeShow(mode, msg.get());
}
} /* namespace gui */
A => +18 -0
@@ 0,0 1,18 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <windows/Dialog.hpp>
namespace gui
{
class TetheringOffPopup : public DialogYesNo
{
public:
TetheringOffPopup(app::Application *app, const std::string &name);
top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
void onBeforeShow(ShowMode mode, SwitchData *data) override;
};
} // namespace gui
M => +7 -1
@@ 101,7 101,6 @@ namespace gui
return true;
}
}
else if (inputEvent.is(KeyCode::KEY_ENTER) && bottomBar->isActive(BottomBar::Side::CENTER)) {
if (lock->isState(locks::Lock::LockState::Blocked)) {
application->returnToPreviousWindow();
@@ 119,6 118,13 @@ namespace gui
lock->clearAttempt();
return true;
}
else if (inputEvent.is(KeyCode::KEY_LEFT) && isIceVisible()) {
app::manager::Controller::sendAction(application,
app::manager::actions::EmergencyDial,
std::make_unique<gui::SwitchData>(),
app::manager::OnSwitchBehaviour::RunInBackground);
return true;
}
// check if any of the lower inheritance onInput methods catch the event
return AppWindow::onInput(inputEvent);
M => +0 -2
@@ 5,7 5,6 @@
#include <service-appmgr/Controller.hpp>
#include <application-desktop/data/DesktopStyle.hpp>
#include <locks/data/LockStyle.hpp>
#include <i18n/i18n.hpp>
@@ 49,7 48,6 @@ top_bar::Configuration PhoneLockedInfoWindow::configureTopBar(top_bar::Configura
void PhoneLockedInfoWindow::buildInterface()
{
namespace lock_style = style::window::lock_input;
AppWindow::buildInterface();
bottomBar->setText(BottomBar::Side::LEFT, utils::translate("app_desktop_emergency"));
M => +1 -1
@@ 147,7 147,7 @@ namespace gui
{
using namespace utils::time;
auto ret = AppWindow::updateTime();
auto timestamp = utils::time::Timestamp();
auto timestamp = utils::time::getCurrentTimestamp();
if (time != nullptr) {
auto fmt = utils::dateAndTimeSettings.isTimeFormat12()
? Locale::format(Locale::TimeFormat::FormatTime12HShort)
M => +6 -0
@@ 44,6 44,12 @@ void SimInfoWindow::onBeforeShow(ShowMode mode, SwitchData *data)
setTitle("");
infoIcon->text->setRichText(utils::translate("sim_card_pin_disabled"));
break;
case locks::SimInputTypeAction::Error:
setTitle(utils::translate("app_settings_net"));
infoIcon->text->setRichText(utils::translate("sim_card_cant_connect"),
{{"$SIM", infoData->getLock().getLockName()}});
infoIcon->image->set("sim_card_W_G");
break;
default:
break;
}
M => +7 -0
@@ 115,6 115,13 @@ namespace gui
}
return true;
}
else if (inputEvent.is(KeyCode::KEY_LEFT) && isIceVisible()) {
app::manager::Controller::sendAction(application,
app::manager::actions::EmergencyDial,
std::make_unique<gui::SwitchData>(),
app::manager::OnSwitchBehaviour::RunInBackground);
return true;
}
// check if any of the lower inheritance onInput methods catch the event
return AppWindow::onInput(inputEvent);
A => +46 -0
@@ 0,0 1,46 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SimNotReadyWindow.hpp"
#include <service-appmgr/Controller.hpp>
#include <application-desktop/data/DesktopStyle.hpp>
#include <i18n/i18n.hpp>
using namespace gui;
SimNotReadyWindow::SimNotReadyWindow(app::Application *app, const std::string &name) : AppWindow(app, name)
{
buildInterface();
}
top_bar::Configuration SimNotReadyWindow::configureTopBar(top_bar::Configuration appConfiguration)
{
appConfiguration.disable(top_bar::Indicator::NetworkAccessTechnology);
appConfiguration.disable(top_bar::Indicator::Lock);
appConfiguration.enable(top_bar::Indicator::PhoneMode);
appConfiguration.enable(top_bar::Indicator::Time);
appConfiguration.enable(top_bar::Indicator::Battery);
appConfiguration.enable(top_bar::Indicator::Signal);
appConfiguration.enable(top_bar::Indicator::SimCard);
return appConfiguration;
}
void SimNotReadyWindow::buildInterface()
{
AppWindow::buildInterface();
setTitle(utils::translate("app_settings_net"));
bottomBar->setText(BottomBar::Side::RIGHT, utils::translate("common_back"));
infoIcon = new gui::Icon(this,
style::window::default_left_margin,
style::header::height,
style::window::default_body_width,
style::window::default_body_height,
"sim_card_W_G",
utils::translate("sim_card_not_ready"));
infoIcon->setAlignment(Alignment::Horizontal::Center);
}
R module-apps/application-onboarding/windows/OnBoardingMainWindow.hpp => +9 -10
@@ 3,21 3,20 @@
#pragma once
-#include <memory>
-
#include <AppWindow.hpp>
-#include <module-gui/gui/widgets/Image.hpp>
+#include <Text.hpp>
+#include <gui/widgets/Icon.hpp>
-namespace app::onBoarding
+namespace gui
{
- class OnBoardingMainWindow : public gui::AppWindow
+ class SimNotReadyWindow : public AppWindow
{
- public:
- explicit OnBoardingMainWindow(app::Application *app);
+ Icon *infoIcon = nullptr;
- bool onInput(const gui::InputEvent &inputEvent) override;
+ public:
+ SimNotReadyWindow(app::Application *app, const std::string &name);
void buildInterface() override;
- gui::top_bar::Configuration configureTopBar(gui::top_bar::Configuration appConfiguration) override;
+ top_bar::Configuration configureTopBar(top_bar::Configuration appConfiguration) override;
};
-} // namespace gui
+} /* namespace gui */
A module-apps/widgets/IceBox.cpp => module-apps/widgets/IceBox.cpp +30 -0
@@ 0,0 1,30 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "IceBox.hpp"
+
+#include <Text.hpp>
+#include <i18n/i18n.hpp>
+
+namespace gui
+{
+ IceBox::IceBox(Item *parent)
+ : HBox(parent, style::window::ice::x, style::window::ice::y, style::window::ice::w, style::window::ice::h)
+ {
+ setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
+ setEdges(RectangleEdge::None);
+
+ auto arrow = new gui::Image("left_label_arrow");
+ arrow->activeItem = false;
+ arrow->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
+ arrow->setMargins(Margins(0, 0, style::window::ice::margin, 0));
+ addWidget(arrow);
+
+ auto iceText = new gui::Text(nullptr, 0, 0, style::window::ice::text::w, style::window::ice::h);
+ iceText->activeItem = false;
+ iceText->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Center));
+ iceText->setFont(style::window::font::verysmall);
+ iceText->setText(utils::translate("app_desktop_emergency"));
+ addWidget(iceText);
+ }
+} // namespace gui
A module-apps/widgets/IceBox.hpp => module-apps/widgets/IceBox.hpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <BoxLayout.hpp>
+#include <Label.hpp>
+#include <Image.hpp>
+
+namespace style::window::ice
+{
+ constexpr inline auto x = 25;
+ constexpr inline auto y = 53;
+ constexpr inline auto w = 60;
+ constexpr inline auto h = 38;
+
+ constexpr inline auto margin = 3;
+
+ namespace text
+ {
+ constexpr inline auto w = 40;
+ }
+} // namespace style::window::ice
+
+namespace gui
+{
+ class IceBox : public HBox
+ {
+ public:
+ explicit IceBox(Item *parent = nullptr);
+ };
+} // namespace gui
M module-apps/widgets/TimeWidget.cpp => module-apps/widgets/TimeWidget.cpp +8 -8
@@ 384,8 384,8 @@ namespace gui
if (!mode24H) {
if (type == Type::Start) {
const auto hours12H = date::make12(hoursFrom);
- hourInput->setText(std::to_string(hours12H.count()));
- minuteInput->setText(std::to_string(minutesFrom.count()));
+ hourInput->setText(utils::to_string(hours12H.count()));
+ minuteInput->setText(utils::to_string(minutesFrom.count()));
if (date::is_am(hoursFrom)) {
mode12hInput->setText(timeConstants::before_noon);
}
@@ 395,8 395,8 @@ namespace gui
}
else if (type == Type::End) {
const auto hours12H = date::make12(hoursTill);
- hourInput->setText(std::to_string(hours12H.count()));
- minuteInput->setText(std::to_string(minutesTill.count()));
+ hourInput->setText(utils::to_string(hours12H.count()));
+ minuteInput->setText(utils::to_string(minutesTill.count()));
if (date::is_am(hoursTill)) {
mode12hInput->setText(timeConstants::before_noon);
}
@@ 407,12 407,12 @@ namespace gui
}
else {
if (type == Type::Start) {
- hourInput->setText(std::to_string(hoursFrom.count()));
- minuteInput->setText(std::to_string(minutesFrom.count()));
+ hourInput->setText(utils::to_string(hoursFrom.count()));
+ minuteInput->setText(utils::to_string(minutesFrom.count()));
}
else if (type == Type::End) {
- hourInput->setText(std::to_string(hoursTill.count()));
- minuteInput->setText(std::to_string(minutesTill.count()));
+ hourInput->setText(utils::to_string(hoursTill.count()));
+ minuteInput->setText(utils::to_string(minutesTill.count()));
}
}
}
M module-audio/Audio/AudioDevice.hpp => module-audio/Audio/AudioDevice.hpp +2 -1
@@ 27,7 27,8 @@ namespace audio
None,
Audiocodec,
Cellular,
- Bluetooth
+ BluetoothA2DP,
+ BluetoothHSP
};
virtual ~AudioDevice() = default;
M module-audio/Audio/Operation/RecorderOperation.cpp => module-audio/Audio/Operation/RecorderOperation.cpp +0 -2
@@ 21,8 21,6 @@ namespace audio
#define PERF_STATS_ON 0
- using namespace bsp;
-
RecorderOperation::RecorderOperation(const char *file, AudioServiceMessage::Callback callback) : Operation(callback)
{
M module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp => module-audio/Audio/Profiles/ProfilePlaybackBluetoothA2DP.hpp +1 -1
@@ 21,7 21,7 @@ namespace audio
.inputGain = 0,
.inputPath = audio::codec::InputPath::None,
.outputPath = audio::codec::OutputPath::None},
- AudioDevice::Type::Bluetooth)
+ AudioDevice::Type::BluetoothA2DP)
{}
};
M module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp => module-audio/Audio/Profiles/ProfileRecordingBluetoothHSP.hpp +1 -1
@@ 23,7 23,7 @@ namespace audio
.inputGain = static_cast<float>(gain),
.inputPath = audio::codec::InputPath::None,
.outputPath = audio::codec::OutputPath::None},
- AudioDevice::Type::Bluetooth)
+ AudioDevice::Type::BluetoothHSP)
{}
};
M module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp => module-audio/Audio/Profiles/ProfileRoutingBluetoothHSP.hpp +1 -1
@@ 23,7 23,7 @@ namespace audio
.inputGain = static_cast<float>(gain),
.inputPath = audio::codec::InputPath::None,
.outputPath = audio::codec::OutputPath::None},
- AudioDevice::Type::Bluetooth)
+ AudioDevice::Type::BluetoothHSP)
{}
};
M module-audio/Audio/decoder/decoderMP3.hpp => module-audio/Audio/decoder/decoderMP3.hpp +3 -4
@@ 1,12 1,11 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "minimp3/minimp3.h"
-
-#include <cstring>
#include "Decoder.hpp"
+#include <minimp3.h>
+#include <cstring>
extern "C"
{
D module-audio/Audio/decoder/minimp3 => module-audio/Audio/decoder/minimp3 +0 -1
@@ 1,1 0,0 @@
-Subproject commit 446d3a32d281eb1dcae7726ba0ff594695182908
M module-audio/Audio/transcode/InputTranscodeProxy.cpp => module-audio/Audio/transcode/InputTranscodeProxy.cpp +5 -0
@@ 23,6 23,11 @@ bool InputTranscodeProxy::push(const Span &span)
return getWrappedStream().push(transform->transform(span, transcodingSpaceSpan));
}
+bool InputTranscodeProxy::push(void *data, std::size_t dataSize)
+{
+ return push(Span{.data = reinterpret_cast<std::uint8_t *>(data), .dataSize = dataSize});
+}
+
void InputTranscodeProxy::commit()
{
if (isReserved) {
M module-audio/Audio/transcode/InputTranscodeProxy.hpp => module-audio/Audio/transcode/InputTranscodeProxy.hpp +1 -0
@@ 27,6 27,7 @@ namespace audio::transcode
std::shared_ptr<Transform> transform) noexcept;
bool push(const Span &span) override;
+ bool push(void *data, std::size_t dataSize);
void commit() override;
bool reserve(Span &span) override;
[[nodiscard]] auto getInputTraits() const noexcept -> Traits override;
M module-audio/CMakeLists.txt => module-audio/CMakeLists.txt +9 -7
@@ 49,7 49,7 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/Audio/transcode/TransformFactory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Audio/VolumeScaler.cpp
)
-target_include_directories(${PROJECT_NAME} PRIVATE ${TAGLIB_INCLUDE_DIRS})
+
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_TARGET})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${TARGET_COMPILE_DEFINITIONS})
@@ 66,12 66,14 @@ set_source_files_properties(
)
target_link_libraries(${PROJECT_NAME}
- ${AUDIO_BOARD_LIBRARY}
- module-bsp
- module-os
- module-utils
- module-sys
- tag
+ PUBLIC
+ ${AUDIO_BOARD_LIBRARY}
+ module-bsp
+ module-os
+ module-utils
+ module-sys
+ tag
+ minimp3::minimp3
)
if (${ENABLE_TESTS})
M module-audio/board/rt1051/RT1051DeviceFactory.cpp => module-audio/board/rt1051/RT1051DeviceFactory.cpp +6 -2
@@ 21,8 21,12 @@ std::shared_ptr<AudioDevice> RT1051DeviceFactory::getDevice(const audio::Profile
device = std::make_shared<RT1051AudioCodec>(profile.GetAudioConfiguration());
} break;
- case AudioDevice::Type::Bluetooth: {
- device = std::make_shared<bluetooth::BluetoothAudioDevice>();
+ case AudioDevice::Type::BluetoothA2DP: {
+ device = std::make_shared<bluetooth::A2DPAudioDevice>();
+ } break;
+
+ case AudioDevice::Type::BluetoothHSP: {
+ device = std::make_shared<bluetooth::HSPAudioDevice>();
} break;
case AudioDevice::Type::Cellular: {
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.cpp +158 -21
@@ 3,42 3,46 @@
#include "BluetoothAudioDevice.hpp"
-#include <Audio/AudioCommon.hpp>
#include <interface/profiles/A2DP/AVDTP.hpp>
-#include <module-audio/Audio/VolumeScaler.hpp>
+#include <interface/profiles/A2DP/AVRCP.hpp>
+#include <interface/profiles/HSP/SCO.hpp>
+#include <Audio/AudioCommon.hpp>
+#include <Audio/VolumeScaler.hpp>
#include <Audio/Stream.hpp>
#include <chrono>
#include <cassert>
using audio::AudioFormat;
-using namespace bluetooth;
+using bluetooth::A2DPAudioDevice;
+using bluetooth::BluetoothAudioDevice;
+using bluetooth::HSPAudioDevice;
+
using namespace std::chrono_literals;
-BluetoothAudioDevice::BluetoothAudioDevice(MediaContext *mediaContext) : ctx(mediaContext)
-{
- LOG_DEBUG("Bluetooth audio device created");
-}
+BluetoothAudioDevice::BluetoothAudioDevice(AudioProfile audioProfile) : profile(audioProfile)
+{}
BluetoothAudioDevice::~BluetoothAudioDevice()
{
LOG_DEBUG("Destroying bluetooth audio device");
}
-void BluetoothAudioDevice::setMediaContext(MediaContext *mediaContext)
+auto BluetoothAudioDevice::getProfileType() const -> AudioProfile
{
- ctx = mediaContext;
+ return profile;
}
auto BluetoothAudioDevice::setOutputVolume(float vol) -> audio::AudioDevice::RetCode
{
const auto volumeToSet = audio::volume::scaler::toAvrcpVolume(vol);
- const auto status = avrcp_controller_set_absolute_volume(ctx->avrcp_cid, volumeToSet);
+ const auto status = avrcp_controller_set_absolute_volume(AVRCP::mediaTracker.avrcp_cid, volumeToSet);
if (status != ERROR_CODE_SUCCESS) {
LOG_ERROR("Can't set volume level. Status %x", status);
return audio::AudioDevice::RetCode::Failure;
}
+
outputVolume = vol;
return audio::AudioDevice::RetCode::Success;
}
@@ 48,19 52,125 @@ auto BluetoothAudioDevice::setInputGain(float gain) -> audio::AudioDevice::RetCo
return audio::AudioDevice::RetCode::Success;
}
-void BluetoothAudioDevice::onDataSend()
+auto BluetoothAudioDevice::isInputEnabled() const -> bool
+{
+ return inputEnabled;
+}
+
+auto BluetoothAudioDevice::isOutputEnabled() const -> bool
{
- if (outputEnabled) {
- fillSbcAudioBuffer(ctx);
+ return outputEnabled;
+}
+
+void A2DPAudioDevice::onDataSend()
+{
+ if (isOutputEnabled()) {
+ fillSbcAudioBuffer();
}
}
-void BluetoothAudioDevice::onDataReceive()
+void A2DPAudioDevice::onDataReceive()
{}
-void BluetoothAudioDevice::enableInput()
+void HSPAudioDevice::onDataSend()
{}
+void HSPAudioDevice::onDataSend(std::uint16_t scoHandle)
+{
+ if (!isOutputEnabled()) {
+ return;
+ }
+
+ hci_reserve_packet_buffer();
+ auto scoPacket = hci_get_outgoing_packet_buffer();
+
+ // get data to send
+ audio::AbstractStream::Span dataSpan;
+ Sink::_stream->peek(dataSpan);
+
+ // prepare packet to send
+ std::copy(dataSpan.data, dataSpan.dataEnd(), &scoPacket[packetDataOffset]);
+ Sink::_stream->consume();
+ little_endian_store_16(scoPacket, packetHandleOffset, scoHandle);
+ scoPacket[packetLengthOffset] = dataSpan.dataSize;
+
+ // send packet
+ hci_send_sco_packet_buffer(dataSpan.dataSize + packetDataOffset);
+ hci_request_sco_can_send_now_event();
+}
+
+void HSPAudioDevice::receiveCVSD(audio::AbstractStream::Span receivedData)
+{
+ if (!isInputEnabled()) {
+ return;
+ }
+
+ auto blockSize = Source::_stream->getInputTraits().blockSize;
+ auto decodedData = decodeCVSD(receivedData);
+ auto processedDataIndex = 0;
+
+ // try to complete leftovers to the full block size
+ if (leftoversSize != 0) {
+ auto maxFillSize = blockSize - leftoversSize;
+ auto fillSize = std::min(maxFillSize, decodedData.dataSize);
+
+ std::copy_n(decodedData.data, fillSize, &rxLeftovers[leftoversSize]);
+
+ if (fillSize + leftoversSize < blockSize) {
+ leftoversSize += fillSize;
+ return;
+ }
+
+ Source::_stream->push(&rxLeftovers[0], blockSize);
+ leftoversSize = 0;
+ processedDataIndex = fillSize;
+ }
+
+ // push as many blocks as possible
+ while (decodedData.dataSize - processedDataIndex >= blockSize) {
+ Source::_stream->push(&decodedData.data[processedDataIndex], blockSize);
+ processedDataIndex += blockSize;
+ }
+
+ // save leftovers
+ leftoversSize = decodedData.dataSize - processedDataIndex;
+ if (leftoversSize > 0) {
+ std::copy_n(&decodedData.data[processedDataIndex], leftoversSize, &rxLeftovers[0]);
+ }
+}
+
+auto HSPAudioDevice::decodeCVSD(audio::AbstractStream::Span dataToDecode) -> audio::AbstractStream::Span
+{
+ auto decodedData = dataToDecode;
+ std::array<std::int16_t, scratchBufferSize> scratchBuffer;
+
+ const auto audioBytesRead = dataToDecode.dataSize - packetDataOffset;
+ const auto samplesCount = audioBytesRead / sizeof(std::int16_t);
+ auto dataStart = &dataToDecode.data[packetDataOffset];
+
+ for (auto i = 0; i < samplesCount; ++i) {
+ scratchBuffer[i] = little_endian_read_16(dataStart, i * sizeof(std::uint16_t));
+ }
+
+ auto packetStatusByte = dataToDecode.data[packetStatusOffset];
+ auto isBadFrame = (packetStatusByte & allGoodMask) != 0;
+
+ btstack_cvsd_plc_process_data(&cvsdPlcState, isBadFrame, &scratchBuffer[0], samplesCount, &decoderBuffer[0]);
+
+ decodedData.data = reinterpret_cast<std::uint8_t *>(decoderBuffer.get());
+ decodedData.dataSize = audioBytesRead;
+
+ return decodedData;
+}
+
+void HSPAudioDevice::onDataReceive()
+{}
+
+void BluetoothAudioDevice::enableInput()
+{
+ inputEnabled = true;
+}
+
void BluetoothAudioDevice::enableOutput()
{
LOG_DEBUG("Enabling bluetooth audio output.");
@@ 68,7 178,9 @@ void BluetoothAudioDevice::enableOutput()
}
void BluetoothAudioDevice::disableInput()
-{}
+{
+ inputEnabled = false;
+}
void BluetoothAudioDevice::disableOutput()
{
@@ 76,11 188,21 @@ void BluetoothAudioDevice::disableOutput()
outputEnabled = false;
}
-auto BluetoothAudioDevice::fillSbcAudioBuffer(MediaContext *context) -> int
+void HSPAudioDevice::enableInput()
+{
+ auto blockSize = Source::_stream->getInputTraits().blockSize;
+ rxLeftovers = std::make_unique<std::uint8_t[]>(blockSize);
+ decoderBuffer = std::make_unique<std::int16_t[]>(scratchBufferSize);
+ btstack_cvsd_plc_init(&cvsdPlcState);
+ BluetoothAudioDevice::enableInput();
+}
+
+auto BluetoothAudioDevice::fillSbcAudioBuffer() -> int
{
// perform sbc encodin
int totalNumBytesRead = 0;
unsigned int numAudioSamplesPerSbcBuffer = btstack_sbc_encoder_num_audio_frames();
+ auto context = &AVRCP::mediaTracker;
assert(context != nullptr);
@@ 104,7 226,7 @@ auto BluetoothAudioDevice::fillSbcAudioBuffer(MediaContext *context) -> int
return totalNumBytesRead;
}
-auto BluetoothAudioDevice::getSupportedFormats() -> std::vector<audio::AudioFormat>
+auto A2DPAudioDevice::getSupportedFormats() -> std::vector<audio::AudioFormat>
{
constexpr static auto supportedBitWidth = 16U;
return std::vector<AudioFormat>{AudioFormat{static_cast<unsigned>(AVDTP::sbcConfig.samplingFrequency),
@@ 112,12 234,27 @@ auto BluetoothAudioDevice::getSupportedFormats() -> std::vector<audio::AudioForm
static_cast<unsigned>(AVDTP::sbcConfig.numChannels)}};
}
-auto BluetoothAudioDevice::getSourceFormat() -> audio::AudioFormat
+auto HSPAudioDevice::getSupportedFormats() -> std::vector<audio::AudioFormat>
{
- return audio::nullFormat;
+ return std::vector<AudioFormat>{getSourceFormat()};
}
-auto BluetoothAudioDevice::getTraits() const -> Traits
+auto A2DPAudioDevice::getTraits() const -> ::audio::Endpoint::Traits
{
return Traits{.usesDMA = false, .blockSizeConstraint = 512U, .timeConstraint = 10ms};
}
+
+auto HSPAudioDevice::getTraits() const -> ::audio::Endpoint::Traits
+{
+ return Traits{.usesDMA = false, .blockSizeConstraint = 32U, .timeConstraint = 16ms};
+}
+
+auto A2DPAudioDevice::getSourceFormat() -> ::audio::AudioFormat
+{
+ return audio::nullFormat;
+}
+
+auto HSPAudioDevice::getSourceFormat() -> ::audio::AudioFormat
+{
+ return AudioFormat{bluetooth::SCO::CVSD_SAMPLE_RATE, supportedBitWidth, supportedChannels};
+}
M module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp => module-bluetooth/Bluetooth/audio/BluetoothAudioDevice.hpp +70 -14
@@ 3,9 3,16 @@
#pragma once
+#include <Audio/Endpoint.hpp>
#include <Audio/AudioDevice.hpp>
#include <Audio/AudioFormat.hpp>
#include <interface/profiles/A2DP/MediaContext.hpp>
+#include <interface/profiles/AudioProfile.hpp>
+
+extern "C"
+{
+#include "classic/btstack_cvsd_plc.h"
+}
namespace bluetooth
{
@@ 13,31 20,80 @@ namespace bluetooth
class BluetoothAudioDevice : public audio::AudioDevice
{
public:
- BluetoothAudioDevice() = default;
- explicit BluetoothAudioDevice(MediaContext *mediaContext);
+ explicit BluetoothAudioDevice(AudioProfile audioProfile);
virtual ~BluetoothAudioDevice();
- RetCode setOutputVolume(float vol) override;
- RetCode setInputGain(float gain) override;
- void setMediaContext(MediaContext *MediaContext);
- auto getTraits() const -> Traits override;
- auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
- auto getSourceFormat() -> audio::AudioFormat override;
+ virtual auto getProfileType() const -> AudioProfile;
+
+ auto setOutputVolume(float vol) -> audio::AudioDevice::RetCode override;
+ auto setInputGain(float gain) -> audio::AudioDevice::RetCode override;
// Endpoint control methods
- void onDataSend() override;
- void onDataReceive() override;
void enableInput() override;
void enableOutput() override;
void disableInput() override;
void disableOutput() override;
+ protected:
+ auto isInputEnabled() const -> bool;
+ auto isOutputEnabled() const -> bool;
+ auto fillSbcAudioBuffer() -> int;
+
+ private:
+ bool outputEnabled = false;
+ bool inputEnabled = false;
+ AudioProfile profile = AudioProfile::None;
+ float outputVolume;
+ };
+
+ class A2DPAudioDevice : public BluetoothAudioDevice
+ {
+ public:
+ explicit A2DPAudioDevice() : BluetoothAudioDevice(AudioProfile::A2DP)
+ {}
+
+ void onDataSend() override;
+ void onDataReceive() override;
+ auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
+ auto getTraits() const -> Traits override;
+ auto getSourceFormat() -> ::audio::AudioFormat override;
+ };
+
+ class HSPAudioDevice : public BluetoothAudioDevice
+ {
+ public:
+ explicit HSPAudioDevice() : BluetoothAudioDevice(AudioProfile::HSP)
+ {}
+
+ void onDataSend() override;
+ void onDataSend(std::uint16_t scoHandle);
+ void onDataReceive() override;
+ auto getSupportedFormats() -> std::vector<audio::AudioFormat> override;
+ auto getTraits() const -> Traits override;
+ auto getSourceFormat() -> ::audio::AudioFormat override;
+ void enableInput() override;
+
+ void receiveCVSD(audio::AbstractStream::Span receivedData);
+
private:
- auto fillSbcAudioBuffer(MediaContext *context) -> int;
+ static constexpr std::size_t scratchBufferSize = 128;
+
+ static constexpr auto packetHandleOffset = 0;
+ static constexpr auto packetStatusOffset = 1;
+ static constexpr auto packetLengthOffset = 2;
+ static constexpr auto packetDataOffset = 3;
+
+ constexpr static auto supportedBitWidth = 16U;
+ constexpr static auto supportedChannels = 1;
+
+ constexpr static auto allGoodMask = 0x30;
+
+ auto decodeCVSD(audio::AbstractStream::Span dataToDecode) -> audio::AbstractStream::Span;
- MediaContext *ctx = nullptr;
- bool outputEnabled = false;
- float outputVolume = 0.0;
+ std::unique_ptr<std::uint8_t[]> rxLeftovers;
+ std::unique_ptr<std::int16_t[]> decoderBuffer;
+ std::size_t leftoversSize = 0;
+ btstack_cvsd_plc_state_t cvsdPlcState;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +1 -1
@@ 97,6 97,7 @@ namespace bluetooth
auto A2DP::startRinging() const noexcept -> Error::Code
{
+ LOG_ERROR("Can't ring in A2DP profile");
return Error::SystemError;
}
@@ 622,7 623,6 @@ namespace bluetooth
void A2DP::A2DPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> newAudioDevice)
{
- newAudioDevice->setMediaContext(&AVRCP::mediaTracker);
A2DP::A2DPImpl::audioDevice = std::move(newAudioDevice);
}
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +0 -1
@@ 50,7 50,6 @@ namespace bluetooth
static void sendMediaPacket();
static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
static bool isConnected;
-
static std::shared_ptr<BluetoothAudioDevice> audioDevice;
public:
A module-bluetooth/Bluetooth/interface/profiles/AudioProfile.hpp => module-bluetooth/Bluetooth/interface/profiles/AudioProfile.hpp +15 -0
@@ 0,0 1,15 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+namespace bluetooth
+{
+ enum class AudioProfile
+ {
+ A2DP,
+ HSP,
+ HFP,
+ None
+ };
+};
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +18 -2
@@ 111,6 111,7 @@ namespace bluetooth
const sys::Service *HSP::HSPImpl::ownerService;
std::string HSP::HSPImpl::agServiceName = "PurePhone HSP";
bool HSP::HSPImpl::isConnected = false;
+ std::shared_ptr<HSPAudioDevice> HSP::HSPImpl::audioDevice;
void HSP::HSPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
{
@@ 127,7 128,9 @@ namespace bluetooth
if (READ_SCO_CONNECTION_HANDLE(event) != scoHandle) {
break;
}
- sco->receive(event, eventSize);
+ if (audioDevice != nullptr) {
+ audioDevice->receiveCVSD(audio::AbstractStream::Span{.data = event, .dataSize = eventSize});
+ }
break;
case HCI_EVENT_PACKET:
@@ 142,7 145,9 @@ namespace bluetooth
{
switch (hci_event_packet_get_type(event)) {
case HCI_EVENT_SCO_CAN_SEND_NOW:
- sco->send(scoHandle);
+ if (audioDevice != nullptr) {
+ audioDevice->onDataSend(scoHandle);
+ }
break;
case HCI_EVENT_HSP_META:
processHSPEvent(event);
@@ 163,6 168,7 @@ namespace bluetooth
break;
}
LOG_DEBUG("RFCOMM connection established.\n");
+ sendAudioEvent(audio::EventType::BlutoothHSPDeviceState, audio::Event::DeviceState::Connected);
isConnected = true;
break;
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE:
@@ 314,4 320,14 @@ namespace bluetooth
stopRinging();
establishAudioConnection();
}
+
+ void HSP::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+ {
+ pimpl->setAudioDevice(audioDevice);
+ }
+
+ void HSP::HSPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+ {
+ HSP::HSPImpl::audioDevice = std::static_pointer_cast<HSPAudioDevice>(audioDevice);
+ }
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +1 -2
@@ 55,8 55,7 @@ namespace bluetooth
/// @return Success
[[nodiscard]] auto initializeCall() const noexcept -> Error::Code override;
- void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override
- {}
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;
private:
class HSPImpl;
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp +3 -1
@@ 27,6 27,7 @@ namespace bluetooth
void setDeviceAddress(bd_addr_t addr);
void setOwnerService(const sys::Service *service);
auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
private:
static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
@@ 43,5 44,6 @@ namespace bluetooth
static bd_addr_t deviceAddr;
static const sys::Service *ownerService;
static bool isConnected;
+ static std::shared_ptr<HSPAudioDevice> audioDevice;
};
-} // namespace Bt
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.cpp +0 -1
@@ 32,7 32,6 @@ namespace bluetooth
auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
private:
- static constexpr auto CVSD_SAMPLE_RATE = 8000;
static constexpr auto BYTES_PER_FRAME = 2;
static constexpr auto ALL_GOOD_MASK = 0x30;
static constexpr auto AUDIO_BUFFER_LENGTH = 128;
M module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/SCO.hpp +3 -1
@@ 30,8 30,10 @@ namespace bluetooth
[[nodiscard]] auto getStreamData() const -> std::shared_ptr<BluetoothStreamData>;
void setOwnerService(const sys::Service *service);
+ static constexpr auto CVSD_SAMPLE_RATE = 8000;
+
private:
class SCOImpl;
std::unique_ptr<SCOImpl> pimpl;
};
-} // namespace Bt
+} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +7 -3
@@ 97,6 97,7 @@ namespace bluetooth
auto ProfileManager::startRinging() -> Error::Code
{
+ switchProfile(AudioProfile::HSP);
return currentProfilePtr->startRinging();
}
@@ 107,16 108,19 @@ namespace bluetooth
auto ProfileManager::initializeCall() -> Error::Code
{
+ switchProfile(AudioProfile::HSP);
return currentProfilePtr->initializeCall();
}
auto ProfileManager::setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code
{
- if (currentProfilePtr == nullptr) {
+ auto profileType = device->getProfileType();
+
+ if (currentProfilePtr == nullptr || profilesList[profileType] == nullptr) {
return Error::NotReady;
}
- currentProfilePtr->setAudioDevice(std::move(device));
- return Error::Success;
+ profilesList[profileType]->setAudioDevice(device);
+ return switchProfile(profileType);
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +1 -8
@@ 6,6 6,7 @@
#include <Service/Service.hpp>
#include <Error.hpp>
#include "Profile.hpp"
+#include "AudioProfile.hpp"
#include "interface/profiles/A2DP/A2DP.hpp"
#include "interface/profiles/HSP/HSP.hpp"
#include "audio/BluetoothAudioDevice.hpp"
@@ 21,14 22,6 @@ extern "C"
namespace bluetooth
{
- enum class AudioProfile
- {
- A2DP,
- HSP,
- HFP,
- None
- };
-
using ProfileList = std::map<AudioProfile, std::shared_ptr<bluetooth::Profile>>;
class ProfileManager
M module-bsp/board/linux/battery-charger/battery_charger.cpp => module-bsp/board/linux/battery-charger/battery_charger.cpp +11 -0
@@ 185,4 185,15 @@ namespace bsp::battery_charger
}
}
+ int getVoltageFilteredMeasurement()
+ {
+ constexpr auto nominalVoltage = 4350;
+ return nominalVoltage;
+ }
+
+ BaseType_t INTB_IRQHandler()
+ {
+ return 1;
+ }
+
} // namespace bsp::battery_charger
M module-bsp/board/linux/magnetometer/magnetometer.cpp => module-bsp/board/linux/magnetometer/magnetometer.cpp +1 -5
@@ 35,11 35,7 @@ namespace bsp
void enableIRQ()
{}
- void initFirstReadout()
+ void resetCurrentParsedValue()
{}
- bsp::KeyCodes getCurrentSliderPosition()
- {
- return bsp::KeyCodes::Undefined;
- }
} // namespace magnetometer
} // namespace bsp
M module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp => module-bsp/board/rt1051/bsp/battery-charger/battery_charger.cpp +10 -0
@@ 592,6 592,9 @@ namespace bsp::battery_charger
enableChargerIRQs();
IRQPinsInit();
+ // Check IRQ status register
+ INTB_IRQHandler();
+
return 0;
}
@@ 740,6 743,13 @@ namespace bsp::battery_charger
}
}
+ int getVoltageFilteredMeasurement()
+ {
+ auto [retCode, value] = fuelGaugeRead(Registers::AvgVCELL_REG);
+ int voltage = value * voltageSenseGain;
+ return voltage;
+ }
+
BaseType_t INTB_IRQHandler()
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
M module-bsp/board/rt1051/bsp/magnetometer/ALS31300.hpp => module-bsp/board/rt1051/bsp/magnetometer/ALS31300.hpp +2 -22
@@ 17,7 17,7 @@ namespace drivers::als31300
using whole_reg_t = uint32_t; // ALS31300 always talks 4 bytes
constexpr auto I2C_ADDRESS = 0x64;
- constexpr auto DUMMY_BYTE = 1;
+
// base ALS31300 register struct.
struct base_reg
{
@@ 109,33 109,13 @@ namespace drivers::als31300
constexpr auto PWR_REG_LOOP_MODE_fast_loop = 0b01;
constexpr auto PWR_REG_LOOP_MODE_full_loop = 0b10;
- enum class PWR_REG_SLEEP_MODE
+ enum PWR_REG_SLEEP_MODE
{
active = PWR_REG_SLEEP_MODE_active,
sleep = PWR_REG_SLEEP_MODE_sleep,
periodic_active = PWR_REG_SLEEP_MODE_LPDCM,
};
- enum class LPDCM_INACTIVE_TIME
- {
- inactive_500us,
- inactive_1ms,
- inactive_5ms,
- inactive_10ms,
- inactive_50ms,
- inactive_100ms,
- inactive_500ms,
- inactive_1s
- };
- enum class BANDWIDTH_SELECT
- {
- bandwidth_3500Hz = 0,
- bandwidth_7kHz = 1,
- bandwidth_14kHz = 2,
- bandwidth_10kHz = 4,
- bandwidth_20kHz = 5,
- bandwidth_40kHz = 6
- };
constexpr auto PWR_ON_DELAY_MS = 1; // spec'd as 600µs at most
// --------
D module-bsp/board/rt1051/bsp/magnetometer/doc/magnetometer_values.png => module-bsp/board/rt1051/bsp/magnetometer/doc/magnetometer_values.png +0 -0
D module-bsp/board/rt1051/bsp/magnetometer/doc/readme.md => module-bsp/board/rt1051/bsp/magnetometer/doc/readme.md +0 -27
@@ 1,27 0,0 @@
-# ALS31300 Hall effect sensor
-This magnetometer is used as a detector of the slider position, which has a magnet attached to itself. When slider position changes,
-the magnetic field intensity measured by the sensor is changing and is properly interpreted to determine the position of the slider.
-
-## Values per position
-
-<center><b>Positions: down, middle, up, middle</b></center>
-
-As shown on the graph, using only X and Y axes can clearly determine the slider position so this has been implemented.
-
-## Magnetometer configuration
-Looking at the graph it's easy to find out, that each slider position has some mean value of the magnetic field intensity. This particular
-sensor has the possibility to generate an interrupt on its pin when the absolute threshold has been exceeded or the increment of
-the intensity related to the last taken measurement was higher than a certain, set value.
-
-In this case, increment (delta) mode has been used, combined with Low Power Delta Compare Mode (LPDCM) -
-magnetometer cycles between active and inactive state and takes measurements. When the change in the magnetic field has been higher than
-set value, it generates an interrupt for the main processor, which then retrieves the measurements and does proper action.
-
-## Caveats
-
-- once the magnetometer has been put to the LPDCM mode it cannot be read nor written until the interrupt happens - despite the datasheet which claims,
-that the device should respond to the I2C commands, the only answer to every one command was NAK,
-- setting a too small period for LPDCM mode (too small inactivity time) caused some instability during tests,
-- to get proper measurements after receiving the interrupt, there's a need to put the magnetometer to the active state,
- then take measurements and put it again to the LPDCM mode - doing anything else means the measurements data was inaccurate and way off.
-
M module-bsp/board/rt1051/bsp/magnetometer/magnetometer.cpp => module-bsp/board/rt1051/bsp/magnetometer/magnetometer.cpp +84 -50
@@ 34,6 34,27 @@ namespace bsp
{
namespace magnetometer
{
+ enum class LPDCM_INACTIVE_TIME
+ {
+ inactive_500us,
+ inactive_1ms,
+ inactive_5ms,
+ inactive_10ms,
+ inactive_50ms,
+ inactive_100ms,
+ inactive_500ms,
+ inactive_1s
+ };
+
+ enum class BANDWIDTH_SELECT
+ {
+ bandwidth_3500Hz = 0,
+ bandwidth_7kHz = 1,
+ bandwidth_14kHz = 2,
+ bandwidth_10kHz = 4,
+ bandwidth_20kHz = 5,
+ bandwidth_40kHz = 6
+ };
namespace
{
bool isTimeToCompleteWriteDefinedForRegistry(std::uint8_t address)
@@ 41,28 62,29 @@ namespace bsp
const auto it = std::find(als31300::EEPROM_REGS.begin(), als31300::EEPROM_REGS.end(), address);
return it != als31300::EEPROM_REGS.end();
}
- auto getThresholdLevel(std::uint16_t gaussThreshold) -> std::uint8_t
- {
- return floor(((gaussThreshold + 1) / 32.0) - 1); // calculation formula taken from ALS datasheet
- }
} // namespace
std::shared_ptr<DriverGPIO> gpio;
bsp::KeyCodes current_parsed = bsp::KeyCodes::Undefined;
- bool setActive(als31300::PWR_REG_SLEEP_MODE sleep_mode);
+ static TimerHandle_t timerHandle;
+ static constexpr uint16_t MAGNETOMETER_POLL_INTERVAL_MS = 500;
- bsp::KeyCodes getCurrentSliderPosition()
+ static void TimerHandler(TimerHandle_t xTimer)
{
- return current_parsed;
+ if (qHandleIrq != nullptr) {
+ uint8_t val = 0x01;
+ xQueueSend(qHandleIrq, &val, 0);
+ }
}
+ bool setActive(als31300::PWR_REG_SLEEP_MODE sleep_mode);
+
bool i2cRead(const uint8_t reg_addr, als31300::whole_reg_t &whole_reg)
{
addr.subAddress = reg_addr;
- auto readBytes = i2c->Read(addr, i2c_buf.buf, sizeof(als31300::whole_reg_t));
- if (readBytes != sizeof(als31300::whole_reg_t)) {
+ if (i2c->Read(addr, i2c_buf.buf, sizeof(als31300::whole_reg_t)) != sizeof(als31300::whole_reg_t)) {
return false;
}
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
@@ 99,9 121,11 @@ namespace bsp
// any configuration must be proceeded in active state
setActive(als31300::PWR_REG_SLEEP_MODE::active);
+
// GET WRITE ACCESS
if (!i2cWrite(als31300::CUSTOMER_ACCESS_REG, als31300::CUSTOMER_ACCESS_REG_code)) {
- LOG_WARN("magneto: Customer access already unlocked or write error");
+ LOG_ERROR("magneto: CANNOT INIT SLIDER SENSOR");
+ return kStatus_Fail;
}
// CONFIGURATION register read
@@ 115,12 139,10 @@ namespace bsp
reg_conf.channel_X_en = als31300::CONF_REG_CHANNEL_enabled;
reg_conf.channel_Y_en = als31300::CONF_REG_CHANNEL_enabled;
reg_conf.channel_Z_en = als31300::CONF_REG_CHANNEL_disabled;
- reg_conf.bandwidth = static_cast<std::uint8_t>(als31300::BANDWIDTH_SELECT::bandwidth_7kHz);
+ reg_conf.bandwidth = static_cast<uint8_t>(BANDWIDTH_SELECT::bandwidth_7kHz);
if (current_reg_conf != reg_conf) {
- if (!i2cWrite(als31300::CONF_REG, reg_conf)) {
- LOG_ERROR("magneto: CANNOT INIT SLIDER SENSOR");
- return kStatus_Fail;
- }
+ [[maybe_unused]] auto ret = i2cWrite(als31300::CONF_REG, reg_conf);
+ assert(ret);
LOG_DEBUG("CONF wrote:\t%" PRIu32, static_cast<uint32_t>(reg_conf));
i2cRead(als31300::CONF_REG, read_reg);
@@ 136,16 158,17 @@ namespace bsp
LOG_DEBUG("INT read:\t%" PRIu32, static_cast<uint32_t>(current_reg_int));
als31300::int_reg reg_int = current_reg_int;
reg_int.int_eeprom_en = als31300::INT_REG_INT_EEPROM_disable;
- reg_int.int_mode = als31300::INT_REG_INT_MODE_delta;
+ reg_int.int_mode = als31300::INT_REG_INT_MODE_threshold;
reg_int.int_threshold_signed = als31300::INT_REG_THRESHOLD_absolute;
- reg_int.int_X_en = als31300::INT_REG_INT_CHANNEL_enabled;
- reg_int.int_Y_en = als31300::INT_REG_INT_CHANNEL_enabled;
+ reg_int.int_X_en = als31300::INT_REG_INT_CHANNEL_disabled;
+ reg_int.int_Y_en = als31300::INT_REG_INT_CHANNEL_disabled;
reg_int.int_Z_en = als31300::INT_REG_INT_CHANNEL_disabled;
- reg_int.int_X_threshold = getThresholdLevel(32);
- reg_int.int_Y_threshold = getThresholdLevel(128);
+ reg_int.int_X_threshold = 1;
+ reg_int.int_Y_threshold = 4;
reg_int.int_Z_threshold = 0;
if (current_reg_int != reg_int) {
- i2cWrite(als31300::INT_REG, reg_int);
+ [[maybe_unused]] auto ret = i2cWrite(als31300::INT_REG, reg_int);
+ assert(ret);
LOG_DEBUG("INT wrote:\t%" PRIu32, static_cast<uint32_t>(reg_int));
i2cRead(als31300::INT_REG, read_reg);
@@ 165,8 188,17 @@ namespace bsp
.irqMode = DriverGPIOPinParams::InterruptMode::IntFallingEdge,
.defLogic = 0,
.pin = static_cast<uint32_t>(BoardDefinitions::MAGNETOMETER_IRQ)});
-
- enableIRQ();
+ // NOTE: irq not yet enabled
+ // this version uses timer to poll the sensor
+ // the timer requests to read the magnetometer periodically
+ if (timerHandle == nullptr) {
+ timerHandle = xTimerCreate(
+ "SliderTimer", pdMS_TO_TICKS(MAGNETOMETER_POLL_INTERVAL_MS), true, nullptr, TimerHandler);
+ if (timerHandle == nullptr) {
+ LOG_FATAL("Could not create the timer for Headset insertion/removal detection");
+ return kStatus_Fail;
+ }
+ }
// POWER register
i2cRead(als31300::PWR_REG, read_reg);
@@ 175,12 207,13 @@ namespace bsp
als31300::pwr_reg reg_pwr = current_reg_pwr;
reg_pwr.I2C_loop_mode = als31300::PWR_REG_LOOP_MODE_single; // we don't want constant data flow
reg_pwr.sleep = als31300::PWR_REG_SLEEP_MODE_active;
- reg_pwr.count_max_LP_mode = static_cast<std::uint8_t>(als31300::LPDCM_INACTIVE_TIME::inactive_100ms);
+ reg_pwr.count_max_LP_mode = static_cast<uint8_t>(LPDCM_INACTIVE_TIME::inactive_10ms);
i2cWrite(als31300::PWR_REG, reg_pwr);
LOG_DEBUG("POWER wrote:\t%" PRIu32, static_cast<uint32_t>(reg_pwr));
- initFirstReadout();
+ xTimerStart(timerHandle, 1000);
+
return kStatus_Success;
}
@@ 197,21 230,30 @@ namespace bsp
if (reg_msb.int_flag == true) {
LOG_DEBUG("magneto: INT flag in register");
- if (!i2cWrite(als31300::MEASUREMENTS_MSB_REG, reg_msb)) {
- return std::make_pair(false, Measurements()); // todo: null opt
- }
}
- Measurements meas;
- i2cRead(als31300::MEASUREMENTS_LSB_REG, read_reg);
+ if (reg_msb.new_data_flag != als31300::MEAS_REG_NEW_DATA_available) {
+ return std::make_pair(false, Measurements());
+ }
+ else {
+ if (reg_msb.int_flag == true) {
+ // clear INT flag
+ if (!i2cWrite(als31300::MEASUREMENTS_MSB_REG, reg_msb)) {
+ return std::make_pair(false, Measurements()); // todo: null opt
+ }
+ }
+ Measurements meas;
+
+ i2cRead(als31300::MEASUREMENTS_LSB_REG, read_reg);
- als31300::measurements_LSB_reg reg_lsb = read_reg;
+ als31300::measurements_LSB_reg reg_lsb = read_reg;
- meas.X = als31300::measurement_sign_convert(reg_msb.X_MSB << 4 | reg_lsb.X_LSB);
- meas.Y = als31300::measurement_sign_convert(reg_msb.Y_MSB << 4 | reg_lsb.Z_LSB);
- meas.Z = als31300::measurement_sign_convert(reg_msb.Z_MSB << 4 | reg_lsb.Z_LSB);
+ meas.X = als31300::measurement_sign_convert(reg_msb.X_MSB << 4 | reg_lsb.X_LSB);
+ meas.Y = als31300::measurement_sign_convert(reg_msb.Y_MSB << 4 | reg_lsb.Z_LSB);
+ meas.Z = als31300::measurement_sign_convert(reg_msb.Z_MSB << 4 | reg_lsb.Z_LSB);
- return std::pair(true, meas);
+ return std::pair(true, meas);
+ }
}
bool setActive(als31300::PWR_REG_SLEEP_MODE sleep_mode)
@@ 220,14 262,12 @@ namespace bsp
als31300::whole_reg_t read_reg;
if (!i2cRead(als31300::PWR_REG, read_reg)) {
- LOG_ERROR("setActive: cannot read PWR REG!");
return false;
}
als31300::pwr_reg reg_pwr = read_reg;
- reg_pwr.sleep = static_cast<std::uint8_t>(sleep_mode);
+ reg_pwr.sleep = sleep_mode;
if (!i2cWrite(als31300::PWR_REG, reg_pwr)) {
- LOG_ERROR("setActive: cannot write PWR REG!");
return false;
}
if (sleep_mode == als31300::PWR_REG_SLEEP_MODE::active ||
@@ 243,10 283,7 @@ namespace bsp
addr.subAddress = 0x00;
auto read = i2c->Read(addr, &buf, 1);
- if (read != 1) {
- return false;
- }
- return true;
+ return read == 1;
}
bsp::KeyCodes parse(const Measurements &measurements)
@@ 280,21 317,17 @@ namespace bsp
}
return bsp::KeyCodes::Undefined;
}
- void initFirstReadout()
+ void resetCurrentParsedValue()
{
current_parsed = bsp::KeyCodes::Undefined;
- if (qHandleIrq != NULL) {
- std::uint8_t val = als31300::DUMMY_BYTE;
- constexpr auto ticksToWait = 1000;
- xQueueSend(qHandleIrq, &val, pdMS_TO_TICKS(ticksToWait));
- }
}
std::optional<bsp::KeyCodes> WorkerEventHandler()
{
+ // try to get new data from active magneto
setActive(als31300::PWR_REG_SLEEP_MODE::active);
auto [new_data, measurement] = getMeasurement();
- setActive(als31300::PWR_REG_SLEEP_MODE::periodic_active);
+ setActive(als31300::PWR_REG_SLEEP_MODE::sleep);
if (new_data) {
auto incoming_parsed = parse(measurement);
if (incoming_parsed != bsp::KeyCodes::Undefined and incoming_parsed != current_parsed) {
@@ 307,9 340,10 @@ namespace bsp
BaseType_t IRQHandler()
{
+ gpio->DisableInterrupt(1 << static_cast<uint32_t>(BoardDefinitions::MAGNETOMETER_IRQ));
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (qHandleIrq != NULL) {
- std::uint8_t val = als31300::DUMMY_BYTE;
+ uint8_t val = 0x01;
xQueueSendFromISR(qHandleIrq, &val, &xHigherPriorityTaskWoken);
}
return xHigherPriorityTaskWoken;
M module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c => module-bsp/board/rt1051/common/fsl_drivers/fsl_snvs_hp.c +0 -2
@@ 417,8 417,6 @@ void SNVS_HP_RTC_GetDatetime(SNVS_Type *base, snvs_hp_rtc_datetime_t *datetime)
*/
status_t SNVS_HP_RTC_SetAlarmSeconds(SNVS_Type *base, uint32_t alarmSeconds)
{
- assert(alarmTime != NULL);
-
uint32_t currSeconds = 0U;
uint32_t tmp = base->HPCR;
M module-bsp/board/rt1051/drivers/RT1051DriverI2C.cpp => module-bsp/board/rt1051/drivers/RT1051DriverI2C.cpp +0 -2
@@ 50,7 50,6 @@ namespace drivers
auto ret = BOARD_LPI2C_Send(
base, addr.deviceAddress, addr.subAddress, addr.subAddressSize, const_cast<uint8_t *>(txBuff), size);
if (ret != kStatus_Success) {
- LOG_ERROR("I2C Write: Error %ld", ret);
return -1; // TODO:M.P: fix me
}
else {
@@ 63,7 62,6 @@ namespace drivers
cpp_freertos::LockGuard lock(mutex);
auto ret = BOARD_LPI2C_Receive(base, addr.deviceAddress, addr.subAddress, addr.subAddressSize, rxBuff, size);
if (ret != kStatus_Success) {
- LOG_ERROR("I2C Read: Error %ld", ret);
return -1; // TODO:M.P: fix me
}
else {
M module-bsp/bsp/BoardDefinitions.hpp => module-bsp/bsp/BoardDefinitions.hpp +2 -3
@@ 18,9 18,8 @@ enum class BoardDefinitions
USB_FUNCTION_MUX_SELECT = 25, // GPIO_AD_B1_09, USB_MUX_SEL0
USB_POWER_ACK = 3, // GPIO_B0_03 Note: pull-up in order to read
+ I2C_STD_BAUDRATE = 100000,
- I2C_STD_BAUDRATE = 100000,
- I2C_FAST_BAUDRATE = 400000,
AUDIOCODEC_I2C_BAUDRATE = I2C_STD_BAUDRATE,
AUDIOCODEC_I2C = static_cast<int>(drivers::I2CInstances ::I2C2),
AUDIOCODEC_DMAMUX = static_cast<int>(drivers::DMAMuxInstances ::DMAMUX0),
@@ 107,7 106,7 @@ enum class BoardDefinitions
VIBRATOR_EN = 0, // GPIO_AD_B0_00
MAGNETOMETER_I2C = AUDIOCODEC_I2C,
- MAGNETOMETER_I2C_BAUDRATE = I2C_FAST_BAUDRATE,
+ MAGNETOMETER_I2C_BAUDRATE = AUDIOCODEC_I2C_BAUDRATE,
MAGNETOMETER_GPIO = static_cast<int>(drivers::GPIOInstances::GPIO_1),
MAGNETOMETER_IRQ = 20, // GPIO_AD_B1_04
M module-bsp/bsp/battery-charger/battery_charger.hpp => module-bsp/bsp/battery-charger/battery_charger.hpp +2 -0
@@ 75,6 75,8 @@ namespace bsp::battery_charger
void actionIfChargerUnplugged();
+ int getVoltageFilteredMeasurement();
+
BaseType_t INTB_IRQHandler();
extern "C"
M module-bsp/bsp/magnetometer/magnetometer.hpp => module-bsp/bsp/magnetometer/magnetometer.hpp +1 -2
@@ 39,8 39,7 @@ namespace bsp
bsp::KeyCodes parse(const Measurements &measurements);
std::optional<bsp::KeyCodes> WorkerEventHandler();
- void initFirstReadout();
- bsp::KeyCodes getCurrentSliderPosition();
+ void resetCurrentParsedValue();
BaseType_t IRQHandler();
void enableIRQ();
M module-cellular/at/Commands.hpp => module-cellular/at/Commands.hpp +16 -8
@@ 31,7 31,7 @@ namespace at
URC_DELAY_ON, /// Enable delay the output of URC indication until ring indicator pulse ends
URC_UART1, /// Route URCs to UART1
AT_PIN_READY_LOGIC, /// Configure AP_Ready pin logic ( enable, logic level 1, 200ms )
- URC_NOTIF_SIGNAL, /// Turn on signal strength change URC
+ CSQ_URC_ON, /// Turn on signal strength change URC
CRC_ON, /// Change incoming call notification from "RING" to "+CRING:type"
CALLER_NUMBER_PRESENTATION, /// Turn on caller's number presentation
SMS_TEXT_FORMAT, /// Set Message format to Text
@@ 54,13 54,14 @@ namespace at
CNUM, /// doc: the command can get the subscribers own number(s) from the (U)SI
CIMI, /// Its getting IMSI from selected SIM card
QCMGR,
- ATH, /// hangup
- ATA, /// (doc): timeout should be possibly set up to 90s
- ATD, /// setup call
- IPR, /// set baudrate
- CMUX, /// setup cmux params
- CFUN, /// set phone functionality
- CMGS, /// sms
+ ATH, /// hangup
+ QHUP_BUSY, /// hangup all calls with busy reason
+ ATA, /// (doc): timeout should be possibly set up to 90s
+ ATD, /// setup call
+ IPR, /// set baudrate
+ CMUX, /// setup cmux params
+ CFUN, /// set phone functionality
+ CMGS, /// sms
QCMGS,
CREG, /// network registration status
QNWINFO, /// network informations (band etc)
@@ 126,6 127,13 @@ namespace at
QMBNCFG, /// Quectel command for MBN files management
QCFG_IMS, /// Set/Get IP Multimedia Services, get state of VoLTE
QEEC, /// Echo cancellation parameters
+ RING_URC_OFF,
+ RING_URC_ON,
+ CSQ_URC_OFF,
+ SMS_URC_OFF,
+ SMS_URC_ON,
+ ACT_URC_OFF,
+ ACT_URC_ON,
};
enum class commadsSet
M module-cellular/at/src/ATFactory.cpp => module-cellular/at/src/ATFactory.cpp +12 -2
@@ 24,7 24,8 @@ namespace at
{AT::URC_DELAY_ON, {"AT+QCFG=\"urc/delay\",1"}},
{AT::URC_UART1, {"AT+QURCCFG=\"urcport\",\"uart1\""}},
{AT::AT_PIN_READY_LOGIC, {"AT+QCFG=\"apready\",1,1,200"}},
- {AT::URC_NOTIF_SIGNAL, {"AT+QINDCFG=\"csq\",1"}},
+ {AT::CSQ_URC_ON, {"AT+QINDCFG=\"csq\",1"}},
+ {AT::CSQ_URC_OFF, {"AT+QINDCFG=\"csq\",0"}},
{AT::CRC_ON, {"AT+CRC=1"}},
{AT::CALLER_NUMBER_PRESENTATION, {"AT+CLIP=1", default_long_timeout}},
{AT::SMS_TEXT_FORMAT, {"AT+CMGF=1"}},
@@ 41,6 42,7 @@ namespace at
{AT::CIMI, {"AT+CIMI"}},
{AT::QCMGR, {"AT+QCMGR=", 180s}},
{AT::ATH, {"ATH", 100s}},
+ {AT::QHUP_BUSY, {"AT+QHUP=17", 100s}},
{AT::ATA, {"ATA", 100s}},
{AT::ATD, {"ATD", 6s}},
{AT::IPR, {"AT+IPR="}},
@@ 110,7 112,15 @@ namespace at
{AT::QNVFR, {"AT+QNVFR=", default_long_timeout}},
{AT::QNVFW, {"AT+QNVFW=", default_long_timeout}},
{AT::QMBNCFG, {"AT+QMBNCFG=", default_long_timeout}},
- {AT::QCFG_IMS, {"AT+QCFG=\"ims\""}}};
+ {AT::QCFG_IMS, {"AT+QCFG=\"ims\""}},
+ {AT::RING_URC_ON, {"AT+QINDCFG=\"ring\",1"}},
+ {AT::RING_URC_OFF, {"AT+QINDCFG=\"ring\",0"}},
+ {AT::ACT_URC_OFF, {"AT+QINDCFG=\"act\",0"}},
+ {AT::ACT_URC_ON, {"AT+QINDCFG=\"act\",1"}},
+ {AT::SMS_URC_ON, {"AT+QINDCFG=\"smsincoming\",1"}},
+ {AT::SMS_URC_OFF, {"AT+QINDCFG=\"smsincoming\",0"}},
+
+ };
auto factory(AT at) -> const Cmd &
{
M module-cellular/at/src/Commands.cpp => module-cellular/at/src/Commands.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <Commands.hpp>
@@ 19,7 19,7 @@ namespace at
ret.push_back(AT::URC_DELAY_ON);
ret.push_back(AT::URC_UART1);
ret.push_back(AT::AT_PIN_READY_LOGIC);
- ret.push_back(AT::URC_NOTIF_SIGNAL);
+ ret.push_back(AT::CSQ_URC_ON);
break;
case commadsSet::simInit:
ret.push_back(AT::CALLER_NUMBER_PRESENTATION);
M module-cellular/modem/mux/CellularMux.cpp => module-cellular/modem/mux/CellularMux.cpp +3 -1
@@ 14,11 14,13 @@
#include <service-cellular/CellularMessage.hpp>
#include <RTOSWrapper/include/ticks.hpp>
+#include <SystemManager/messages/DeviceRegistrationMessage.hpp>
+#include <time/time_conversion.hpp>
#include <gsl/gsl_util>
+
#include <memory>
#include <sstream>
-#include <SystemManager/messages/DeviceRegistrationMessage.hpp>
std::map<TypeOfFrame_e, std::string> TypeOfFrame_text = {{TypeOfFrame_e::SABM, "SABM"},
{TypeOfFrame_e::UA, "UA"},
M module-db/CMakeLists.txt => module-db/CMakeLists.txt +1 -0
@@ 98,6 98,7 @@ set(SOURCES
queries/calllog/QueryCalllogGetByContactID.cpp
queries/notifications/QueryNotificationsGet.cpp
queries/notifications/QueryNotificationsIncrement.cpp
+ queries/notifications/QueryNotificationsMultipleIncrement.cpp
queries/notifications/QueryNotificationsClear.cpp
queries/notifications/QueryNotificationsGetAll.cpp
queries/phonebook/QueryContactGet.cpp
M module-db/Interface/CalllogRecord.cpp => module-db/Interface/CalllogRecord.cpp +5 -1
@@ 25,6 25,10 @@ CalllogRecord::CalllogRecord(const CalllogTableRow &tableRow)
phoneNumber(utils::PhoneNumber(tableRow.number, tableRow.e164number).getView()), isRead(tableRow.isRead)
{}
+CalllogRecord::CalllogRecord(const CallType type, const utils::PhoneNumber::View &number)
+ : presentation(PresentationType::PR_UNKNOWN), date(std::time(nullptr)), type(type), phoneNumber(number)
+{}
+
uint32_t CalllogRecord::getContactId() const
{
return contactId;
@@ 54,7 58,7 @@ CalllogRecordInterface::CalllogRecordInterface(CalllogDB *calllogDb, ContactsDB
bool CalllogRecordInterface::Add(const CalllogRecord &rec)
{
- auto localRec = rec;
+ auto localRec = rec;
if (!rec.phoneNumber.getFormatted().empty()) {
ContactRecordInterface contactInterface(contactsDB);
auto contactMatch =
M module-db/Interface/CalllogRecord.hpp => module-db/Interface/CalllogRecord.hpp +2 -1
@@ 29,7 29,8 @@ struct CalllogRecord : public Record
friend std::ostream &operator<<(std::ostream &out, const CalllogRecord &point);
[[nodiscard]] std::string str() const;
- CalllogRecord() = default;
+ CalllogRecord() = default;
+ CalllogRecord(const CallType type, const utils::PhoneNumber::View &number);
CalllogRecord(const CalllogTableRow &tableRow);
uint32_t getContactId() const;
M module-db/Interface/NotificationsRecord.cpp => module-db/Interface/NotificationsRecord.cpp +54 -17
@@ 4,6 4,7 @@
#include "NotificationsRecord.hpp"
#include "module-db/queries/notifications/QueryNotificationsGet.hpp"
#include "module-db/queries/notifications/QueryNotificationsIncrement.hpp"
+#include "module-db/queries/notifications/QueryNotificationsMultipleIncrement.hpp"
#include "module-db/queries/notifications/QueryNotificationsClear.hpp"
#include "module-db/queries/notifications/QueryNotificationsGetAll.hpp"
#include "Databases/NotificationsDB.hpp"
@@ 147,6 148,9 @@ std::unique_ptr<db::QueryResult> NotificationsRecordInterface::runQuery(std::sha
if (const auto local_query = dynamic_cast<const db::query::notifications::Increment *>(query.get())) {
return runQueryImpl(local_query);
}
+ if (const auto local_query = dynamic_cast<const db::query::notifications::MultipleIncrement *>(query.get())) {
+ return runQueryImpl(local_query);
+ }
if (const auto local_query = dynamic_cast<const db::query::notifications::Clear *>(query.get())) {
return runQueryImpl(local_query);
}
@@ 166,25 170,26 @@ std::unique_ptr<db::query::notifications::GetResult> NotificationsRecordInterfac
std::unique_ptr<db::query::notifications::IncrementResult> NotificationsRecordInterface::runQueryImpl(
const db::query::notifications::Increment *query)
{
- auto ret = false;
- if (auto record = GetByKey(query->getKey()); record.isValid()) {
- auto ¤tContactRecord = record.contactRecord;
- if (auto numberMatch = contactsDb->MatchByNumber(query->getNumber()); numberMatch.has_value()) {
- if (record.value == 0) {
- currentContactRecord = std::move(numberMatch.value().contact);
- }
- else if (currentContactRecord.has_value() &&
- numberMatch.value().contactId != currentContactRecord.value().ID) {
- currentContactRecord.reset();
- }
- }
- else {
- currentContactRecord.reset();
+ auto ret = processIncrement(query->getKey(), query->getNumber(), 1);
+
+ return std::make_unique<db::query::notifications::IncrementResult>(ret);
+}
+
+std::unique_ptr<db::query::notifications::MultipleIncrementResult> NotificationsRecordInterface::runQueryImpl(
+ const db::query::notifications::MultipleIncrement *query)
+{
+ auto ret = false;
+ const auto &numbers = query->getNumbers();
+ std::optional<utils::PhoneNumber::View> number;
+
+ if (!numbers.empty()) {
+ if (all_of(numbers.begin(), numbers.end(), [&](const auto &number) { return number == numbers.at(0); })) {
+ number = std::make_optional(numbers.at(0));
}
- record.value++;
- ret = Update(record);
+
+ ret = processIncrement(query->getKey(), std::move(number), numbers.size());
}
- return std::make_unique<db::query::notifications::IncrementResult>(ret);
+ return std::make_unique<db::query::notifications::MultipleIncrementResult>(ret);
}
std::unique_ptr<db::query::notifications::ClearResult> NotificationsRecordInterface::runQueryImpl(
@@ 206,3 211,35 @@ std::unique_ptr<db::query::notifications::GetAllResult> NotificationsRecordInter
auto records = GetLimitOffset(0, numberOfNotifications);
return std::make_unique<db::query::notifications::GetAllResult>(std::move(records));
}
+
+bool NotificationsRecordInterface::processIncrement(NotificationsRecord::Key key,
+ std::optional<utils::PhoneNumber::View> &&number,
+ size_t size)
+{
+ auto ret = false;
+
+ if (auto record = GetByKey(key); record.isValid() && number.has_value()) {
+ auto ¤tContactRecord = record.contactRecord;
+ if (size == 1) {
+ if (auto numberMatch = contactsDb->MatchByNumber(number.value()); numberMatch.has_value()) {
+ if (record.value == 0) {
+ currentContactRecord = std::move(numberMatch.value().contact);
+ }
+ else if (currentContactRecord.has_value() &&
+ numberMatch.value().contactId != currentContactRecord.value().ID) {
+ currentContactRecord.reset();
+ }
+ }
+ else {
+ currentContactRecord.reset();
+ }
+ }
+ else if (size > 1) {
+ currentContactRecord.reset();
+ }
+ record.value += size;
+ ret = Update(record);
+ }
+
+ return ret;
+}
M module-db/Interface/NotificationsRecord.hpp => module-db/Interface/NotificationsRecord.hpp +9 -2
@@ 21,6 21,8 @@ namespace db::query::notifications
class Get;
class GetResult;
class Increment;
+ class MultipleIncrement;
+ class MultipleIncrementResult;
class IncrementResult;
class Clear;
class ClearResult;
@@ 44,7 46,7 @@ struct NotificationsRecord : public Record
friend std::ostream &operator<<(std::ostream &out, const NotificationsRecord &point);
- NotificationsRecord() = default;
+ NotificationsRecord() = default;
explicit NotificationsRecord(const NotificationsTableRow &tableRow,
std::optional<ContactRecord> record = std::nullopt);
@@ 78,13 80,18 @@ class NotificationsRecordInterface : public RecordInterface<NotificationsRecord,
std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;
private:
- NotificationsDB *notificationsDb = nullptr;
+ NotificationsDB *notificationsDb = nullptr;
ContactRecordInterface *contactsDb = nullptr;
std::optional<ContactRecord> getContactRecord(uint32_t id) const;
std::unique_ptr<db::query::notifications::GetResult> runQueryImpl(const db::query::notifications::Get *query);
std::unique_ptr<db::query::notifications::IncrementResult> runQueryImpl(
const db::query::notifications::Increment *query);
+ std::unique_ptr<db::query::notifications::MultipleIncrementResult> runQueryImpl(
+ const db::query::notifications::MultipleIncrement *query);
std::unique_ptr<db::query::notifications::ClearResult> runQueryImpl(const db::query::notifications::Clear *query);
std::unique_ptr<db::query::notifications::GetAllResult> runQueryImpl(const db::query::notifications::GetAll *query);
+ [[nodiscard]] bool processIncrement(NotificationsRecord::Key key,
+ std::optional<utils::PhoneNumber::View> &&number,
+ size_t size);
};
M module-db/Interface/SMSRecord.cpp => module-db/Interface/SMSRecord.cpp +0 -2
@@ 68,7 68,6 @@ bool SMSRecordInterface::Add(const SMSRecord &rec)
.threadID = thread.ID,
.contactID = contactID,
.date = rec.date,
- .dateSent = rec.dateSent,
.errorCode = rec.errorCode,
.body = rec.body,
.type = rec.type
@@ 175,7 174,6 @@ bool SMSRecordInterface::Update(const SMSRecord &recUpdated)
.threadID = recCurrent.threadID,
.contactID = recCurrent.contactID,
.date = recUpdated.date,
- .dateSent = recUpdated.dateSent,
.errorCode = recUpdated.errorCode,
.body = recUpdated.body,
.type = recUpdated.type});
M module-db/Interface/SMSRecord.hpp => module-db/Interface/SMSRecord.hpp +5 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 23,7 23,6 @@ namespace db::query
struct SMSRecord : public Record
{
uint32_t date = 0;
- uint32_t dateSent = 0;
uint32_t errorCode = 0;
UTF8 body;
SMSType type = SMSType::UNKNOWN;
@@ 33,12 32,12 @@ struct SMSRecord : public Record
SMSRecord() = default;
SMSRecord(const SMSTableRow &w)
- : Record(w.ID), date(w.date), dateSent(w.dateSent), errorCode(w.errorCode), body(w.body), type(w.type),
- threadID(w.threadID), contactID(w.contactID)
+ : Record(w.ID), date(w.date), errorCode(w.errorCode), body(w.body), type(w.type), threadID(w.threadID),
+ contactID(w.contactID)
{}
SMSRecord(const SMSTableRow &w, const utils::PhoneNumber::View &num)
- : Record(w.ID), date(w.date), dateSent(w.dateSent), errorCode(w.errorCode), body(w.body), type(w.type),
- threadID(w.threadID), contactID(w.contactID), number(num)
+ : Record(w.ID), date(w.date), errorCode(w.errorCode), body(w.body), type(w.type), threadID(w.threadID),
+ contactID(w.contactID), number(num)
{}
};
M module-db/Tables/SMSTable.cpp => module-db/Tables/SMSTable.cpp +35 -47
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SMSTable.hpp"
@@ 14,12 14,11 @@ bool SMSTable::create()
bool SMSTable::add(SMSTableRow entry)
{
- return db->execute("INSERT or ignore INTO sms ( thread_id,contact_id, date, date_send, error_code, body, "
- "type ) VALUES (%lu,%lu,%lu,%lu,0,'%q',%d);",
+ return db->execute("INSERT or ignore INTO sms ( thread_id,contact_id, date, error_code, body, "
+ "type ) VALUES (%lu,%lu,%lu,0,'%q',%d);",
entry.threadID,
entry.contactID,
entry.date,
- entry.dateSent,
entry.body.c_str(),
entry.type);
}
@@ 54,12 53,11 @@ bool SMSTable::removeByField(SMSTableFields field, const char *str)
bool SMSTable::update(SMSTableRow entry)
{
- return db->execute("UPDATE sms SET thread_id = %lu, contact_id = %lu ,date = %lu, date_send = %lu, error_code = 0, "
+ return db->execute("UPDATE sms SET thread_id = %lu, contact_id = %lu ,date = %lu, error_code = 0, "
"body = '%q', type =%d WHERE _id=%lu;",
entry.threadID,
entry.contactID,
entry.date,
- entry.dateSent,
entry.body.c_str(),
entry.type,
entry.ID);
@@ 78,10 76,9 @@ SMSTableRow SMSTable::getById(uint32_t id)
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
};
}
@@ 101,10 98,9 @@ std::vector<SMSTableRow> SMSTable::getByContactId(uint32_t contactId)
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
@@ 130,10 126,9 @@ std::vector<SMSTableRow> SMSTable::getByThreadId(uint32_t threadId, uint32_t off
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
@@ 146,7 141,7 @@ std::vector<SMSTableRow> SMSTable::getByThreadIdWithoutDraftWithEmptyInput(uint3
{
auto retQuery = db->query("SELECT * FROM sms WHERE thread_id= %u AND type != %u UNION ALL SELECT 0 as _id, 0 as "
"thread_id, 0 as contact_id, 0 as "
- "date, 0 as date_send, 0 as error_code, 0 as body, %u as type LIMIT %u OFFSET %u",
+ "date, 0 as error_code, 0 as body, %u as type LIMIT %u OFFSET %u",
threadId,
SMSType::DRAFT,
SMSType::INPUT,
@@ 165,10 160,9 @@ std::vector<SMSTableRow> SMSTable::getByThreadIdWithoutDraftWithEmptyInput(uint3
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
@@ 200,10 194,9 @@ SMSTableRow SMSTable::getDraftByThreadId(uint32_t threadId)
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
};
}
@@ 224,10 217,9 @@ std::vector<SMSTableRow> SMSTable::getByText(std::string text)
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
@@ 249,10 241,9 @@ std::vector<SMSTableRow> SMSTable::getByText(std::string text, uint32_t threadId
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
return ret;
@@ 274,10 265,9 @@ std::vector<SMSTableRow> SMSTable::getLimitOffset(uint32_t offset, uint32_t limi
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
@@ 323,10 313,9 @@ std::vector<SMSTableRow> SMSTable::getLimitOffsetByField(uint32_t offset,
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
@@ 375,10 364,9 @@ std::pair<uint32_t, std::vector<SMSTableRow>> SMSTable::getManyByType(SMSType ty
(*retQuery)[1].getUInt32(), // threadID
(*retQuery)[2].getUInt32(), // contactID
(*retQuery)[3].getUInt32(), // date
- (*retQuery)[4].getUInt32(), // dateSent
- (*retQuery)[5].getUInt32(), // errorCode
- (*retQuery)[6].getString(), // body
- static_cast<SMSType>((*retQuery)[7].getUInt32()), // type
+ (*retQuery)[4].getUInt32(), // errorCode
+ (*retQuery)[5].getString(), // body
+ static_cast<SMSType>((*retQuery)[6].getUInt32()), // type
});
} while (retQuery->nextRow());
}
M module-db/Tables/SMSTable.hpp => module-db/Tables/SMSTable.hpp +1 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 14,7 14,6 @@ struct SMSTableRow : public Record
uint32_t threadID;
uint32_t contactID;
uint32_t date;
- uint32_t dateSent;
uint32_t errorCode;
UTF8 body;
SMSType type;
A module-db/queries/notifications/QueryNotificationsMultipleIncrement.cpp => module-db/queries/notifications/QueryNotificationsMultipleIncrement.cpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "QueryNotificationsMultipleIncrement.hpp"
+
+namespace db::query::notifications
+{
+ MultipleIncrement::MultipleIncrement(NotificationsRecord::Key key,
+ const std::vector<utils::PhoneNumber::View> &numbers)
+ : Query(Query::Type::Update), key(key), numbers(numbers)
+ {}
+
+ auto MultipleIncrement::getKey() const noexcept -> NotificationsRecord::Key
+ {
+ return key;
+ }
+ auto MultipleIncrement::getNumbers() const noexcept -> const std::vector<utils::PhoneNumber::View> &
+ {
+ return numbers;
+ }
+
+ auto MultipleIncrement::debugInfo() const -> std::string
+ {
+ return "MultipleIncrement";
+ }
+
+ MultipleIncrementResult::MultipleIncrementResult(bool ret) : ret(ret)
+ {}
+
+ auto MultipleIncrementResult::getResult() const noexcept -> bool
+ {
+ return ret;
+ }
+
+ auto MultipleIncrementResult::debugInfo() const -> std::string
+ {
+ return "MultipleIncrementResult";
+ }
+} // namespace db::query::notifications
A module-db/queries/notifications/QueryNotificationsMultipleIncrement.hpp => module-db/queries/notifications/QueryNotificationsMultipleIncrement.hpp +38 -0
@@ 0,0 1,38 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Interface/NotificationsRecord.hpp>
+#include <Common/Query.hpp>
+#include <string>
+#include <PhoneNumber.hpp>
+
+namespace db::query::notifications
+{
+ class MultipleIncrement : public Query
+ {
+ const NotificationsRecord::Key key;
+ const std::vector<utils::PhoneNumber::View> numbers;
+
+ public:
+ MultipleIncrement(NotificationsRecord::Key key, const std::vector<utils::PhoneNumber::View> &numbers);
+
+ [[nodiscard]] auto getKey() const noexcept -> NotificationsRecord::Key;
+ [[nodiscard]] auto getNumbers() const noexcept -> const std::vector<utils::PhoneNumber::View> &;
+
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
+ class MultipleIncrementResult : public QueryResult
+ {
+ bool ret;
+
+ public:
+ explicit MultipleIncrementResult(bool ret);
+ [[nodiscard]] auto getResult() const noexcept -> bool;
+
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
+} // namespace db::query::notifications
M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +3 -3
@@ 35,10 35,10 @@ add_catch2_executable(
common.cpp
LIBS
- module-db
- module-vfs
+ module-sys
iosyscalls
+ module-db
DEPS
- disk_image
+ assets
)
add_subdirectory(test-initializer)
M module-db/tests/SMSRecord_tests.cpp => module-db/tests/SMSRecord_tests.cpp +0 -2
@@ 40,7 40,6 @@ TEST_CASE("SMS Record tests")
SmsDB smsDB(smsPath.c_str());
const uint32_t dateTest = 123456789;
- const uint32_t dateSentTest = 987654321;
const uint32_t errorCodeTest = 555;
auto numberTest = utils::PhoneNumber("+48600123456", utils::country::Id::UNKNOWN).getView();
auto numberTest2 = utils::PhoneNumber("222333444", utils::country::Id::UNKNOWN).getView();
@@ 52,7 51,6 @@ TEST_CASE("SMS Record tests")
SMSRecord recordIN;
recordIN.date = dateTest;
- recordIN.dateSent = dateSentTest;
recordIN.errorCode = errorCodeTest;
recordIN.number = numberTest;
recordIN.body = bodyTest;
M module-db/tests/SMSTable_tests.cpp => module-db/tests/SMSTable_tests.cpp +0 -2
@@ 28,7 28,6 @@ TEST_CASE("SMS Table tests")
.threadID = 0,
.contactID = 0,
.date = 0,
- .dateSent = 0,
.errorCode = 0,
.body = "Test SMS message 1",
.type = SMSType ::INBOX
@@ 39,7 38,6 @@ TEST_CASE("SMS Table tests")
.threadID = 0,
.contactID = 0,
.date = 0,
- .dateSent = 0,
.errorCode = 0,
.body = "Test Draft SMS",
.type = SMSType ::DRAFT
M module-db/tests/ThreadRecord_tests.cpp => module-db/tests/ThreadRecord_tests.cpp +0 -2
@@ 218,7 218,6 @@ TEST_CASE("Thread Record tests")
SMSRecordInterface smsRecInterface(&smsDB, &contactsDB);
SMSRecord recordIN;
recordIN.date = 123456789;
- recordIN.dateSent = 987654321;
recordIN.errorCode = 0;
recordIN.number = phoneNumber.getView();
recordIN.body = "Ala";
@@ 274,7 273,6 @@ TEST_CASE("Thread Record tests")
SMSRecordInterface smsRecInterface(&smsDB, &contactsDB);
SMSRecord recordIN;
recordIN.date = 123456789;
- recordIN.dateSent = 987654321;
recordIN.errorCode = 0;
recordIN.number = phoneNumber.getView();
recordIN.type = SMSType ::DRAFT;
M module-db/tests/test-initializer/CMakeLists.txt => module-db/tests/test-initializer/CMakeLists.txt +3 -3
@@ 10,9 10,9 @@ add_catch2_executable(
"${CMAKE_CURRENT_SOURCE_DIR}/tests-main.cpp"
LIBS
- module-db
- module-vfs
+ module-sys
iosyscalls
+ module-db
DEPS
- disk_image
+ assets
)
M module-gui/gui/widgets/TopBar/Time.cpp => module-gui/gui/widgets/TopBar/Time.cpp +2 -2
@@ 2,9 2,9 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Time.hpp"
-#include "time/time_conversion.hpp"
#include "Style.hpp"
+#include <ctime>
namespace gui::top_bar
{
Time::Time(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
@@ 21,7 21,7 @@ namespace gui::top_bar
void Time::update()
{
- _time.set_time(utils::time::getCurrentTimestamp().getTime());
+ _time.set_time(std::time(nullptr));
setText(_time.str());
}
M module-gui/test/test-catch-text/CMakeLists.txt => module-gui/test/test-catch-text/CMakeLists.txt +2 -3
@@ 20,10 20,9 @@ add_catch2_executable(
..
../mock/
LIBS
- module-vfs
- module-gui
+ module-sys
iosyscalls
+ module-gui
DEPS
assets
- disk_image
)
M module-gui/test/test-catch/CMakeLists.txt => module-gui/test/test-catch/CMakeLists.txt +2 -3
@@ 14,10 14,9 @@ add_catch2_executable(
INCLUDE
..
LIBS
- module-gui
- module-vfs
+ module-sys
iosyscalls
+ module-gui
DEPS
assets
- disk_image
)
M module-services/service-appmgr/model/ApplicationManager.cpp => module-services/service-appmgr/model/ApplicationManager.cpp +41 -4
@@ 17,6 17,8 @@
#include <application-call/ApplicationCall.hpp>
#include <application-special-input/ApplicationSpecialInput.hpp>
#include <application-desktop/ApplicationDesktop.hpp>
+#include <application-onboarding/ApplicationOnBoarding.hpp>
+#include <application-onboarding/data/OnBoardingMessages.hpp>
#include <i18n/i18n.hpp>
#include <log/log.hpp>
#include <service-appmgr/messages/Message.hpp>
@@ 437,7 439,7 @@ namespace app::manager
});
connect(typeid(locks::UnLockPhoneInput), [&](sys::Message *request) -> sys::MessagePointer {
auto data = static_cast<locks::UnLockPhoneInput *>(request);
- return phoneLockHandler.verifyPhoneLockInput(data->getInputData());
+ return phoneLockHandler.handlePhoneLockInput(data->getInputData());
});
connect(typeid(locks::EnablePhoneLock),
[&](sys::Message *request) -> sys::MessagePointer { return phoneLockHandler.handleEnablePhoneLock(); });
@@ 463,6 465,14 @@ namespace app::manager
auto req = static_cast<SetAutoLockTimeoutRequest *>(request);
return handleAutoLockSetRequest(req);
});
+ connect(typeid(locks::ExternalUnLockPhone), [&](sys::Message *request) -> sys::MessagePointer {
+ auto data = static_cast<locks::ExternalUnLockPhone *>(request);
+ return phoneLockHandler.handleExternalUnlockRequest(data->getInputData());
+ });
+ connect(typeid(locks::ExternalPhoneLockAvailabilityChange), [&](sys::Message *request) -> sys::MessagePointer {
+ auto data = static_cast<locks::ExternalPhoneLockAvailabilityChange *>(request);
+ return phoneLockHandler.handleExternalAvailabilityChange(data->getAvailability());
+ });
// SimLock connects
connect(typeid(cellular::msg::notification::SimNeedPin), [&](sys::Message *request) -> sys::MessagePointer {
@@ 506,7 516,7 @@ namespace app::manager
[&](sys::Message *request) -> sys::MessagePointer {
auto data = static_cast<cellular::msg::request::sim::ChangePin::Response *>(request);
if (data->retCode) {
- return simLockHandler.handleSimChangedMessage();
+ return simLockHandler.handleSimPinChangedMessage();
}
else {
return simLockHandler.handleSimPinChangeFailedRequest();
@@ 560,9 570,12 @@ namespace app::manager
}
return sys::msgNotHandled();
});
+ connect(typeid(cellular::msg::notification::SimReady),
+ [&](sys::Message *request) -> sys::MessagePointer { return simLockHandler.handleSimReadyMessage(); });
connect(typeid(cellular::StateChange), [&](sys::Message *request) -> sys::MessagePointer {
auto data = static_cast<cellular::StateChange *>(request);
if (data->request == cellular::service::State::ST::URCReady) {
+ simLockHandler.setSimReady();
simLockHandler.getSettingsSimSelect(
settings->getValue(settings::SystemProperties::activeSim, settings::SettingsScope::Global));
return sys::msgHandled();
@@ 570,6 583,9 @@ namespace app::manager
return sys::msgNotHandled();
});
+ connect(typeid(onBoarding::FinalizeOnBoarding),
+ [&](sys::Message *request) -> sys::MessagePointer { return handleOnBoardingFinalize(); });
+
connect(typeid(sdesktop::developerMode::DeveloperModeRequest),
[&](sys::Message *request) -> sys::MessagePointer { return handleDeveloperModeRequest(request); });
@@ 777,9 793,9 @@ namespace app::manager
auto ApplicationManager::handleHomeAction(ActionEntry &action) -> ActionProcessStatus
{
- action.setTargetApplication(rootApplicationName);
+ action.setTargetApplication(resolveHomeApplication());
- SwitchRequest switchRequest(ServiceName, rootApplicationName, resolveHomeWindow(), nullptr);
+ SwitchRequest switchRequest(ServiceName, resolveHomeApplication(), resolveHomeWindow(), nullptr);
return handleSwitchApplication(&switchRequest) ? ActionProcessStatus::Accepted : ActionProcessStatus::Dropped;
}
@@ 789,6 805,27 @@ namespace app::manager
: gui::name::window::main_window;
}
+ auto ApplicationManager::handleOnBoardingFinalize() -> sys::MessagePointer
+ {
+ settings->setValue(settings::SystemProperties::onboardingDone, utils::to_string(true));
+ app::manager::Controller::sendAction(this, app::manager::actions::Home);
+ return sys::msgHandled();
+ }
+
+ auto ApplicationManager::checkOnBoarding() -> bool
+ {
+ return not utils::getNumericValue<bool>(settings->getValue(settings::SystemProperties::onboardingDone));
+ }
+
+ auto ApplicationManager::resolveHomeApplication() -> std::string
+ {
+ if (checkOnBoarding()) {
+ phoneLockHandler.handleUnlockRequest();
+ return app::name_onboarding;
+ }
+ return rootApplicationName;
+ }
+
auto ApplicationManager::handleLaunchAction(ActionEntry &action) -> ActionProcessStatus
{
auto launchParams = static_cast<ApplicationLaunchData *>(action.params.get());
M module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp => module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp +3 -0
@@ 129,6 129,9 @@ namespace app::manager
void handleActionRequest(ActionRequest *actionMsg);
auto handleHomeAction(ActionEntry &action) -> ActionProcessStatus;
auto resolveHomeWindow() -> std::string;
+ auto handleOnBoardingFinalize() -> sys::MessagePointer;
+ auto checkOnBoarding() -> bool;
+ auto resolveHomeApplication() -> std::string;
auto handleLaunchAction(ActionEntry &action) -> ActionProcessStatus;
auto handleActionOnFocusedApp(ActionEntry &action) -> ActionProcessStatus;
auto handlePhoneModeChangedAction(ActionEntry &action) -> ActionProcessStatus;
M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +31 -13
@@ 26,11 26,11 @@ using namespace audio;
inline constexpr auto audioServiceStackSize = 1024 * 4;
-static constexpr auto defaultVolumeHigh = "10";
-static constexpr auto defaultVolumeLow = "2";
-static constexpr auto defaultVolumeMuted = "0";
-static constexpr auto defaultTrue = "1";
-static constexpr auto defaultFalse = "0";
+static constexpr auto defaultVolumeHigh = "10";
+static constexpr auto defaultVolumeLow = "2";
+static constexpr auto defaultVolumeMuted = "0";
+static constexpr auto defaultTrue = "1";
+static constexpr auto defaultFalse = "0";
static constexpr auto defaultCallRingtonePath = "assets/audio/ringtone/ringtone_drum_2.mp3";
static constexpr auto defaultTextMessageRingtonePath = "assets/audio/sms/sms_drum_2.mp3";
static constexpr auto defaultNotificationsPath = "assets/audio/alarm/alarm_hang_drum.mp3";
@@ 153,9 153,14 @@ std::optional<std::string> ServiceAudio::AudioServicesCallback(const sys::Messag
return settings_it->second;
}
else if (const auto *deviceMsg = dynamic_cast<const AudioServiceMessage::AudioDeviceCreated *>(msg); deviceMsg) {
- if (deviceMsg->getDeviceType() == AudioDevice::Type::Bluetooth) {
+ if (deviceMsg->getDeviceType() == AudioDevice::Type::BluetoothA2DP) {
auto startBluetoothAudioMsg = std::make_shared<BluetoothAudioStartMessage>(
- std::static_pointer_cast<bluetooth::BluetoothAudioDevice>(deviceMsg->getDevice()));
+ std::static_pointer_cast<bluetooth::A2DPAudioDevice>(deviceMsg->getDevice()));
+ bus.sendUnicast(std::move(startBluetoothAudioMsg), service::name::bluetooth);
+ }
+ else if (deviceMsg->getDeviceType() == AudioDevice::Type::BluetoothHSP) {
+ auto startBluetoothAudioMsg = std::make_shared<BluetoothAudioStartMessage>(
+ std::static_pointer_cast<bluetooth::HSPAudioDevice>(deviceMsg->getDevice()));
bus.sendUnicast(std::move(startBluetoothAudioMsg), service::name::bluetooth);
}
}
@@ 325,11 330,14 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
if (opType == Operation::Type::Playback) {
auto input = audioMux.GetPlaybackInput(playbackType);
// stop bluetooth stream if available
- if (bluetoothConnected) {
+ if (bluetoothA2DPConnected || bluetoothHSPConnected) {
if (playbackType == audio::PlaybackType::CallRingtone) {
+ HandleSendEvent(std::make_shared<audio::Event>(EventType::BlutoothHSPDeviceState));
+
LOG_DEBUG("Sending Bluetooth start ringing");
bus.sendUnicast(std::make_shared<message::bluetooth::Ring>(message::bluetooth::Ring::State::Enable),
service::name::bluetooth);
+ return std::make_unique<AudioStartPlaybackResponse>(audio::RetCode::Success, retToken);
}
else {
LOG_DEBUG("Sending Bluetooth start stream request");
@@ 348,7 356,10 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStart(const Operation:
}
else if (opType == Operation::Type::Router) {
auto input = audioMux.GetRoutingInput(true);
- if (bluetoothConnected) {
+ if (bluetoothA2DPConnected) {
+ HandleSendEvent(std::make_shared<audio::Event>(EventType::BlutoothHSPDeviceState));
+ }
+ if (bluetoothHSPConnected) {
LOG_DEBUG("Sending Bluetooth start routing");
bus.sendUnicast(std::make_shared<message::bluetooth::StartAudioRouting>(), service::name::bluetooth);
}
@@ 363,11 374,10 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_
// update bluetooth state
if (evt->getType() == EventType::BlutoothA2DPDeviceState) {
auto newState = evt->getDeviceState() == Event::DeviceState::Connected;
- if (newState != bluetoothConnected) {
+ if (newState != bluetoothA2DPConnected) {
LOG_DEBUG("Bluetooth connection status changed: %s", newState ? "connected" : "disconnected");
- bluetoothConnected = newState;
+ bluetoothA2DPConnected = newState;
HandleStop({audio::PlaybackType::Alarm,
- audio::PlaybackType::CallRingtone,
audio::PlaybackType::Meditation,
audio::PlaybackType::Notifications,
audio::PlaybackType::TextMessageRingtone},
@@ 375,6 385,14 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleSendEvent(std::shared_
}
}
+ if (evt->getType() == EventType::BlutoothHSPDeviceState) {
+ auto newState = evt->getDeviceState() == Event::DeviceState::Connected;
+ if (newState != bluetoothHSPConnected) {
+ LOG_DEBUG("Bluetooth connection status changed: %s", newState ? "connected" : "disconnected");
+ bluetoothHSPConnected = newState;
+ }
+ }
+
// update information about endpoints availability
for (auto &input : audioMux.GetAllInputs()) {
input.audio->SendEvent(evt);
@@ 426,7 444,7 @@ std::unique_ptr<AudioResponseMessage> ServiceAudio::HandleStop(const std::vector
}
// stop bluetooth stream if available
- if (bluetoothConnected) {
+ if (bluetoothA2DPConnected) {
LOG_DEBUG("Sending Bluetooth stop request");
bus.sendUnicast(std::make_shared<BluetoothMessage>(BluetoothMessage::Request::Stop), service::name::bluetooth);
}
M module-services/service-audio/service-audio/ServiceAudio.hpp => module-services/service-audio/service-audio/ServiceAudio.hpp +2 -1
@@ 57,7 57,8 @@ class ServiceAudio : public sys::Service
audio::AudioMux::VibrationStatus vibrationMotorStatus = audio::AudioMux::VibrationStatus::Off;
std::unique_ptr<settings::Settings> settingsProvider;
std::map<std::string, std::string> settingsCache;
- bool bluetoothConnected = false;
+ bool bluetoothA2DPConnected = false;
+ bool bluetoothHSPConnected = false;
auto IsVibrationMotorOn()
{
M module-services/service-cellular/CellularCall.cpp => module-services/service-cellular/CellularCall.cpp +4 -8
@@ 7,9 7,9 @@
#include <PhoneNumber.hpp>
#include <Utils.hpp>
#include <log/log.hpp>
-#include <time/time_conversion.hpp>
#include <cinttypes>
+#include <ctime>
#include <optional>
#include <sstream>
#include <stdexcept>
@@ 30,11 30,7 @@ namespace CellularCall
}
clear();
- CalllogRecord callRec;
- callRec.type = type;
- callRec.date = utils::time::Timestamp().getTime();
- callRec.presentation = PresentationType::PR_UNKNOWN;
- callRec.phoneNumber = number;
+ CalllogRecord callRec{type, number};
call = startCallAction ? startCallAction(callRec) : CalllogRecord();
if (!call.isValid()) {
LOG_ERROR("startCallAction failed");
@@ 51,7 47,7 @@ namespace CellularCall
bool CellularCall::setActive()
{
if (isValid()) {
- startActiveTime = utils::time::Timestamp();
+ startActiveTime = utils::time::getCurrentTimestamp();
isActiveCall = true;
return true;
}
@@ 70,7 66,7 @@ namespace CellularCall
}
if (isActiveCall) {
- auto endTime = utils::time::Timestamp();
+ auto endTime = utils::time::getCurrentTimestamp();
call.duration = (endTime - startActiveTime).get();
}
else {
M module-services/service-cellular/CellularUrcHandler.cpp => module-services/service-cellular/CellularUrcHandler.cpp +1 -1
@@ 154,7 154,7 @@ void CellularUrcHandler::Handle(Cpin &urc)
LOG_INFO("Invalid cpin - ignore");
}
else {
- response = std::make_unique<cellular::internal::msg::SimStateChanged>(*state);
+ response = std::make_unique<cellular::internal::msg::HandleATSimStateChange>(*state);
urc.setHandled(true);
}
}
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +116 -8
@@ 58,6 58,7 @@
#include <at/UrcFactory.hpp>
#include <queries/messages/sms/QuerySMSSearchByType.hpp>
#include <queries/notifications/QueryNotificationsIncrement.hpp>
+#include <queries/notifications/QueryNotificationsMultipleIncrement.hpp>
#include <projdefs.h>
#include <service-antenna/AntennaMessage.hpp>
#include <service-antenna/AntennaServiceAPI.hpp>
@@ 74,7 75,6 @@
#include <service-desktop/DeveloperModeMessage.hpp>
#include <service-appmgr/model/ApplicationManager.hpp>
#include <task.h>
-#include <time/time_conversion.hpp>
#include <ucs2/UCS2.hpp>
#include <utf8/UTF8.hpp>
@@ 99,6 99,8 @@
#include <service-cellular/api/request/sim.hpp>
#include <service-cellular/api/notification/notification.hpp>
+#include <ctime>
+
const char *ServiceCellular::serviceName = cellular::service::name;
inline constexpr auto cellularStack = 8000;
@@ 279,9 281,23 @@ void ServiceCellular::registerMessageHandlers()
phoneModeObserver->connect(this);
phoneModeObserver->subscribe(
[this](sys::phone_modes::PhoneMode mode) { connectionManager->onPhoneModeChange(mode); });
- phoneModeObserver->subscribe([](sys::phone_modes::Tethering tethering) {
+ phoneModeObserver->subscribe([&](sys::phone_modes::Tethering tethering) {
using bsp::cellular::USB::setPassthrough;
using bsp::cellular::USB::PassthroughState;
+ if (tethering == sys::phone_modes::Tethering::On) {
+ if (!tetheringTurnOffURC()) {
+ LOG_ERROR("Failed to disable URC on tethering enable");
+ }
+ }
+ else {
+ if (!tetheringTurnOnURC()) {
+ LOG_ERROR("Failed to enable URC on tethering disable");
+ }
+ if (!receiveAllMessages()) {
+ LOG_ERROR("Failed to receive all sms after tethering disabling");
+ }
+ logTetheringCalls();
+ }
setPassthrough(tethering == sys::phone_modes::Tethering::On ? PassthroughState::ENABLED
: PassthroughState::DISABLED);
});
@@ 1116,8 1132,7 @@ auto ServiceCellular::receiveSMS(std::string messageNumber) -> bool
// parse date
tokens[3].erase(std::remove(tokens[3].begin(), tokens[3].end(), '\"'), tokens[3].end());
- utils::time::Timestamp time;
- auto messageDate = time.getTime();
+ auto messageDate = std::time(nullptr);
if (tokens.size() == 5) {
LOG_DEBUG("Single message");
@@ 1413,6 1428,7 @@ bool ServiceCellular::handle_modem_on()
channel->cmd("AT+CCLK?");
// inform host ap ready
cmux->informModemHostWakeup();
+ tetheringTurnOnURC();
priv->state->set(State::ST::URCReady);
LOG_DEBUG("AP ready");
return true;
@@ 2048,6 2064,7 @@ auto ServiceCellular::handleCellularIncominCallMessage(sys::Message *msg) -> std
auto ServiceCellular::handleCellularCallerIdMessage(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
+
auto message = static_cast<CellularCallerIdMessage *>(msg);
ongoingCall.setNumber(message->number);
return sys::MessageNone{};
@@ 2319,13 2336,19 @@ auto ServiceCellular::handleCellularRingNotification(sys::Message *msg) -> std::
auto ServiceCellular::handleCellularCallerIdNotification(sys::Message *msg) -> std::shared_ptr<sys::ResponseMessage>
{
+ auto message = static_cast<CellularCallerIdNotification *>(msg);
if (isIncommingCallAllowed()) {
- auto message = static_cast<CellularCallerIdNotification *>(msg);
bus.sendMulticast(std::make_shared<CellularCallerIdMessage>(message->getNubmer()),
sys::BusChannel::ServiceCellularNotifications);
return std::make_shared<CellularResponseMessage>(true);
}
- return std::make_shared<CellularResponseMessage>(this->hangUpCall());
+ else {
+ if (phoneModeObserver->isTetheringOn()) {
+ tetheringCalllog.push_back(CalllogRecord{CallType::CT_MISSED, message->getNubmer()});
+ return std::make_shared<CellularResponseMessage>(hangUpCallBusy());
+ }
+ }
+ return std::make_shared<CellularResponseMessage>(hangUpCall());
}
auto ServiceCellular::handleCellularSetConnectionFrequencyMessage(sys::Message *msg)
@@ 2343,13 2366,13 @@ auto ServiceCellular::handleCellularSetConnectionFrequencyMessage(sys::Message *
auto ServiceCellular::isIncommingCallAllowed() -> bool
{
- return phoneModeObserver->isInMode(sys::phone_modes::PhoneMode::Connected);
+ return phoneModeObserver->isInMode(sys::phone_modes::PhoneMode::Connected) && !phoneModeObserver->isTetheringOn();
}
auto ServiceCellular::hangUpCall() -> bool
{
auto channel = cmux->get(CellularMux::Channel::Commands);
- if (channel) {
+ if (channel != nullptr) {
if (channel->cmd(at::factory(at::AT::ATH))) {
return true;
}
@@ 2357,3 2380,88 @@ auto ServiceCellular::hangUpCall() -> bool
LOG_ERROR("Failed to hang up call");
return false;
}
+
+auto ServiceCellular::hangUpCallBusy() -> bool
+{
+ auto channel = cmux->get(CellularMux::Channel::Commands);
+ if (channel != nullptr) {
+ if (channel->cmd(at::factory(at::AT::QHUP_BUSY))) {
+ return true;
+ }
+ }
+ LOG_ERROR("Failed to hang up call");
+ return false;
+}
+
+auto ServiceCellular::tetheringTurnOffURC() -> bool
+{
+ auto channel = cmux->get(CellularMux::Channel::Commands);
+ if (channel != nullptr) {
+ if (!channel->cmd(at::factory(at::AT::CSQ_URC_OFF))) {
+ LOG_ERROR("Failed to stop CSQ URC");
+ return false;
+ }
+ if (!channel->cmd(at::factory(at::AT::ACT_URC_OFF))) {
+ LOG_ERROR("Failed to stop ACT URC");
+ return false;
+ }
+ if (!channel->cmd(at::factory(at::AT::SMS_URC_OFF))) {
+ LOG_ERROR("Failed to stop SMS URC");
+ return false;
+ }
+ if (!channel->cmd(at::factory(at::AT::RING_URC_OFF))) {
+ LOG_ERROR("Failed to stop RING URC");
+ return false;
+ }
+ }
+ return true;
+}
+
+auto ServiceCellular::tetheringTurnOnURC() -> bool
+{
+ auto channel = cmux->get(CellularMux::Channel::Commands);
+ if (channel != nullptr) {
+ if (!channel->cmd(at::factory(at::AT::CSQ_URC_ON))) {
+ LOG_ERROR("Failed to stop CSQ URC");
+ return false;
+ }
+ if (!channel->cmd(at::factory(at::AT::ACT_URC_ON))) {
+ LOG_ERROR("Failed to stop ACT URC");
+ return false;
+ }
+ if (!channel->cmd(at::factory(at::AT::SMS_URC_ON))) {
+ LOG_ERROR("Failed to stop SMS URC");
+ return false;
+ }
+
+ if (!channel->cmd(at::factory(at::AT::RING_URC_ON))) {
+ LOG_ERROR("Failed to stop RING URC");
+ return false;
+ }
+ }
+ return true;
+}
+
+auto ServiceCellular::logTetheringCalls() -> void
+{
+ if (!tetheringCalllog.empty()) {
+ for (auto callRecord : tetheringCalllog) {
+ auto call = DBServiceAPI::CalllogAdd(this, callRecord);
+ if (call.ID == DB_ID_NONE) {
+ LOG_ERROR("CalllogAdd failed");
+ }
+ }
+
+ std::vector<utils::PhoneNumber::View> numbers;
+ for (auto calllogRecord : tetheringCalllog) {
+ numbers.push_back(calllogRecord.phoneNumber);
+ }
+
+ DBServiceAPI::GetQuery(
+ this,
+ db::Interface::Name::Notifications,
+ std::make_unique<db::query::notifications::MultipleIncrement>(NotificationsRecord::Key::Calls, numbers));
+
+ tetheringCalllog.clear();
+ }
+}
A module-services/service-cellular/include/service-cellular/api/message.hpp => module-services/service-cellular/include/service-cellular/api/message.hpp +38 -0
@@ 0,0 1,38 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Service/Message.hpp>
+
+namespace cellular::msg
+{
+ struct Request : public sys::msg::Request
+ {
+ const char *target() const final
+ {
+ return m_target;
+ }
+
+ private:
+ static constexpr const char *m_target = cellular::service::name;
+ };
+
+ struct Response : public sys::msg::Response
+ {
+ explicit Response(bool retCode = true) : sys::msg::Response(retCode)
+ {}
+ };
+
+ struct Notification : public sys::msg::Notification
+ {
+ sys::BusChannel channel() const final
+ {
+ return m_channel;
+ }
+
+ private:
+ static constexpr sys::BusChannel m_channel = sys::BusChannel::ServiceCellularNotifications;
+ };
+
+} // namespace cellular::msg
M module-services/service-cellular/include/service-cellular/api/notification/notification.hpp => module-services/service-cellular/include/service-cellular/api/notification/notification.hpp +25 -38
@@ 3,49 3,36 @@
#pragma once
-#include <Service/Message.hpp>
-
#include <service-cellular/api/common.hpp>
+#include <service-cellular/api/message.hpp>
-namespace cellular::msg
+namespace cellular::msg::notification
{
- struct Notification : public sys::Message
+ struct SimReady : public msg::Notification
+ {};
+
+ struct SimNeedPin : public msg::Notification
+ {
+ explicit SimNeedPin(unsigned int attempts) : attempts(attempts)
+ {}
+ const unsigned int attempts;
+ };
+
+ struct SimNeedPuk : public msg::Notification
{
- Notification() : Message(Type::Data)
+ explicit SimNeedPuk(unsigned int attempts) : attempts(attempts)
{}
+ const unsigned int attempts;
};
- namespace notification
+ struct SimBlocked : public msg::Notification
+ {};
+
+ struct UnhandledCME : public msg::Notification
{
- struct SimReady : public msg::Notification
- {
- explicit SimReady(bool ready) : ready(ready)
- {}
- const bool ready;
- };
-
- struct SimNeedPin : public msg::Notification
- {
- explicit SimNeedPin(unsigned int attempts) : attempts(attempts)
- {}
- const unsigned int attempts;
- };
-
- struct SimNeedPuk : public msg::Notification
- {
- explicit SimNeedPuk(unsigned int attempts) : attempts(attempts)
- {}
- const unsigned int attempts;
- };
-
- struct SimBlocked : public msg::Notification
- {};
-
- struct UnhandledCME : public msg::Notification
- {
- explicit UnhandledCME(unsigned int code) : code(code)
- {}
- const unsigned int code;
- };
- } // namespace notification
-} // namespace cellular::msg
+ explicit UnhandledCME(unsigned int code) : code(code)
+ {}
+ const unsigned int code;
+ };
+
+} // namespace cellular::msg::notification
D module-services/service-cellular/include/service-cellular/api/request/request.hpp => module-services/service-cellular/include/service-cellular/api/request/request.hpp +0 -25
@@ 1,25 0,0 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#pragma once
-
-#include <Service/Message.hpp>
-
-#include <service-cellular/api/common.hpp>
-
-namespace cellular::msg
-{
- struct Request : public sys::Message
- {
- Request() : Message(Type::Data)
- {}
- static constexpr const char *target = cellular::service::name;
- };
- struct Response : public sys::Message
- {
- explicit Response(bool retCode = true) : Message(Type::Data), retCode(retCode)
- {}
- const bool retCode;
- };
-
-} // namespace cellular::msg
M module-services/service-cellular/include/service-cellular/api/request/sim.hpp => module-services/service-cellular/include/service-cellular/api/request/sim.hpp +2 -1
@@ 3,7 3,8 @@
#pragma once
-#include "request.hpp"
+#include <service-cellular/api/common.hpp>
+#include <service-cellular/api/message.hpp>
namespace cellular::msg::request::sim
{
M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +6 -0
@@ 138,6 138,7 @@ class ServiceCellular : public sys::Service
std::vector<std::string> messageParts;
CellularCall::CellularCall ongoingCall;
+ std::vector<CalllogRecord> tetheringCalllog;
ussd::State ussdState = ussd::State::none;
@@ 316,6 317,11 @@ class ServiceCellular : public sys::Service
auto isIncommingCallAllowed() -> bool;
auto hangUpCall() -> bool;
+ auto hangUpCallBusy() -> bool;
+
+ auto tetheringTurnOffURC() -> bool;
+ auto tetheringTurnOnURC() -> bool;
+ auto logTetheringCalls() -> void;
private:
std::unique_ptr<cellular::internal::ServiceCellularPriv> priv;
M module-services/service-cellular/src/ServiceCellularPriv.cpp => module-services/service-cellular/src/ServiceCellularPriv.cpp +13 -22
@@ 20,32 20,22 @@ namespace cellular::internal
void ServiceCellularPriv::initSimCard()
{
using namespace cellular::msg;
- simCard->onSimReady = [this](bool ready) {
- // SIM causes SIM INIT, only on ready
- if (ready) {
- state->set(State::ST::SimInit);
- }
- owner->bus.sendMulticast(std::make_shared<notification::SimReady>(ready),
- sys::BusChannel::ServiceCellularNotifications);
+ simCard->onSimReady = [this]() {
+ state->set(State::ST::SimInit);
+ owner->bus.sendMulticast<notification::SimReady>();
};
simCard->onNeedPin = [this](unsigned int attempts) {
- owner->bus.sendMulticast(std::make_shared<notification::SimNeedPin>(attempts),
- sys::BusChannel::ServiceCellularNotifications);
+ owner->bus.sendMulticast<notification::SimNeedPin>(attempts);
};
simCard->onNeedPuk = [this](unsigned int attempts) {
- owner->bus.sendMulticast(std::make_shared<notification::SimNeedPuk>(attempts),
- sys::BusChannel::ServiceCellularNotifications);
- };
- simCard->onSimBlocked = [this]() {
- owner->bus.sendMulticast(std::make_shared<notification::SimBlocked>(),
- sys::BusChannel::ServiceCellularNotifications);
+ owner->bus.sendMulticast<notification::SimNeedPuk>(attempts);
};
+ simCard->onSimBlocked = [this]() { owner->bus.sendMulticast<notification::SimBlocked>(); };
simCard->onSimEvent = [this]() {
owner->bus.sendUnicast(std::make_shared<sevm::SIMMessage>(), ::service::name::evt_manager);
};
simCard->onUnhandledCME = [this](unsigned int code) {
- owner->bus.sendMulticast(std::make_shared<notification::UnhandledCME>(code),
- sys::BusChannel::ServiceCellularNotifications);
+ owner->bus.sendMulticast<notification::UnhandledCME>(code);
};
}
@@ 77,11 67,12 @@ namespace cellular::internal
auto msg = static_cast<request::sim::PinUnlock *>(request);
return std::make_shared<request::sim::PinUnlock::Response>(simCard->handlePinUnlock(msg->pin));
});
- owner->connect(typeid(internal::msg::SimStateChanged), [&](sys::Message *request) -> sys::MessagePointer {
- auto msg = static_cast<internal::msg::SimStateChanged *>(request);
- simCard->handleSimStateChanged(msg->state);
- return sys::MessageNone{};
- });
+ owner->connect(typeid(internal::msg::HandleATSimStateChange),
+ [&](sys::Message *request) -> sys::MessagePointer {
+ auto msg = static_cast<internal::msg::HandleATSimStateChange *>(request);
+ simCard->handleATSimStateChange(msg->state);
+ return sys::MessageNone{};
+ });
}
} // namespace cellular::internal
M module-services/service-cellular/src/SimCard.cpp => module-services/service-cellular/src/SimCard.cpp +2 -4
@@ 89,7 89,7 @@ namespace cellular
return processPinResult(supplyPin(_pin));
}
- void SimCard::handleSimStateChanged(at::SimState state)
+ void SimCard::handleATSimStateChange(at::SimState state)
{
handleSimState(state);
}
@@ 100,12 100,10 @@ namespace cellular
case at::SimState::Ready:
Store::GSM::get()->sim = Store::GSM::get()->selected;
if (onSimReady)
- onSimReady(true);
+ onSimReady();
break;
case at::SimState::NotReady:
Store::GSM::get()->sim = Store::GSM::SIM::SIM_FAIL;
- if (onSimReady)
- onSimReady(false);
break;
case at::SimState::SimPin:
[[fallthrough]];
M module-services/service-cellular/src/SimCard.hpp => module-services/service-cellular/src/SimCard.hpp +2 -2
@@ 86,12 86,12 @@ namespace cellular::service
/**
* Internal message handlers
*/
- void handleSimStateChanged(at::SimState state);
+ void handleATSimStateChange(at::SimState state);
/**
* Notification events
*/
- std::function<void(bool ready)> onSimReady;
+ std::function<void()> onSimReady;
std::function<void(unsigned int attempts)> onNeedPin;
std::function<void(unsigned int attempts)> onNeedPuk;
std::function<void()> onSimBlocked;
M module-services/service-cellular/src/messages.hpp => module-services/service-cellular/src/messages.hpp +3 -3
@@ 3,14 3,14 @@
#pragma once
-#include <service-cellular/api/request/request.hpp>
+#include <service-cellular/api/message.hpp>
#include <at/SimState.hpp>
namespace cellular::internal::msg
{
- struct SimStateChanged : public cellular::msg::Request
+ struct HandleATSimStateChange : public cellular::msg::Request
{
- SimStateChanged(at::SimState state) : state(state)
+ HandleATSimStateChange(at::SimState state) : state(state)
{}
at::SimState state;
};
M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 19,6 19,7 @@ namespace settings
constexpr inline auto automaticTimeZoneIsOn = "gs_automatic_time_zone_is_on";
constexpr inline auto timeFormat = "gs_time_format";
constexpr inline auto dateFormat = "gs_date_format";
+ constexpr inline auto onboardingDone = "gs_onboarding_done";
constexpr inline auto eulaAccepted = "gs_eula_accepted";
constexpr inline auto osCurrentVersion = "gs_os_current_version";
constexpr inline auto osUpdateVersion = "gs_os_update_version";
M module-services/service-desktop/CMakeLists.txt => module-services/service-desktop/CMakeLists.txt +1 -0
@@ 60,6 60,7 @@ target_link_libraries(${PROJECT_NAME}
module-cellular
crc32
microtar
+ utils-bootconfig
)
if (${ENABLE_TESTS})
M module-services/service-desktop/ServiceDesktop.cpp => module-services/service-desktop/ServiceDesktop.cpp +5 -3
@@ 22,8 22,6 @@
#include <module-sys/SystemManager/SystemManager.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
-#include <cinttypes>
-#include <filesystem>
#include <module-services/service-appmgr/service-appmgr/model/ApplicationManager.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>
#include <module-sys/SystemManager/Constants.hpp>
@@ 34,6 32,10 @@
#include <sys/mount.h>
#include <sys/statvfs.h>
+#include <ctime>
+#include <cinttypes>
+#include <filesystem>
+
namespace
{
bool RemountFS(bool readOnly = false, std::string path = std::string(purefs::dir::getRootDiskPath()))
@@ 348,7 350,7 @@ void ServiceDesktop::storeHistory(const std::string &historyValue)
void ServiceDesktop::prepareBackupData()
{
backupRestoreStatus.operation = ServiceDesktop::Operation::Backup;
- backupRestoreStatus.task = std::to_string(static_cast<uint32_t>(utils::time::getCurrentTimestamp().getTime()));
+ backupRestoreStatus.task = std::to_string(static_cast<uint32_t>(std::time(nullptr)));
backupRestoreStatus.state = OperationState::Stopped;
backupRestoreStatus.backupTempDir = purefs::dir::getTemporaryPath() / backupRestoreStatus.task;
}
M module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp => module-services/service-desktop/endpoints/developerMode/DeveloperModeHelper.cpp +3 -2
@@ 21,11 21,12 @@
#include <module-sys/SystemManager/Constants.hpp>
#include <service-db/DBServiceAPI.hpp>
-#include <time/time_conversion.hpp>
#include <service-desktop/parser/MessageHandler.hpp>
#include <service-desktop/endpoints/developerMode/event/ATRequest.hpp>
#include <service-appmgr/service-appmgr/Controller.hpp>
+#include <ctime>
+
namespace parserFSM
{
class Context;
@@ 283,7 284,7 @@ auto DeveloperModeHelper::smsRecordFromJson(json11::Json msgJson) -> SMSRecord
record.type = static_cast<SMSType>(msgJson[json::messages::messageType].int_value());
utils::PhoneNumber phoneNumber(msgJson[json::messages::phoneNumber].string_value());
record.number = phoneNumber.getView();
- record.date = utils::time::getCurrentTimestamp().getTime();
+ record.date = std::time(nullptr);
record.body = UTF8(msgJson[json::messages::messageBody].string_value());
return record;
}
M module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp => module-services/service-desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp +3 -2
@@ 9,7 9,6 @@
#include <common_data/EventStore.hpp>
#include <json/json11.hpp>
#include <source/version.hpp>
-#include <time/time_conversion.hpp>
#include <service-desktop/service-desktop/ServiceDesktop.hpp>
#include <version.hpp>
@@ 18,6 17,8 @@
#include <sys/statvfs.h>
#include <purefs/filesystem_paths.hpp>
+#include <ctime>
+
using namespace parserFSM;
auto DeviceInfoEndpoint::handle(Context &context) -> void
@@ 61,7 62,7 @@ auto DeviceInfoEndpoint::getDeviceInfo(Context &context) -> bool
{json::gitTag, (std::string)GIT_TAG},
{json::gitBranch, (std::string)GIT_BRANCH},
{json::updateHistory, updateHistory},
- {json::currentRTCTime, std::to_string(static_cast<uint32_t>(utils::time::getCurrentTimestamp().getTime()))},
+ {json::currentRTCTime, std::to_string(static_cast<uint32_t>(std::time(nullptr)))},
{json::version, std::string(VERSION)}}));
MessageHandler::putToSendQueue(context.createSimpleResponse());
M module-services/service-desktop/endpoints/messages/MessageHelper.cpp => module-services/service-desktop/endpoints/messages/MessageHelper.cpp +1 -2
@@ 41,8 41,7 @@ namespace parserFSM
{
auto recordEntry = json11::Json::object{{json::messages::contactID, static_cast<int>(record.contactID)},
- {json::messages::receivedAt, static_cast<int>(record.date)},
- {json::messages::sentAt, static_cast<int>(record.dateSent)},
+ {json::messages::createdAt, static_cast<int>(record.date)},
{json::messages::messageID, static_cast<int>(record.ID)},
{json::messages::messageBody, record.body.c_str()},
{json::messages::messageType, static_cast<int>(record.type)},
M module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp => module-services/service-desktop/endpoints/update/UpdateMuditaOS.cpp +4 -4
@@ 11,7 11,6 @@
#include <application-desktop/Constants.hpp>
#include <service-db/service-db/Settings.hpp>
#include <purefs/filesystem_paths.hpp>
-#include <time/time_conversion.hpp>
#include <filesystem>
#include <Utils.hpp>
#include <boot/bootconfig.hpp>
@@ 26,8 25,9 @@
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
-#include <memory>
+#include <ctime>
#include <fstream>
+#include <memory>
FileInfo::FileInfo(mtar_header_t &h, unsigned long crc32) : fileSize(h.size), fileCRC32(crc32)
{
@@ 93,7 93,7 @@ updateos::UpdateError UpdateMuditaOS::runUpdate()
{
informDebug("Preparing temp dir");
- updateRunStatus.startTime = utils::time::getCurrentTimestamp().getTime();
+ updateRunStatus.startTime = static_cast<uint32_t>(std::time(nullptr));
updateRunStatus.fromVersion = bootConfig.to_json()[boot::json::git_info];
versionInformation = UpdateMuditaOS::getVersionInfoFromFile(updateFile);
@@ 166,7 166,7 @@ updateos::UpdateError UpdateMuditaOS::runUpdate()
informError(err, "runUpdate cleanupAfterUpdate failed, resetting anyway");
}
- updateRunStatus.endTime = utils::time::Time().getTime();
+ updateRunStatus.endTime = static_cast<uint32_t>(std::time(nullptr));
storeRunStatusInDB();
// reboot always
M module-services/service-desktop/parser/ParserUtils.hpp => module-services/service-desktop/parser/ParserUtils.hpp +1 -2
@@ 155,8 155,7 @@ namespace parserFSM
inline constexpr auto messageID = "messageID";
inline constexpr auto messageType = "messageType";
inline constexpr auto phoneNumber = "phoneNumber";
- inline constexpr auto receivedAt = "receivedAt";
- inline constexpr auto sentAt = "sentAt";
+ inline constexpr auto createdAt = "createdAt";
inline constexpr auto lastUsedAt = "lastUsedAt";
inline constexpr auto lastUpdatedAt = "lastUpdatedAt";
inline constexpr auto isUnread = "isUnread";
M module-services/service-desktop/tests/unittest.cpp => module-services/service-desktop/tests/unittest.cpp +1 -3
@@ 187,7 187,6 @@ TEST_CASE("DB Helpers test - json encoding (messages)")
message->body = "test message";
message->contactID = 1;
message->date = 12345;
- message->dateSent = 54321;
message->errorCode = 0;
message->number = contactNum.number;
message->threadID = 1;
@@ 198,8 197,7 @@ TEST_CASE("DB Helpers test - json encoding (messages)")
REQUIRE(messageJson[json::messages::messageBody] == "test message");
REQUIRE(messageJson[json::messages::contactID] == 1);
- REQUIRE(messageJson[json::messages::receivedAt] == 12345);
- REQUIRE(messageJson[json::messages::sentAt] == 54321);
+ REQUIRE(messageJson[json::messages::createdAt] == 12345);
REQUIRE(messageJson[json::messages::threadID] == 1);
REQUIRE(messageJson[json::messages::messageID] == 10);
M module-services/service-evtmgr/CMakeLists.txt => module-services/service-evtmgr/CMakeLists.txt +1 -0
@@ 7,6 7,7 @@ set(SOURCES
api/EventManagerServiceAPI.cpp
battery-level-check/BatteryLevelCheck.cpp
backlight-handler/BacklightHandler.cpp
+ battery-brownout-detector/BatteryBrownoutDetector.cpp
screen-light-control/ControlFunctions.cpp
screen-light-control/ScreenLightControl.cpp
vibra/Vibra.cpp
M module-services/service-evtmgr/EventManager.cpp => module-services/service-evtmgr/EventManager.cpp +35 -19
@@ 222,30 222,28 @@ sys::ReturnCodes EventManager::InitHandler()
connect(typeid(sevm::ScreenLightControlMessage), [&](sys::Message *msgl) {
auto *m = dynamic_cast<sevm::ScreenLightControlMessage *>(msgl);
- backlightHandler.processScreenRequest(m->action);
+ backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters());
return sys::msgHandled();
});
- connect(typeid(sevm::ScreenLightSetParameters), [&](sys::Message *msgl) {
- auto *m = dynamic_cast<sevm::ScreenLightSetParameters *>(msgl);
- backlightHandler.processScreenRequest(m->action, std::move(m->parameters));
+ connect(typeid(sevm::ScreenLightSetAutoModeParams), [&](sys::Message *msgl) {
+ auto *m = static_cast<sevm::ScreenLightSetAutoModeParams *>(msgl);
+ backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters(m->getParams()));
+ return sys::msgHandled();
+ });
+
+ connect(typeid(sevm::ScreenLightSetManualModeParams), [&](sys::Message *msgl) {
+ auto *m = static_cast<sevm::ScreenLightSetManualModeParams *>(msgl);
+ backlightHandler.processScreenRequest(m->getAction(), screen_light_control::Parameters(m->getParams()));
return sys::msgHandled();
});
connect(sevm::ScreenLightControlRequestParameters(), [&](sys::Message *msgl) {
- screen_light_control::Parameters params = {backlightHandler.getScreenBrightnessValue()};
- auto msg = std::make_shared<sevm::ScreenLightControlParametersResponse>(
+ screen_light_control::ManualModeParameters params = {backlightHandler.getScreenBrightnessValue()};
+ auto msg = std::make_shared<sevm::ScreenLightControlParametersResponse>(
backlightHandler.getScreenLightState(), backlightHandler.getScreenAutoModeState(), params);
return msg;
});
- connect(sevm::RtcUpdateTimeMessage(0), [&](sys::Message *msgl) {
- auto msg = static_cast<sevm::RtcUpdateTimeMessage *>(msgl);
- bsp::rtc::setDateTimeFromTimestamp(msg->getTime());
- bsp::rtc::setMinuteAlarm(msg->getTime());
- handleMinuteUpdate(msg->getTime());
- return sys::msgHandled();
- });
-
connect(sevm::BatteryStatusChangeMessage(), [&](sys::Message *msgl) {
if (msgl->sender == this->GetName()) {
LOG_INFO("Battery level: %d , charging: %d",
@@ 284,9 282,15 @@ sys::ReturnCodes EventManager::InitHandler()
return sys::MessageNone{};
});
- connect(typeid(stm::message::UpdateRTCValueMessage), [&](sys::Message *msg) {
- auto message = static_cast<stm::message::UpdateRTCValueMessage *>(msg);
- processRTCRequest(message->getTime());
+ connect(typeid(stm::message::UpdateRTCValueFromTmMessage), [&](sys::Message *msg) {
+ auto message = static_cast<stm::message::UpdateRTCValueFromTmMessage *>(msg);
+ processRTCFromTmRequest(message->getTime());
+ return sys::MessageNone{};
+ });
+
+ connect(typeid(stm::message::UpdateRTCValueFromTimestampMessage), [&](sys::Message *msg) {
+ auto message = static_cast<stm::message::UpdateRTCValueFromTimestampMessage *>(msg);
+ processRTCFromTimestampRequest(message->getTime());
return sys::MessageNone{};
});
@@ 412,7 416,7 @@ void EventManager::toggleTorchColor()
}
}
-void EventManager::processRTCRequest(struct tm &newTime)
+void EventManager::processRTCFromTmRequest(struct tm &newTime)
{
if (bsp::rtc::setDateTime(&newTime) != bsp::rtc::ErrorCode::OK) {
LOG_ERROR("Setting RTC failed.");
@@ 423,6 427,18 @@ void EventManager::processRTCRequest(struct tm &newTime)
auto notification = std::make_shared<sys::DataMessage>(MessageType::EVMTimeUpdated);
bus.sendMulticast(std::move(notification), sys::BusChannel::ServiceEvtmgrNotifications);
}
+
+void EventManager::processRTCFromTimestampRequest(time_t &newTime)
+{
+ if (bsp::rtc::setDateTimeFromTimestamp(newTime) != bsp::rtc::ErrorCode::OK) {
+ LOG_ERROR("Setting RTC failed.");
+ return;
+ }
+ bsp::rtc::setMinuteAlarm(newTime);
+ auto notification = std::make_shared<sys::DataMessage>(MessageType::EVMTimeUpdated);
+ bus.sendMulticast(std::move(notification), sys::BusChannel::ServiceEvtmgrNotifications);
+}
+
void EventManager::processTimezoneRequest(const std::string &timezone)
{
if (setenv("TZ", timezone.c_str(), 1) != 0) {
@@ 431,4 447,4 @@ void EventManager::processTimezoneRequest(const std::string &timezone)
}
auto notification = std::make_shared<sys::DataMessage>(MessageType::EVMTimeUpdated);
bus.sendMulticast(std::move(notification), sys::BusChannel::ServiceEvtmgrNotifications);
-}>
\ No newline at end of file
+}
M module-services/service-evtmgr/WorkerEvent.cpp => module-services/service-evtmgr/WorkerEvent.cpp +61 -36
@@ 45,6 45,18 @@ extern "C"
#include <string> // for string
#include <vector> // for vector
+WorkerEvent::WorkerEvent(sys::Service *service)
+ : sys::Worker(service, stackDepthBytes), service(service),
+ batteryBrownoutDetector(
+ service,
+ []() { return bsp::battery_charger::getVoltageFilteredMeasurement(); },
+ [service]() {
+ auto messageBrownout = std::make_shared<sevm::BatteryBrownoutMessage>();
+ service->bus.sendUnicast(std::move(messageBrownout), service::name::system_manager);
+ },
+ [this]() { checkBatteryChargerInterrupts(); })
+{}
+
bool WorkerEvent::handleMessage(uint32_t queueID)
{
@@ 98,41 110,7 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
return false;
}
if (notification == static_cast<std::uint8_t>(bsp::battery_charger::batteryIRQSource::INTB)) {
- auto topINT = bsp::battery_charger::getTopControllerINTSource();
- if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::CHGR_INT)) {
- bsp::battery_charger::getChargeStatus();
- bsp::battery_charger::actionIfChargerUnplugged();
- auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
- service->bus.sendUnicast(std::move(message), service::name::evt_manager);
- battery_level_check::checkBatteryLevel();
- bsp::battery_charger::clearAllChargerIRQs();
- }
- if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::FG_INT)) {
- const auto status = bsp::battery_charger::getStatusRegister();
- if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert)) {
- auto messageBrownout = std::make_shared<sevm::BatteryBrownoutMessage>();
- service->bus.sendUnicast(std::move(messageBrownout), service::name::system_manager);
- }
- if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange)) {
- bsp::battery_charger::clearFuelGuageIRQ(
- static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange));
- bsp::battery_charger::getBatteryLevel();
- auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
- service->bus.sendUnicast(std::move(message), service::name::evt_manager);
- battery_level_check::checkBatteryLevel();
- }
- if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) ||
- status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp)) {
- bsp::battery_charger::clearFuelGuageIRQ(
- static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) |
- static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp));
- bsp::battery_charger::checkTemperatureRange();
- bsp::battery_charger::getChargeStatus();
- auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
- service->bus.sendUnicast(std::move(message), service::name::evt_manager);
- battery_level_check::checkBatteryLevel();
- }
- }
+ checkBatteryChargerInterrupts();
}
}
@@ 184,7 162,10 @@ bool WorkerEvent::handleMessage(uint32_t queueID)
if (!queue->Dequeue(¬ification, 0)) {
return false;
}
- processKeyEvent(bsp::KeyEvents::Pressed, bsp::magnetometer::getCurrentSliderPosition());
+
+ bsp::magnetometer::resetCurrentParsedValue();
+ LOG_WARN("Received notify, current value reset!");
+ handleMagnetometerEvent();
}
if (queueID == static_cast<uint32_t>(WorkerEventQueues::queueMagnetometerIRQ)) {
@@ 244,6 225,7 @@ bool WorkerEvent::init(std::list<sys::WorkerQueueInfo> queuesList)
auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
service->bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
+
return true;
}
@@ 327,6 309,49 @@ void WorkerEvent::handleMagnetometerEvent()
}
}
+void WorkerEvent::checkBatteryChargerInterrupts()
+{
+ auto topINT = bsp::battery_charger::getTopControllerINTSource();
+ if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::CHGR_INT)) {
+ bsp::battery_charger::getChargeStatus();
+ bsp::battery_charger::actionIfChargerUnplugged();
+ auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
+ service->bus.sendUnicast(std::move(message), service::name::evt_manager);
+ battery_level_check::checkBatteryLevel();
+ bsp::battery_charger::clearAllChargerIRQs();
+ }
+ if (topINT & static_cast<std::uint8_t>(bsp::battery_charger::topControllerIRQsource::FG_INT)) {
+ const auto status = bsp::battery_charger::getStatusRegister();
+ if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert)) {
+ batteryBrownoutDetector.startDetection();
+ bsp::battery_charger::clearFuelGuageIRQ(
+ static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minVAlert));
+ }
+ if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange)) {
+ bsp::battery_charger::clearFuelGuageIRQ(
+ static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::SOCOnePercentChange));
+ bsp::battery_charger::getBatteryLevel();
+ auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
+ service->bus.sendUnicast(std::move(message), service::name::evt_manager);
+ battery_level_check::checkBatteryLevel();
+ }
+ if (status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) ||
+ status & static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp)) {
+ bsp::battery_charger::clearFuelGuageIRQ(
+ static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::maxTemp) |
+ static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::minTemp));
+ bsp::battery_charger::checkTemperatureRange();
+ bsp::battery_charger::getChargeStatus();
+ auto message = std::make_shared<sevm::BatteryStatusChangeMessage>();
+ service->bus.sendUnicast(std::move(message), service::name::evt_manager);
+ battery_level_check::checkBatteryLevel();
+ }
+ // Clear other unsupported IRQ sources just in case
+ bsp::battery_charger::clearFuelGuageIRQ(
+ static_cast<std::uint16_t>(bsp::battery_charger::batteryINTBSource::all));
+ }
+}
+
bsp::KeyCodes WorkerEvent::headsetKeyToKeyboardKey(uint8_t headsetKeyCode)
{
switch (headsetKeyCode) {
M module-services/service-evtmgr/backlight-handler/BacklightHandler.cpp => module-services/service-evtmgr/backlight-handler/BacklightHandler.cpp +53 -36
@@ 18,18 18,18 @@ namespace backlight
} // namespace timers
Handler::Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
- : settings{settings}, screenLightControl{std::make_unique<screen_light_control::ScreenLightControl>(settings,
- parent)},
+ : settings{std::move(settings)}, screenLightControl{std::make_unique<screen_light_control::ScreenLightControl>(
+ parent)},
keypadLightTimer{
sys::TimerFactory::createSingleShotTimer(parent,
timers::keypadLightTimerName,
timers::keypadLightTimerTimeout,
[this](sys::Timer &) { bsp::keypad_backlight::shutdown(); })},
screenLightTimer{sys::TimerFactory::createSingleShotTimer(
- parent, timers::screenLightTimerName, timers::keypadLightTimerTimeout, [this](sys::Timer &) {
- if (utils::getNumericValue<bool>(getValue(settings::Brightness::state)) &&
- utils::getNumericValue<bool>(getValue(settings::Brightness::autoMode)) &&
- screenLightControl->getLightState()) {
+ parent, timers::screenLightTimerName, timers::keypadLightTimerTimeout, [this](sys::Timer &t) {
+ if (getScreenLightState() &&
+ getScreenAutoModeState() == screen_light_control::ScreenLightMode::Manual &&
+ screenLightControl->isLightOn()) {
screenLightControl->processRequest(screen_light_control::Action::turnOff);
}
})}
@@ 38,21 38,33 @@ namespace backlight
void Handler::init()
{
- screenLightControl->initFromSettings();
+ using namespace screen_light_control;
+ settings->registerValueChange(settings::Brightness::brightnessLevel, [&](const std::string &value) {
+ ManualModeParameters params{utils::getNumericValue<float>(value)};
+ screenLightControl->processRequest(Action::setManualModeBrightness, Parameters(params));
+ });
+
+ settings->registerValueChange(settings::Brightness::autoMode, [&]([[maybe_unused]] const std::string &value) {
+ const auto action = getScreenAutoModeState() == ScreenLightMode::Automatic ? Action::enableAutomaticMode
+ : Action::disableAutomaticMode;
+ screenLightControl->processRequest(action);
+ });
+
+ settings->registerValueChange(settings::Brightness::state, [&]([[maybe_unused]] const std::string &value) {
+ const auto action = getScreenLightState() ? Action::turnOn : Action::turnOff;
+ if (action == Action::turnOn) {
+ screenLightTimer.start();
+ }
+ screenLightControl->processRequest(action);
+ });
}
- void Handler::processScreenRequest(screen_light_control::Action action)
+ void Handler::processScreenRequest(screen_light_control::Action action,
+ const screen_light_control::Parameters ¶ms)
{
if (action == screen_light_control::Action::enableAutomaticMode) {
startScreenLightTimer();
}
- handleScreenLightSettings(action);
- screenLightControl->processRequest(action);
- }
-
- void Handler::processScreenRequest(screen_light_control::ParameterizedAction action,
- screen_light_control::Parameters params)
- {
handleScreenLightSettings(action, params);
screenLightControl->processRequest(action, params);
}
@@ 132,12 144,12 @@ namespace backlight
}
}
- auto Handler::getValue(std::string path) const -> std::string
+ auto Handler::getValue(const std::string &path) const -> std::string
{
return settings->getValue(path);
}
- void Handler::setValue(std::string path, std::string value)
+ void Handler::setValue(const std::string &path, const std::string &value)
{
settings->setValue(path, value);
}
@@ 154,17 166,18 @@ namespace backlight
auto Handler::getScreenLightState() const noexcept -> bool
{
- return screenLightControl->getLightState();
+ return utils::getNumericValue<bool>(getValue(settings::Brightness::state));
}
auto Handler::getScreenAutoModeState() const noexcept -> screen_light_control::ScreenLightMode
{
- return screenLightControl->getAutoModeState();
+ auto mode = utils::getNumericValue<int>(getValue(settings::Brightness::autoMode));
+ return static_cast<screen_light_control::ScreenLightMode>(mode);
}
auto Handler::getScreenBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage
{
- return screenLightControl->getBrightnessValue();
+ return utils::getNumericValue<float>(getValue(settings::Brightness::brightnessLevel));
}
void Handler::handleKeypadLightRefresh()
@@ 177,40 190,44 @@ namespace backlight
void Handler::handleScreenLightRefresh()
{
- if (utils::getNumericValue<bool>(getValue(settings::Brightness::state)) &&
- utils::getNumericValue<bool>(getValue(settings::Brightness::autoMode))) {
-
- if (!screenLightControl->getLightState()) {
+ if (getScreenLightState() && getScreenAutoModeState() == screen_light_control::ScreenLightMode::Manual) {
+ if (!screenLightControl->isLightOn()) {
screenLightControl->processRequest(screen_light_control::Action::turnOn);
}
startScreenLightTimer();
}
}
- void Handler::handleScreenLightSettings(screen_light_control::Action action)
+ void Handler::handleScreenLightSettings(screen_light_control::Action action,
+ const screen_light_control::Parameters ¶ms)
{
switch (action) {
case screen_light_control::Action::enableAutomaticMode:
- setValue(settings::Brightness::autoMode, utils::to_string(true));
+ setValue(settings::Brightness::autoMode,
+ utils::to_string(static_cast<int>(screen_light_control::ScreenLightMode::Automatic)));
break;
case screen_light_control::Action::disableAutomaticMode:
- setValue(settings::Brightness::autoMode, utils::to_string(false));
- screenLightControl->processRequest(screen_light_control::ParameterizedAction::setManualModeBrightness,
- screen_light_control::Parameters{utils::getNumericValue<float>(
- getValue(settings::Brightness::brightnessLevel))});
+ setValue(settings::Brightness::autoMode,
+ utils::to_string(static_cast<int>(screen_light_control::ScreenLightMode::Manual)));
break;
case screen_light_control::Action::turnOff:
setValue(settings::Brightness::state, utils::to_string(false));
break;
case screen_light_control::Action::turnOn:
setValue(settings::Brightness::state, utils::to_string(true));
+ screenLightTimer.start();
+ break;
+ case screen_light_control::Action::setManualModeBrightness:
+ if (params.hasManualModeParams()) {
+ setValue(settings::Brightness::brightnessLevel,
+ utils::to_string(params.getManualModeParams().manualModeBrightness));
+ }
+ else {
+ LOG_ERROR("Missing ManualModeBrightness value, change request ignored");
+ }
+ break;
+ default:
break;
}
}
-
- void Handler::handleScreenLightSettings(screen_light_control::ParameterizedAction action,
- screen_light_control::Parameters params)
- {
- setValue(settings::Brightness::brightnessLevel, utils::to_string(params.manualModeBrightness));
- }
} // namespace backlight
M module-services/service-evtmgr/backlight-handler/BacklightHandler.hpp => module-services/service-evtmgr/backlight-handler/BacklightHandler.hpp +8 -24
@@ 15,38 15,23 @@ namespace settings
namespace backlight
{
- class SettingsInterface
- {
- public:
- virtual ~SettingsInterface() = default;
-
- protected:
- virtual auto getValue(std::string path) const -> std::string = 0;
- virtual void setValue(std::string path, std::string value) = 0;
- };
-
/// @brief Backlight events handler
- class Handler : public SettingsInterface
+ class Handler
{
public:
Handler(std::shared_ptr<settings::Settings> settings, sys::Service *parent);
- /// initiaise in InitHandler when Service is ready
+ /// initialise in InitHandler when Service is ready
void init();
/// Process request of the screen light control
/// @screen_light_control::Action an action to perform
- void processScreenRequest(screen_light_control::Action action);
-
- /// Process request of the screen light control with specified parameters
- /// @screen_light_control::ParameterizedAction an action to perform
/// @screen_light_control::Parameters parameters being set
- void processScreenRequest(screen_light_control::ParameterizedAction action,
- screen_light_control::Parameters params);
+ void processScreenRequest(screen_light_control::Action action, const screen_light_control::Parameters ¶ms);
void handleKeyPressed();
/// Process request of the keypad light control
- /// @screen_light_control::ParameterizedAction an action to perform
+ /// @keypad_backlight::action an action to perform
/// @return True if request was processed successfully, false otherwise
auto processKeypadRequest(bsp::keypad_backlight::Action action) -> bool;
@@ 55,8 40,8 @@ namespace backlight
[[nodiscard]] auto getScreenBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage;
protected:
- [[nodiscard]] auto getValue(std::string path) const -> std::string override;
- void setValue(std::string path, std::string value) override;
+ [[nodiscard]] auto getValue(const std::string &path) const -> std::string;
+ void setValue(const std::string &path, const std::string &value);
private:
std::shared_ptr<settings::Settings> settings;
@@ 76,8 61,7 @@ namespace backlight
void restoreKeypadLightState();
void handleKeypadLightRefresh();
void handleScreenLightRefresh();
- void handleScreenLightSettings(screen_light_control::Action action);
- void handleScreenLightSettings(screen_light_control::ParameterizedAction action,
- screen_light_control::Parameters params);
+ void handleScreenLightSettings(screen_light_control::Action action,
+ const screen_light_control::Parameters ¶ms);
};
} // namespace backlight
A module-services/service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.cpp => module-services/service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.cpp +54 -0
@@ 0,0 1,54 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "BatteryBrownoutDetector.hpp"
+#include <Timers/TimerFactory.hpp>
+
+namespace
+{
+ constexpr std::chrono::milliseconds measurementTickTime{1000};
+ constexpr auto measurementTickName = "BrtownoutDetectorTick";
+ constexpr unsigned measurementMaxCount = 5;
+ constexpr auto brownoutLevelVoltage = 3600; // mV
+} // namespace
+
+BatteryBrownoutDetector::BatteryBrownoutDetector(sys::Service *service,
+ std::function<int()> getMeasurementCallback,
+ std::function<void()> positiveResultCallback,
+ std::function<void()> negativeResultCallback)
+ : parentService(service), getMeasurementCallback(std::move(getMeasurementCallback)),
+ positiveResultCallback(std::move(positiveResultCallback)),
+ negativeResultCallback(std::move(negativeResultCallback)), detectionOngoing{false}, measurementCount{0},
+ measurementTick{sys::TimerFactory::createSingleShotTimer(
+ service, measurementTickName, measurementTickTime, [this](sys::Timer &) { checkBrownout(); })}
+{}
+
+void BatteryBrownoutDetector::startDetection()
+{
+ if (detectionOngoing) {
+ return;
+ }
+ LOG_DEBUG("Battery Brownout detection window start");
+ detectionOngoing = true;
+ measurementCount = 0;
+ checkBrownout();
+}
+
+void BatteryBrownoutDetector::checkBrownout()
+{
+ if (getMeasurementCallback() < brownoutLevelVoltage) {
+ LOG_DEBUG("Battery Brownout detected");
+ positiveResultCallback();
+ return;
+ }
+
+ measurementCount++;
+ if (measurementCount <= measurementMaxCount) {
+ measurementTick.start();
+ }
+ else {
+ LOG_DEBUG("Battery Brownout detection window finish with negative result");
+ detectionOngoing = false;
+ negativeResultCallback();
+ }
+}
A module-services/service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.hpp => module-services/service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.hpp +33 -0
@@ 0,0 1,33 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Service/Service.hpp>
+#include <Timers/TimerHandle.hpp>
+
+namespace sys
+{
+ class Service;
+} // namespace sys
+
+class BatteryBrownoutDetector
+{
+ public:
+ BatteryBrownoutDetector(sys::Service *service,
+ std::function<int()> getMeasurementCallback,
+ std::function<void()> positiveResultCallback,
+ std::function<void()> negativeResultCallback);
+ void startDetection();
+
+ private:
+ void checkBrownout();
+
+ sys::Service *parentService;
+ const std::function<int()> getMeasurementCallback;
+ const std::function<void()> positiveResultCallback;
+ const std::function<void()> negativeResultCallback;
+ bool detectionOngoing;
+ unsigned measurementCount;
+ sys::TimerHandle measurementTick;
+};
M module-services/service-evtmgr/doc/battery_charging.md => module-services/service-evtmgr/doc/battery_charging.md +5 -1
@@ 48,4 48,8 @@ Implementation is interrupt-driven. In interrupt handler temperature measurement

-Additional 2 Cdeg hysteresis was introduced to prevent rapid changes in charging states.>
\ No newline at end of file
+Additional 2 Cdeg hysteresis was introduced to prevent rapid changes in charging states.
+
+## Battery Brownout Detection
+
+Battery charger chip is capable of providing interrupt when low voltage threshold is violated. This voltage value is instantaneous measurement. To prevent spurious brownout events, additional algorithm was introduced. This kind of false detection could occur when phone call is stared and GSM module consumes high current what results in narrow voltage dip. Interrupt from battery charger creates a time window of 5 seconds and every second filtered value of voltage is sampled. If any of those samples drop below given 3.6V threshold, the brownout event is fired.
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.cpp +26 -48
@@ 2,19 2,13 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "ScreenLightControl.hpp"
-
-#include <agents/settings/SystemSettings.hpp>
#include <module-sys/Timers/TimerFactory.hpp>
-#include <Service/Message.hpp>
#include <Service/Service.hpp>
-#include <service-db/service-db/Settings.hpp>
-#include <Utils.hpp>
namespace screen_light_control
{
- ScreenLightControl::ScreenLightControl(std::shared_ptr<settings::Settings> settings, sys::Service *parent)
- : settings(settings)
+ ScreenLightControl::ScreenLightControl(sys::Service *parent)
{
controlTimer = sys::TimerFactory::createPeriodicTimer(parent,
"LightControlTimer",
@@ 24,6 18,8 @@ namespace screen_light_control
"LightSensorReadoutTimer",
std::chrono::milliseconds{READOUT_TIMER_MS},
[this](sys::Timer &) { readoutTimerCallback(); });
+
+ setParameters(screen_light_control::AutomaticModeParameters());
}
ScreenLightControl::~ScreenLightControl()
@@ 31,32 27,11 @@ namespace screen_light_control
disableTimers();
}
- void ScreenLightControl::initFromSettings()
+ void ScreenLightControl::processRequest(Action action)
{
- settings->registerValueChange(settings::Brightness::brightnessLevel, [&](const std::string &value) {
- setBrightnessLevel(utils::getNumericValue<float>(value));
- });
-
- settings->registerValueChange(settings::Brightness::autoMode, [&](const std::string &value) {
- if (utils::getNumericValue<bool>(value)) {
- enableAutomaticMode();
- }
- else {
- disableAutomaticMode();
- }
- });
-
- settings->registerValueChange(settings::Brightness::state, [&](const std::string &value) {
- if (utils::getNumericValue<bool>(value)) {
- turnOn();
- }
- else {
- turnOff();
- }
- });
+ processRequest(action, Parameters());
}
-
- void ScreenLightControl::processRequest(Action action)
+ void ScreenLightControl::processRequest(Action action, const Parameters ¶ms)
{
switch (action) {
case Action::turnOff:
@@ 71,17 46,15 @@ namespace screen_light_control
case Action::disableAutomaticMode:
disableAutomaticMode();
break;
- }
- }
-
- void ScreenLightControl::processRequest(ParameterizedAction action, Parameters params)
- {
- switch (action) {
- case ParameterizedAction::setManualModeBrightness:
- setBrightnessLevel(params.manualModeBrightness);
+ case Action::setManualModeBrightness:
+ if (params.hasManualModeParams()) {
+ setParameters(params.getManualModeParams());
+ }
break;
- case ParameterizedAction::setAutomaticModeParameters:
- setAutomaticModeParameters(params);
+ case Action::setAutomaticModeParameters:
+ if (params.hasAutoModeParams()) {
+ setParameters(params.getAutoModeParams());
+ }
break;
}
}
@@ 101,7 74,7 @@ namespace screen_light_control
return automaticMode;
}
- auto ScreenLightControl::getLightState() const noexcept -> bool
+ auto ScreenLightControl::isLightOn() const noexcept -> bool
{
return lightOn;
}
@@ 123,7 96,7 @@ namespace screen_light_control
readoutTimer.stop();
}
- void ScreenLightControl::setAutomaticModeParameters(const Parameters ¶ms)
+ void ScreenLightControl::setParameters(const AutomaticModeParameters ¶ms)
{
if (lightOn && automaticMode == ScreenLightMode::Automatic) {
disableTimers();
@@ 138,6 111,12 @@ namespace screen_light_control
}
}
+ void ScreenLightControl::setParameters(ManualModeParameters params)
+ {
+ brightnessValue = params.manualModeBrightness;
+ setManualBrightnessLevel();
+ }
+
void ScreenLightControl::enableAutomaticMode()
{
if (lightOn) {
@@ 150,6 129,7 @@ namespace screen_light_control
{
disableTimers();
automaticMode = ScreenLightMode::Manual;
+ setManualBrightnessLevel();
}
void ScreenLightControl::turnOn()
@@ 162,18 142,16 @@ namespace screen_light_control
lightOn = true;
}
- void ScreenLightControl::setBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightnessPercentage)
+ void ScreenLightControl::setManualBrightnessLevel()
{
- bsp::eink_frontlight::setBrightness(brightnessPercentage);
- brightnessValue = brightnessPercentage;
+ bsp::eink_frontlight::setBrightness(brightnessValue);
}
void ScreenLightControl::turnOff()
{
bsp::eink_frontlight::turnOff();
bsp::light_sensor::standby();
- controlTimer.stop();
- readoutTimer.stop();
+ disableTimers();
lightOn = false;
}
} // namespace screen_light_control
M module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp +7 -51
@@ 3,10 3,9 @@
#pragma once
-#include "ControlFunctions.hpp"
+#include "ScreenLightControlParameters.hpp"
#include <memory>
#include <module-sys/Timers/TimerHandle.hpp>
-
namespace settings
{
class Settings;
@@ 21,62 20,20 @@ namespace sys
/// Processing of ambient light sensor input to screen brightness output.
namespace screen_light_control
{
- /// Modes in which front light can operate
- enum ScreenLightMode
- {
- Automatic, /// Automally sets screen brightness based on sensor data
- Manual /// Manually set brightness level
- };
-
- /// Set of actions to control the screen light
- enum class Action
- {
- turnOff, ///< Turn off screen frontlight
- turnOn, ///< Turn on screen frontlight
- enableAutomaticMode, ///< Enable automatic mode of screen frontlight
- disableAutomaticMode ///< Disable automatic mode of screen frontlight
- };
-
- /// Set of actions to control the screen light using specified parameters
- enum class ParameterizedAction
- {
- setManualModeBrightness, ///< Set screen brightness in manual mode control
- setAutomaticModeParameters ///< Set parameters for automatic mode of screen frontlight
- };
-
- struct Parameters
- {
- static constexpr auto MAX_BRIGHTNESS = 100.0;
-
- /// Screen brightness 0-100% in manual mode
- bsp::eink_frontlight::BrightnessPercentage manualModeBrightness = 50.0f;
- /// Vector of points for screen brightness [%] in relation to ambient light [Lux] function. Points have to be in
- /// ascending order of ambient light values.
- functions::BrightnessFunction functionPoints = functions::BrightnessFunction({{0.0f, 50.0f}});
- /// Ramp time of screen brightness in miliseconds per 0-100% change
- unsigned int rampTimeMS = 1500;
- /// Hysteresis value of screen brightness control
- float brightnessHysteresis = 10.0f;
- /// Gamma factor for screen brightness correction
- float gammaFactor = 2.5f;
- };
-
/// Control screen light and keeps it's current state
class ScreenLightControl
{
public:
- explicit ScreenLightControl(std::shared_ptr<settings::Settings> settings, sys::Service *parent);
+ explicit ScreenLightControl(sys::Service *parent);
~ScreenLightControl();
void processRequest(Action action);
- void processRequest(ParameterizedAction action, Parameters params);
+ void processRequest(Action action, const Parameters ¶ms);
- [[nodiscard]] auto getLightState() const noexcept -> bool;
+ [[nodiscard]] auto isLightOn() const noexcept -> bool;
[[nodiscard]] auto getAutoModeState() const noexcept -> ScreenLightMode;
[[nodiscard]] auto getBrightnessValue() const noexcept -> bsp::eink_frontlight::BrightnessPercentage;
- void initFromSettings();
-
private:
void controlTimerCallback();
void readoutTimerCallback();
@@ 84,8 41,9 @@ namespace screen_light_control
void enableTimers();
void disableTimers();
- void setAutomaticModeParameters(const Parameters ¶ms);
- void setBrightnessLevel(bsp::eink_frontlight::BrightnessPercentage brightnessPercentage);
+ void setParameters(const AutomaticModeParameters ¶ms);
+ void setParameters(ManualModeParameters params);
+ void setManualBrightnessLevel();
void turnOff();
void turnOn();
@@ 102,8 60,6 @@ namespace screen_light_control
bool lightOn = false;
screen_light_control::ScreenLightMode automaticMode = ScreenLightMode::Manual;
bsp::eink_frontlight::BrightnessPercentage brightnessValue = 0.0;
-
- std::shared_ptr<settings::Settings> settings;
};
} // namespace screen_light_control
A module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp => module-services/service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp +87 -0
@@ 0,0 1,87 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "ControlFunctions.hpp"
+#include <gsl_assert>
+#include <optional>
+
+namespace screen_light_control
+{
+ /// Modes in which front light can operate
+ enum class ScreenLightMode
+ {
+ Automatic, /// Automatically sets screen brightness based on sensor data
+ Manual /// Manually set brightness level
+ };
+
+ /// Set of actions to control the screen light
+ enum class Action
+ {
+ turnOff, ///< Turn off screen frontlight
+ turnOn, ///< Turn on screen frontlight
+ enableAutomaticMode, ///< Enable automatic mode of screen frontlight
+ disableAutomaticMode, ///< Disable automatic mode of screen frontlight
+ setManualModeBrightness, ///< Set screen brightness in manual mode control
+ setAutomaticModeParameters ///< Set parameters for automatic mode of screen frontlight
+ };
+
+ struct ManualModeParameters
+ {
+ static constexpr auto MAX_BRIGHTNESS = 100.0;
+ /// Screen brightness 0-100% in manual mode
+ bsp::eink_frontlight::BrightnessPercentage manualModeBrightness = 50.0f;
+ };
+
+ struct AutomaticModeParameters
+ {
+ /// Vector of points for screen brightness [%] in relation to ambient light [Lux] function. Points have to be in
+ /// ascending order of ambient light values.
+ functions::BrightnessFunction functionPoints =
+ functions::BrightnessFunction({{0.0f, 70.0f}, {250.0f, 70.0f}, {450.0f, 40.0f}, {500.0f, 0.0f}});
+ /// Ramp time of screen brightness in milliseconds per 0-100% change
+ unsigned int rampTimeMS = 1500;
+ /// Hysteresis value of screen brightness control
+ float brightnessHysteresis = 10.0f;
+ /// Gamma factor for screen brightness correction
+ float gammaFactor = 2.5f;
+ };
+
+ class Parameters
+ {
+ std::optional<ManualModeParameters> manualModeParams;
+ std::optional<AutomaticModeParameters> autoModeParams;
+
+ public:
+ Parameters() = default;
+ explicit Parameters(ManualModeParameters manualModeParams)
+ : manualModeParams{std::make_optional(manualModeParams)}
+ {}
+ explicit Parameters(const AutomaticModeParameters &autoModeParams)
+ : autoModeParams{std::make_optional(autoModeParams)}
+ {}
+
+ [[nodiscard]] bool hasManualModeParams() const noexcept
+ {
+ return manualModeParams.has_value();
+ }
+
+ [[nodiscard]] auto getManualModeParams() const noexcept -> ManualModeParameters
+ {
+ Expects(hasManualModeParams());
+ return manualModeParams.value();
+ }
+
+ [[nodiscard]] bool hasAutoModeParams() const noexcept
+ {
+ return autoModeParams.has_value();
+ }
+
+ [[nodiscard]] auto getAutoModeParams() const noexcept -> const AutomaticModeParameters &
+ {
+ Expects(hasAutoModeParams());
+ return autoModeParams.value();
+ }
+ };
+} // namespace screen_light_control
M module-services/service-evtmgr/service-evtmgr/EVMessages.hpp => module-services/service-evtmgr/service-evtmgr/EVMessages.hpp +0 -15
@@ 40,27 40,12 @@ namespace sevm
uint32_t timestamp = 0;
};
- class RtcUpdateTimeMessage : public sys::DataMessage
- {
- public:
- explicit RtcUpdateTimeMessage(time_t time) : time(time)
- {}
- [[nodiscard]] time_t getTime() const noexcept
- {
- return time;
- }
-
- private:
- const time_t time = 0;
- };
-
class SIMMessage : public sys::DataMessage
{
public:
SIMMessage() : DataMessage(MessageType::SIMTrayEvent)
{}
};
-
/*
* @brief Template for all messages that go to application manager
*/
M module-services/service-evtmgr/service-evtmgr/EventManager.hpp => module-services/service-evtmgr/service-evtmgr/EventManager.hpp +2 -1
@@ 37,7 37,8 @@ class EventManager : public sys::Service
void toggleTorchOnOff();
void toggleTorchColor();
- void processRTCRequest(struct tm &newTime);
+ void processRTCFromTmRequest(struct tm &newTime);
+ void processRTCFromTimestampRequest(time_t &newTime);
void processTimezoneRequest(const std::string &timezone);
std::shared_ptr<settings::Settings> settings;
M module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp => module-services/service-evtmgr/service-evtmgr/ScreenLightControlMessage.hpp +50 -15
@@ 3,7 3,7 @@
#pragma once
-#include "module-services/service-evtmgr/screen-light-control/ScreenLightControl.hpp"
+#include <service-evtmgr/screen-light-control/ScreenLightControlParameters.hpp>
#include <Service/Message.hpp>
#include <Service/Service.hpp>
@@ 13,23 13,48 @@ namespace sevm
{
class ScreenLightControlMessage : public sys::DataMessage
{
+ const screen_light_control::Action action;
+
public:
explicit ScreenLightControlMessage(screen_light_control::Action act)
: sys::DataMessage(MessageType::ScreenLightControlAction), action(act)
{}
- const screen_light_control::Action action;
+ [[nodiscard]] auto getAction() const noexcept -> screen_light_control::Action
+ {
+ return action;
+ }
+ };
+
+ class ScreenLightSetAutoModeParams : public ScreenLightControlMessage
+ {
+ screen_light_control::AutomaticModeParameters params;
+
+ public:
+ explicit ScreenLightSetAutoModeParams(screen_light_control::AutomaticModeParameters params)
+ : ScreenLightControlMessage(screen_light_control::Action::setAutomaticModeParameters), params{std::move(
+ params)}
+ {}
+
+ [[nodiscard]] auto getParams() const noexcept -> const screen_light_control::AutomaticModeParameters &
+ {
+ return params;
+ }
};
- class ScreenLightSetParameters : public sys::DataMessage
+ class ScreenLightSetManualModeParams : public ScreenLightControlMessage
{
+ screen_light_control::ManualModeParameters params;
+
public:
- ScreenLightSetParameters(screen_light_control::ParameterizedAction act, screen_light_control::Parameters params)
- : sys::DataMessage(MessageType::ScreenLightControlAction), action(act), parameters(std::move(params))
+ explicit ScreenLightSetManualModeParams(screen_light_control::ManualModeParameters params)
+ : ScreenLightControlMessage(screen_light_control::Action::setManualModeBrightness), params{params}
{}
- const screen_light_control::ParameterizedAction action;
- const screen_light_control::Parameters parameters;
+ [[nodiscard]] auto getParams() const noexcept -> screen_light_control::ManualModeParameters
+ {
+ return params;
+ }
};
class ScreenLightControlRequestParameters : public sys::DataMessage
@@ 41,19 66,29 @@ namespace sevm
class ScreenLightControlParametersResponse : public sys::DataMessage
{
- public:
- ScreenLightControlParametersResponse() : sys::DataMessage(MessageType::ScreenLightControlParametersResponse)
- {}
+ bool lightOn;
+ screen_light_control::ScreenLightMode mode;
+ screen_light_control::ManualModeParameters parameters;
+ public:
ScreenLightControlParametersResponse(bool lightOn,
screen_light_control::ScreenLightMode mode,
- screen_light_control::Parameters params)
+ screen_light_control::ManualModeParameters params)
: sys::DataMessage(MessageType::ScreenLightControlParametersResponse), lightOn(lightOn), mode(mode),
- parameters(std::move(params))
+ parameters(params)
{}
- bool lightOn;
- screen_light_control::ScreenLightMode mode;
- screen_light_control::Parameters parameters;
+ [[nodiscard]] bool isLightOn() const noexcept
+ {
+ return lightOn;
+ }
+ [[nodiscard]] auto getMode() const noexcept -> screen_light_control::ScreenLightMode
+ {
+ return mode;
+ }
+ [[nodiscard]] auto getParams() const noexcept -> screen_light_control::ManualModeParameters
+ {
+ return parameters;
+ }
};
} // namespace sevm
M module-services/service-evtmgr/service-evtmgr/WorkerEvent.hpp => module-services/service-evtmgr/service-evtmgr/WorkerEvent.hpp +4 -1
@@ 12,6 12,7 @@
#include <bsp/keyboard/key_codes.hpp>
#include <bsp/keyboard/key_codes.hpp>
#include <Service/CpuSentinel.hpp>
+#include <module-services/service-evtmgr/battery-brownout-detector/BatteryBrownoutDetector.hpp>
#include <cstdint>
#include <list>
@@ 73,9 74,10 @@ class WorkerEvent : public sys::Worker
bsp::KeyCodes lastPressed = static_cast<bsp::KeyCodes>(0);
sys::Service *service = nullptr;
std::shared_ptr<sys::CpuSentinel> cpuSentinel;
+ BatteryBrownoutDetector batteryBrownoutDetector;
public:
- WorkerEvent(sys::Service *service) : sys::Worker(service, stackDepthBytes), service(service){};
+ WorkerEvent(sys::Service *service);
/**
* This function is responsible for creating all queues provided in the constructor.
* When all queues are created this method creates set of queues.
@@ 92,4 94,5 @@ class WorkerEvent : public sys::Worker
bool handleMessage(uint32_t queueID) override final;
void requestSliderPositionRead();
void handleMagnetometerEvent();
+ void checkBatteryChargerInterrupts();
};
M module-services/service-fileindexer/CMakeLists.txt => module-services/service-fileindexer/CMakeLists.txt +0 -3
@@ 5,8 5,6 @@ project(service-fileindexer VERSION 1.0
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})
-target_include_directories( ${PROJECT_NAME} PRIVATE ${TAGLIB_INCLUDE_DIRS} )
-
# Board specific compilation definitions,options,include directories and features
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_CONFIG_DEFINITIONS})
target_compile_definitions(${PROJECT_NAME} PUBLIC ${PROJECT_TARGET})
@@ 20,7 18,6 @@ target_link_options(${PROJECT_NAME} PUBLIC ${TARGET_LINK_OPTIONS})
target_sources( ${PROJECT_NAME}
PRIVATE
"ServiceFileIndexer.cpp"
- "messages/FileChangeMessage.cpp"
"StartupIndexer.cpp"
"notesIndexer.cpp"
)
M module-services/service-fileindexer/ServiceFileIndexer.cpp => module-services/service-fileindexer/ServiceFileIndexer.cpp +40 -14
@@ 1,13 1,23 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <log/log.hpp>
+#include <purefs/filesystem_paths.hpp>
+#include <purefs/fs/inotify.hpp>
#include "ServiceFileIndexer.hpp"
-#include "notesIndexer.hpp"
-#include "messages/FileChangeMessage.hpp"
-#include "Constants.hpp"
#include <fileref.h>
#include <tag.h>
+#include "notesIndexer.hpp"
+#include "Constants.hpp"
+#include <purefs/fs/inotify_message.hpp>
+
+namespace
+{
+ inline auto getMusicPath()
+ {
+ return purefs::createPath(purefs::dir::getUserDiskPath(), "music").string();
+ }
+} // namespace
namespace service
{
@@ 20,6 30,15 @@ namespace service
// When receive notification handler
sys::MessagePointer ServiceFileIndexer::DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp)
{
+ auto inotify = dynamic_cast<purefs::fs::message::inotify *>(msg);
+ if (inotify) {
+ LOG_ERROR("Inotify event %s %08x", inotify->name.c_str(), int(inotify->flags));
+ }
+ else {
+ LOG_ERROR("Not a inotify message");
+ }
+
+#if 0
auto fcm = dynamic_cast<msg::FileChangeMessage *>(msg);
if (fcm) {
switch (fcm->event()) {
@@ 47,6 66,7 @@ namespace service
}
return std::make_shared<sys::ResponseMessage>();
}
+#endif
return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Unresolved);
}
@@ 54,23 74,29 @@ namespace service
sys::ReturnCodes ServiceFileIndexer::InitHandler()
{
/*
- vfs.registerNotificationHandler(
- [_this = shared_from_this()](std::string_view new_path, vfs::FsEvent event, std::string_view old_path) {
- namespace fs = std::filesystem;
- const auto new_ext = fs::path(new_path).extension().string();
- auto msg = std::make_shared<msg::FileChangeMessage>(new_path, event, old_path);
- _this->bus.sendUnicast(msg, std::string(service::name::file_indexer));
- });
mStartupIndexer.start(shared_from_this(), service::name::file_indexer);
*/
+
+ mfsNotifier = purefs::fs::inotify_create(shared_from_this());
+ if (!mfsNotifier) {
+ LOG_ERROR("Unable to create inotify object");
+ return sys::ReturnCodes::Failure;
+ }
+ const int err = mfsNotifier->add_watch(getMusicPath(), purefs::fs::inotify_flags::close_write);
+ if (err) {
+ LOG_ERROR("Unable to create inotify watch errno: %i", err);
+ return sys::ReturnCodes::Failure;
+ }
return sys::ReturnCodes::Success;
}
sys::ReturnCodes ServiceFileIndexer::DeinitHandler()
{
- /*
- vfs.registerNotificationHandler(nullptr);
- */
+ const int err = mfsNotifier->rm_watch(getMusicPath());
+ if (err) {
+ LOG_ERROR("Unable to remove watch errno: %i", err);
+ return sys::ReturnCodes::Failure;
+ }
return sys::ReturnCodes::Success;
}
M module-services/service-fileindexer/ServiceFileIndexer.hpp => module-services/service-fileindexer/ServiceFileIndexer.hpp +8 -0
@@ 8,6 8,11 @@
#include "Constants.hpp"
#include "StartupIndexer.hpp"
+namespace purefs::fs
+{
+ class inotify;
+}
+
namespace service
{
@@ 28,6 33,9 @@ namespace service
auto onRenameFile(std::string_view oldPath, std::string_view newPath) -> void;
auto onAudioContentChanged(std::string_view path) -> void;
auto onTextContentChanged(std::string_view path) -> void;
+
+ private:
+ std::shared_ptr<purefs::fs::inotify> mfsNotifier;
detail::StartupIndexer mStartupIndexer;
};
M module-services/service-fileindexer/StartupIndexer.cpp => module-services/service-fileindexer/StartupIndexer.cpp +1 -3
@@ 2,10 2,8 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "StartupIndexer.hpp"
-#include "messages/FileChangeMessage.hpp"
#include <Timers/TimerFactory.hpp>
#include <filesystem>
-//#include <ff_stdio_listdir_recursive.h>
#include <purefs/filesystem_paths.hpp>
#include "Constants.hpp"
@@ 63,7 61,7 @@ namespace service::detail
mIdxTimer = sys::TimerFactory::createPeriodicTimer(
svc.get(), "file_indexing", std::chrono::milliseconds{timer_indexing_time}, [this, svc](sys::Timer &) {
if (!mMsgs.empty()) {
- svc->bus.sendUnicast(mMsgs.front(), std::string(service::name::file_indexer));
+ // svc->bus.sendUnicast(mMsgs.front(), std::string(service::name::file_indexer));
mMsgs.pop_front();
}
else {
D module-services/service-fileindexer/messages/FileChangeMessage.cpp => module-services/service-fileindexer/messages/FileChangeMessage.cpp +0 -11
@@ 1,11 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include "FileChangeMessage.hpp"
-
-namespace service::msg
-{
- FileChangeMessage::FileChangeMessage(std::string_view new_path, evt_t ev, std::string_view old_path)
- : DataMessage(MessageType::FileContentModified), mNewPath(new_path), mEvent(ev), mOldPath(old_path)
- {}
-} // namespace service::msg
D module-services/service-fileindexer/messages/FileChangeMessage.hpp => module-services/service-fileindexer/messages/FileChangeMessage.hpp +0 -36
@@ 1,36 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#pragma once
-
-#include <Service/Message.hpp>
-#include <vfsNotifier.hpp>
-namespace service::msg
-{
- class FileChangeMessage final : public sys::DataMessage
- {
- public:
- using evt_t = vfsn::utility::vfsNotifier::FsEvent;
- FileChangeMessage(std::string_view new_path, evt_t ev, std::string_view old_path);
- virtual ~FileChangeMessage() = default;
- FileChangeMessage(FileChangeMessage &) = delete;
- FileChangeMessage &operator=(FileChangeMessage &) = delete;
- [[nodiscard]] auto newPath() const noexcept
- {
- return mNewPath;
- }
- [[nodiscard]] auto oldPath() const noexcept
- {
- return mOldPath;
- }
- [[nodiscard]] auto event() const noexcept
- {
- return mEvent;
- }
-
- private:
- const std::string mNewPath;
- const evt_t mEvent;
- const std::string mOldPath;
- };
-} // namespace service::msg
M module-services/service-time/RTCcommand.cpp => module-services/service-time/RTCcommand.cpp +7 -1
@@ 8,7 8,13 @@
void RTCCommand::setTime(const struct tm &time)
{
- auto message = std::make_shared<stm::message::UpdateRTCValueMessage>(time);
+ auto message = std::make_shared<stm::message::UpdateRTCValueFromTmMessage>(time);
+ owner->bus.sendUnicast(message, service::name::evt_manager);
+}
+
+void RTCCommand::setTime(const time_t &time)
+{
+ auto message = std::make_shared<stm::message::UpdateRTCValueFromTimestampMessage>(time);
owner->bus.sendUnicast(message, service::name::evt_manager);
}
M module-services/service-time/ServiceTime.cpp => module-services/service-time/ServiceTime.cpp +6 -0
@@ 128,5 128,11 @@ namespace stm
std::chrono::minutes{message->getTimeZoneOffset().value() / utils::time::secondsInMinute});
return std::make_shared<sys::ResponseMessage>();
});
+
+ connect(typeid(stm::message::TimeChangeRequestMessage), [&](sys::Message *request) -> sys::MessagePointer {
+ auto message = static_cast<stm::message::TimeChangeRequestMessage *>(request);
+ timeManager->handleTimeChangeRequest(message->getTime());
+ return std::make_shared<sys::ResponseMessage>();
+ });
}
} /* namespace stm */
M module-services/service-time/TimeManager.cpp => module-services/service-time/TimeManager.cpp +5 -0
@@ 13,3 13,8 @@ void TimeManager::handleCellularTimeUpdate(struct tm time, std::chrono::minutes
rtcCommand->setTime(time);
rtcCommand->setTimezone(timezone);
}
+
+void TimeManager::handleTimeChangeRequest(const time_t &time)
+{
+ rtcCommand->setTime(time);
+}
M module-services/service-time/service-time/RTCCommand.hpp => module-services/service-time/service-time/RTCCommand.hpp +1 -0
@@ 12,6 12,7 @@ class RTCCommand : public RTCCommandInterface
{}
virtual ~RTCCommand() = default;
virtual void setTime(const struct tm &time) final;
+ virtual void setTime(const time_t &time) final;
virtual void setTimezone(const std::string &timezone) final;
private:
M module-services/service-time/service-time/RTCCommandInterface.hpp => module-services/service-time/service-time/RTCCommandInterface.hpp +7 -2
@@ 5,7 5,7 @@
#include <module-sys/Service/Service.hpp>
-#include <time.h>
+#include <ctime>
/**
* @brief Basic interface for bsp rtc related commands
@@ 19,10 19,15 @@ class RTCCommandInterface
virtual ~RTCCommandInterface() = default;
/**
* Sets RTC counter
- * @param time UTC time value to sed
+ * @param time UTC time value to set
*/
virtual void setTime(const struct tm &time) = 0;
/**
+ * Sets RTC counter
+ * @param time UTC time value to set
+ */
+ virtual void setTime(const time_t &time) = 0;
+ /**
* Sets timezone variable
* @param timezone new timezone variable
*/
M module-services/service-time/service-time/TimeManager.hpp => module-services/service-time/service-time/TimeManager.hpp +5 -0
@@ 25,6 25,11 @@ class TimeManager
* @param timezoneOffset timezone offset related to UTC time
*/
void handleCellularTimeUpdate(const struct tm time, std::chrono::minutes timezoneOffset);
+ /**
+ * Handles time change request.
+ * @param time UTC time to set
+ */
+ void handleTimeChangeRequest(const time_t &time);
private:
std::unique_ptr<RTCCommandInterface> rtcCommand;
M module-services/service-time/service-time/TimeMessage.hpp => module-services/service-time/service-time/TimeMessage.hpp +32 -2
@@ 52,10 52,10 @@ class TimeResponseMessage : public sys::ResponseMessage
namespace stm::message
{
- class UpdateRTCValueMessage : public sys::DataMessage
+ class UpdateRTCValueFromTmMessage : public sys::DataMessage
{
public:
- explicit UpdateRTCValueMessage(const struct tm &time)
+ explicit UpdateRTCValueFromTmMessage(const struct tm &time)
: sys::DataMessage(MessageType::MessageTypeUninitialized), time(time){};
auto getTime() -> struct tm &
@@ 67,6 67,21 @@ namespace stm::message
struct tm time;
};
+ class UpdateRTCValueFromTimestampMessage : public sys::DataMessage
+ {
+ public:
+ explicit UpdateRTCValueFromTimestampMessage(const time_t &time)
+ : sys::DataMessage(MessageType::MessageTypeUninitialized), time(time){};
+
+ auto getTime() -> time_t &
+ {
+ return time;
+ }
+
+ private:
+ time_t time;
+ };
+
class UpdateTimeZoneMessage : public sys::DataMessage
{
public:
@@ 81,4 96,19 @@ namespace stm::message
private:
std::string timezone;
};
+
+ class TimeChangeRequestMessage : public sys::DataMessage
+ {
+ public:
+ explicit TimeChangeRequestMessage(const time_t &time)
+ : sys::DataMessage(MessageType::MessageTypeUninitialized), time(time){};
+
+ auto getTime() -> time_t
+ {
+ return time;
+ }
+
+ private:
+ time_t time;
+ };
} // namespace stm::message
M module-sys/Service/BusProxy.hpp => module-sys/Service/BusProxy.hpp +11 -1
@@ 32,8 32,18 @@ namespace sys
template <typename Msg, typename... Params> bool sendUnicast(Params &&... params)
{
+ static_assert(std::is_base_of<sys::msg::Request, Msg>::value,
+ "Only sys::msg::Request can be sent via Unicast<>");
auto msg = std::make_shared<Msg>(std::forward<Params>(params)...);
- return sendUnicast(msg, Msg::target);
+ return sendUnicast(msg, msg->target());
+ }
+
+ template <typename Msg, typename... Params> void sendMulticast(Params &&... params)
+ {
+ static_assert(std::is_base_of<sys::msg::Notification, Msg>::value,
+ "Only sys::msg::Notification can be sent via Multicast<>");
+ auto msg = std::make_shared<Msg>(std::forward<Params>(params)...);
+ sendMulticast(msg, msg->channel());
}
std::vector<BusChannel> channels;
M module-sys/Service/Message.hpp => module-sys/Service/Message.hpp +24 -0
@@ 106,6 106,30 @@ namespace sys
void ValidateMulticastMessage() const;
};
+ namespace msg
+ {
+ struct Request : public sys::Message
+ {
+ Request() : Message(Type::Data)
+ {}
+ virtual const char *target() const = 0;
+ };
+
+ struct Response : public sys::Message
+ {
+ explicit Response(bool retCode = true) : Message(Type::Data), retCode(retCode)
+ {}
+ const bool retCode;
+ };
+
+ struct Notification : public sys::Message
+ {
+ Notification() : Message(Type::Data)
+ {}
+ virtual sys::BusChannel channel() const = 0;
+ };
+ } // namespace msg
+
enum class SystemMessageType
{
Ping,
M module-utils/CMakeLists.txt => module-utils/CMakeLists.txt +0 -10
@@ 50,21 50,11 @@ include(segger/rtt/CMakeLists.txt)
# add third party libs
include(third-party/re2.cmake)
-include(third-party/protobuf-lite.cmake)
include(third-party/libphonenumber.cmake)
-include(third-party/tinyexpr.cmake)
# link against libphonenumber
target_link_libraries (${PROJECT_NAME} PUBLIC ${LIBPHONENUMBER_TARGET})
-add_subdirectory(taglib EXCLUDE_FROM_ALL)
-set( TAGLIB_INCLUDE_DIRS
- "${CMAKE_CURRENT_SOURCE_DIR}/taglib/taglib/toolkit"
- "${CMAKE_CURRENT_SOURCE_DIR}/taglib/taglib"
- "${CMAKE_CURRENT_BINARY_DIR}/taglib"
- PARENT_SCOPE
-)
-
target_link_libraries(${PROJECT_NAME} PRIVATE crc32 )
# link against tinyexpr
M module-utils/Utils.cpp => module-utils/Utils.cpp +5 -2
@@ 2,9 2,12 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "Utils.hpp"
-#include <filesystem>
+
#include <crc32.h>
+#include <ctime>
+#include <filesystem>
+
namespace utils::filesystem
{
namespace
@@ 35,7 38,7 @@ namespace utils::filesystem
std::random_device random_device;
std::mt19937 generator(random_device());
- generator.seed(utils::time::Timestamp().getTime());
+ generator.seed(std::time(nullptr));
std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);
std::string random_string;
M module-utils/Utils.hpp => module-utils/Utils.hpp +5 -4
@@ 3,16 3,17 @@
#pragma once
#include "Split.hpp"
-#include "i18n/i18n.hpp"
+#include <i18n/i18n.hpp>
+#include <log/log.hpp>
+
+#include <magic_enum.hpp>
+
#include <algorithm> // std::find_if_not
#include <sstream>
#include <iomanip>
#include <cmath>
#include <chrono>
#include <random>
-#include "time/time_conversion.hpp"
-
-#include <magic_enum.hpp>
namespace utils
{
M module-utils/bootconfig/src/bootconfig.cpp => module-utils/bootconfig/src/bootconfig.cpp +2 -2
@@ 149,7 149,7 @@ namespace boot
m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type);
m_boot_json = bootJsonPath;
m_bootloader_version = m_boot_json_parsed[boot::json::bootloader][boot::json::os_version].string_value();
- m_timestamp = utils::time::Timestamp().str("%c");
+ m_timestamp = utils::time::getCurrentTimestamp().str("%c");
m_os_version = std::string(VERSION);
LOG_INFO("boot_config: %s", to_json().dump().c_str());
@@ 160,7 160,7 @@ namespace boot
m_os_image = purefs::file::boot_bin;
m_os_root_path = purefs::createPath(purefs::dir::getRootDiskPath(), m_os_type);
m_boot_json = bootJsonPath;
- m_timestamp = utils::time::Timestamp().str("%c");
+ m_timestamp = utils::time::getCurrentTimestamp().str("%c");
m_os_version = std::string(VERSION);
LOG_WARN("%s failed to parse %s: \"%s\"", __FUNCTION__, bootJsonPath.c_str(), parseErrors.c_str());
return false;
D module-utils/parallel-hashmap => module-utils/parallel-hashmap +0 -1
@@ 1,1 0,0 @@
-Subproject commit e77a448e95643a4cf9a0efdaa8fe91d44d97869c
D module-utils/protobuf => module-utils/protobuf +0 -1
@@ 1,1 0,0 @@
-Subproject commit 1733c4f163746471c720d99100110f078b5dcd44
D module-utils/taglib => module-utils/taglib +0 -1
@@ 1,1 0,0 @@
-Subproject commit 351dd5f5c8ad2fa95b483bee2505b8e926a21873
M module-utils/test/test_i18n.cpp => module-utils/test/test_i18n.cpp +4 -4
@@ 16,7 16,7 @@ TEST_CASE("Test set display language - empty display language string")
REQUIRE(utils::getDisplayLanguage().empty());
// Invalid string provided - language should be set to default one.
- CHECK(utils::setDisplayLanguage(""));
+ CHECK_FALSE(utils::setDisplayLanguage(""));
REQUIRE(utils::getDisplayLanguage() == utils::getDefaultLanguage());
}
@@ 27,7 27,7 @@ TEST_CASE("Test set display language - invalid display language string")
REQUIRE(utils::getDisplayLanguage().empty());
// Invalid string provided - language should be set to default one.
- CHECK(utils::setDisplayLanguage("NonExistingLanguage"));
+ CHECK_FALSE(utils::setDisplayLanguage("NonExistingLanguage"));
REQUIRE(utils::getDisplayLanguage() == utils::getDefaultLanguage());
}
@@ 38,7 38,7 @@ TEST_CASE("Test set display language - double invalid display language string")
REQUIRE(utils::getDisplayLanguage().empty());
// Invalid string provided - language should be set to default one.
- CHECK(utils::setDisplayLanguage(""));
+ CHECK_FALSE(utils::setDisplayLanguage(""));
REQUIRE(utils::getDisplayLanguage() == utils::getDefaultLanguage());
// Invalid string provided - language already set to default one so method returns false.
@@ 93,7 93,7 @@ TEST_CASE("Test get string method - invalid display language set")
REQUIRE(utils::getDisplayLanguage().empty());
// Invalid string provided - language should be set to default one.
- CHECK(utils::setDisplayLanguage(""));
+ CHECK_FALSE(utils::setDisplayLanguage(""));
REQUIRE(utils::getDisplayLanguage() == utils::getDefaultLanguage());
// Default fallback language set - English
M module-utils/third-party/libphonenumber.cmake => module-utils/third-party/libphonenumber.cmake +1 -5
@@ 67,11 67,7 @@ if (NOT RE2_TARGET)
endif ()
target_link_libraries (${LIBPHONENUMBER_TARGET} PUBLIC ${RE2_TARGET})
-# protobuf dependency
-if (NOT PROTOBUF_TARGET)
- message (FATAL_ERROR "Protobuf is required for libphonenumber")
-endif()
-target_link_libraries (${LIBPHONENUMBER_TARGET} PUBLIC ${PROTOBUF_TARGET})
+target_link_libraries (${LIBPHONENUMBER_TARGET} PUBLIC protobuf::libprotobuf-lite)
# turn on optimization in debug
third_party_source_optimization (${LIBPHONENUMBER_SOURCES})
D module-utils/third-party/protobuf-lite.cmake => module-utils/third-party/protobuf-lite.cmake +0 -64
@@ 1,64 0,0 @@
-include (thirdparty)
-
-# add sources
-set (PROTOBUF_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/protobuf/src)
-set (PROTOBUF ${PROTOBUF_SRCDIR}/google/protobuf)
-set (PROTOBUF_SOURCES
- ${PROTOBUF}/any_lite.cc
- ${PROTOBUF}/arena.cc
- ${PROTOBUF}/extension_set.cc
- ${PROTOBUF}/generated_enum_util.cc
- ${PROTOBUF}/generated_message_table_driven_lite.cc
- ${PROTOBUF}/generated_message_util.cc
- ${PROTOBUF}/implicit_weak_message.cc
- ${PROTOBUF}/io/coded_stream.cc
- ${PROTOBUF}/io/io_win32.cc
- ${PROTOBUF}/io/strtod.cc
- ${PROTOBUF}/io/zero_copy_stream.cc
- ${PROTOBUF}/io/zero_copy_stream_impl.cc
- ${PROTOBUF}/io/zero_copy_stream_impl_lite.cc
- ${PROTOBUF}/message_lite.cc
- ${PROTOBUF}/parse_context.cc
- ${PROTOBUF}/repeated_field.cc
- ${PROTOBUF}/stubs/bytestream.cc
- ${PROTOBUF}/stubs/common.cc
- ${PROTOBUF}/stubs/int128.cc
- ${PROTOBUF}/stubs/status.cc
- ${PROTOBUF}/stubs/statusor.cc
- ${PROTOBUF}/stubs/stringpiece.cc
- ${PROTOBUF}/stubs/stringprintf.cc
- ${PROTOBUF}/stubs/structurally_valid.cc
- ${PROTOBUF}/stubs/strutil.cc
- ${PROTOBUF}/stubs/time.cc
- ${PROTOBUF}/wire_format_lite.cc
-)
-
-# create static library for the third party
-set (PROTOBUF_TARGET protobuf)
-add_library (${PROTOBUF_TARGET} STATIC ${PROTOBUF_SOURCES})
-
-# setup flags for the third party
-third_party_target_setup (${PROTOBUF_TARGET})
-
-# set compile definitions for third party libraries
-target_compile_definitions (${PROTOBUF_TARGET} PUBLIC GOOGLE_PROTOBUF_NO_THREADS)
-
-# supress warnings for protobuf
-set_source_files_properties (${PROTOBUF_SOURCES}
- PROPERTIES COMPILE_FLAGS
- "-Wno-stringop-truncation \
- -Wno-stringop-overflow \
- -Wno-sign-compare \
- -Wno-type-limits \
- -Wno-redundant-move \
- -Wno-maybe-uninitialized"
-)
-
-# add include dir
-target_include_directories (${PROTOBUF_TARGET} PUBLIC ${PROTOBUF_SRCDIR})
-
-# module-os dependency (locking support)
-target_link_libraries (${RE2_TARGET} PUBLIC module-os)
-
-# turn on optimization in debug
-third_party_source_optimization (${PROTOBUF_SOURCES})
D module-utils/third-party/tinyexpr.cmake => module-utils/third-party/tinyexpr.cmake +0 -20
@@ 1,20 0,0 @@
-include (thirdparty)
-
-# add tinyexpr library sources
-set (TINYEXPR_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/tinyexpr)
-set (TINYEXPR_SOURCES
- ${TINYEXPR_SRCDIR}/tinyexpr.c
-)
-
-# create static library for the third party
-set (TINYEXPR_TARGET tinyexpr)
-add_library (${TINYEXPR_TARGET} STATIC ${TINYEXPR_SOURCES})
-
-# setup flags for the third party
-third_party_target_setup (${TINYEXPR_TARGET})
-
-# add include directory path
-target_include_directories (${TINYEXPR_TARGET} PUBLIC ${TINYEXPR_SRCDIR})
-
-# optimize thirdy party sources in dbeug
-third_party_source_optimization (${TINYEXPR_SOURCES})
M module-utils/time/time_conversion.cpp => module-utils/time/time_conversion.cpp +3 -25
@@ 56,7 56,6 @@ namespace utils::time
} // namespace
Locale tlocale;
- static int msTimeGmtOff = 4 * utils::time::minutesInQuarterOfHour * utils::time::secondsInMinute;
UTF8 Localer::get_replacement(Replacements val, const struct tm &timeinfo)
{
@@ 82,12 81,8 @@ namespace utils::time
Timestamp::Timestamp()
{
- auto err = bsp::rtc::getCurrentTimestamp(&time);
- time += utils::time::Time::getTimeZoneOffset();
- if (err != bsp::rtc::ErrorCode::OK) {
- LOG_ERROR("rtc::getCurrentTimestamp failure!");
- }
- timeinfo = *localtime(&time);
+ time = 0;
+ timeinfo = *std::localtime(&time);
}
void Timestamp::set_time(time_t newtime)
@@ 284,16 279,6 @@ namespace utils::time
}
}
- void Time::setTimeZoneOffset(int tzOffset)
- {
- msTimeGmtOff = tzOffset;
- }
-
- int Time::getTimeZoneOffset()
- {
- return msTimeGmtOff;
- };
-
Duration::Duration(time_t duration) : duration(duration)
{
calculate();
@@ 345,13 330,6 @@ namespace utils::time
Timestamp getCurrentTimestamp()
{
- return Timestamp{};
- }
-
- std::string getHoursMinInCurrentTimeFormat()
- {
- auto timestamp = getCurrentTimestamp();
- return utils::dateAndTimeSettings.isTimeFormat12() ? timestamp.str(hoursMinFormat12H)
- : timestamp.str(hoursMinFormat24H);
+ return Timestamp{std::time(nullptr)};
}
}; // namespace utils::time
M module-utils/time/time_conversion.hpp => module-utils/time/time_conversion.hpp +2 -7
@@ 153,7 153,8 @@ namespace utils
std::string long_ago_format = "%d.%m.%y";
/// shows time in past: time_now - val in seconds
- DateTime(time_t val = 0, bool date_format_long = true) : date_format_long(date_format_long)
+ DateTime(time_t val = 0, bool date_format_long = true)
+ : Timestamp(std::time(nullptr)), date_format_long(date_format_long)
{
before_n_sec(val);
}
@@ 185,11 186,6 @@ namespace utils
public:
Time(time_t val = 0, bool date_format_long = true) : DateTime(val, date_format_long){};
virtual UTF8 str(std::string format = "") final;
-
- /// set time zone offset including adjustment for daylight saving
- static void setTimeZoneOffset(int tzOffset);
- // get time zone offset including adjustment for daylight saving
- static int getTimeZoneOffset();
};
class Duration
@@ 288,6 284,5 @@ namespace utils
};
Timestamp getCurrentTimestamp();
- std::string getHoursMinInCurrentTimeFormat();
} // namespace time
} // namespace utils
D module-utils/tinyexpr => module-utils/tinyexpr +0 -1
@@ 1,1 0,0 @@
-Subproject commit 2ef22d228f8760561b8f485f0997ca07fafd0f12
M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +22 -20
@@ 16,23 16,28 @@ set(FF_FAT_SOURCES
${FF_FAT_SOURCES_THIRDPARTY}
${CMAKE_CURRENT_SOURCE_DIR}/drivers/src/thirdparty/fatfs/ffsystem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/drivers/src/thirdparty/fatfs/ff_glue.cpp
+)
+set(FF_LFS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/drivers/src/thirdparty/littlefs/lfs_glue.cpp
)
set(SOURCES
- ${FF_FAT_SOURCES}
- src/purefs/filesystem_paths.cpp
- src/purefs/blkdev/disk_manager.cpp
- src/purefs/blkdev/disk.cpp
- src/purefs/blkdev/partition_parser.cpp
- src/purefs/blkdev/disk_handle.cpp
- src/purefs/fs/filesystem.cpp
- src/purefs/fs/filesystem_operations.cpp
- src/purefs/fs/filesystem_syscalls.cpp
- src/purefs/fs/filesystem_cwd.cpp
- src/purefs/vfs_subsystem.cpp
- drivers/src/purefs/fs/filesystem_vfat.cpp
- drivers/src/purefs/fs/filesystem_littlefs.cpp
+ ${FF_FAT_SOURCES}
+ ${FF_LFS_SOURCES}
+ src/purefs/filesystem_paths.cpp
+ src/purefs/blkdev/disk_manager.cpp
+ src/purefs/blkdev/disk.cpp
+ src/purefs/blkdev/partition_parser.cpp
+ src/purefs/blkdev/disk_handle.cpp
+ src/purefs/fs/filesystem.cpp
+ src/purefs/fs/filesystem_operations.cpp
+ src/purefs/fs/filesystem_syscalls.cpp
+ src/purefs/fs/filesystem_cwd.cpp
+ src/purefs/vfs_subsystem.cpp
+ src/purefs/fs/notifier.cpp
+ src/purefs/fs/fsnotify.cpp
+ drivers/src/purefs/fs/filesystem_vfat.cpp
+ drivers/src/purefs/fs/filesystem_littlefs.cpp
)
@@ 64,23 69,20 @@ target_compile_definitions(${PROJECT_NAME}
target_include_directories(${PROJECT_NAME}
PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}/include/user/deprecated
- ${CMAKE_CURRENT_SOURCE_DIR}/include/user/
- ${CMAKE_CURRENT_SOURCE_DIR}/include/internal/
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/user
${CMAKE_CURRENT_SOURCE_DIR}/drivers/include
)
target_include_directories(${PROJECT_NAME}
PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/include/internal
${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty/fatfs
${CMAKE_CURRENT_SOURCE_DIR}/drivers/include/thirdparty
${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/fatfs/source
)
-target_link_libraries(${PROJECT_NAME} PUBLIC ${TARGET_LIBRARIES} module-bsp module-utils)
-target_link_libraries(${PROJECT_NAME} PRIVATE littlefs )
-# TODO: Temporary only remove when removing old vfs
-target_link_libraries(${PROJECT_NAME} PUBLIC utils-bootconfig )
+target_link_libraries(${PROJECT_NAME} PUBLIC ${TARGET_LIBRARIES} module-os module-sys module-bsp module-utils)
+target_link_libraries(${PROJECT_NAME} PRIVATE littlefs)
if (${ENABLE_TESTS})
add_subdirectory(tests)
A module-vfs/include/internal/purefs/fs/notifier.hpp => module-vfs/include/internal/purefs/fs/notifier.hpp +130 -0
@@ 0,0 1,130 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#pragma once
+
+#include <map>
+#include <string>
+#include <memory>
+#include <optional>
+#include <purefs/fs/fsnotify.hpp>
+#include <purefs/fs/inotify_flags.hpp>
+
+namespace sys
+{
+ class Service;
+}
+namespace cpp_freertos
+{
+ class MutexRecursive;
+}
+namespace purefs::fs::internal
+{
+ //! Internal class related to the notify VFS events
+ class notifier
+ {
+ //! Container for path item
+ struct path_item
+ {
+ path_item(std::string_view _path, bool _read_only) : path(_path), read_only(_read_only)
+ {}
+ const std::string path;
+ const bool read_only;
+ };
+ //! Container for service and subscribed events
+ struct service_item
+ {
+ service_item(std::weak_ptr<sys::Service> _service, inotify_flags _subscribed_events)
+ : service(_service), subscribed_events(_subscribed_events)
+ {}
+ const std::weak_ptr<sys::Service> service;
+ const inotify_flags subscribed_events;
+ };
+ //! Container for the the event
+ using container_t = std::multimap<std::string, service_item>;
+
+ public:
+ notifier();
+ notifier(notifier &) = delete;
+ notifier &operator=(notifier &) = delete;
+ virtual ~notifier();
+ //! Iterator for the registered event
+ using item_it = container_t::iterator;
+ /**
+ * @brief Register selected path for the monitoring
+ *
+ * @param path Path for monitor
+ * @param owner Service which should be notified
+ * @param flags Event mask which should be monitored
+ * @return std::optional<item_it> Registered event iterator or nothing if failed
+ */
+ auto register_path(std::string_view path, std::shared_ptr<sys::Service> owner, inotify_flags flags)
+ -> std::optional<item_it>;
+ /**
+ * @brief Unregister selected path from monitoring
+ *
+ * @param item Iterator returned by the @see register_path method
+ */
+ auto unregister_path(item_it item) -> void;
+ /**
+ * @brief Internal method called on file open
+ *
+ * @param path Open file path
+ * @param fd File descriptor assigned by open method
+ * @param ro File is opened in read only mode
+ */
+ auto notify_open(std::string_view path, int fd, bool ro) const -> void;
+ /**
+ * @brief Internal method called on closing gile
+ *
+ * @param fd File descriptor
+ */
+ auto notify_close(int fd) const -> void;
+ /**
+ * @brief Notify for event on the file system
+ *
+ * @param fd File descriptor for file
+ * @param mask Filesystem event type
+ */
+ auto notify(int fd, inotify_flags mask) const -> void;
+ /**
+ * @brief Notify for event on filesystem on path change
+ *
+ * @param path Path before event occured
+ * @param path_prv Path after event occured
+ * @param mask Filesystem event type
+ */
+ auto notify(std::string_view path, std::string_view path_prv, inotify_flags mask) const -> void;
+ /**
+ * @brief Notify for event on the filesystem
+ *
+ * @param path Path related to th event
+ * @param mask Filesystem event type
+ */
+ auto notify(std::string_view path, inotify_flags mask) const -> void
+ {
+ notify(path, "", mask);
+ }
+
+ private:
+ /**
+ * @brief Private method called for send file monitor event
+ *
+ * @param svc Target service
+ * @param flags Filesystem event type
+ * @param name Path related to the event before change
+ * @param name_dst Path realated to the event after change
+ */
+ virtual auto send_notification(std::shared_ptr<sys::Service> svc,
+ inotify_flags flags,
+ std::string_view name,
+ std::string_view name_dst) const -> void;
+
+ private:
+ //! Events container
+ container_t m_events;
+ //! Map file descriptors with path assiociated with it
+ mutable std::map<int, path_item> m_fd_map;
+ //! Internal mutex for lock the object
+ std::unique_ptr<cpp_freertos::MutexRecursive> m_lock;
+ };
+} // namespace purefs::fs::internal
D module-vfs/include/user/deprecated/vfsNotifier.hpp => module-vfs/include/user/deprecated/vfsNotifier.hpp +0 -98
@@ 1,98 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-//
-#pragma once
-#include <unordered_map>
-#include <mutex.hpp>
-#include <functional>
-#include <string>
-#include <thread.hpp>
-
-namespace vfsn::utility
-{
- class vfsNotifier
- {
- struct FF_FILE;
- using FILE = FF_FILE;
-
- public:
- //! Default constructor and destructor
- vfsNotifier() = default;
- vfsNotifier(const vfsNotifier &) = delete;
- vfsNotifier &operator=(const vfsNotifier &) = delete;
- //! Event type notified for indexer
- enum class FsEvent
- {
- initialized, //! Filesystem is intialized
- modified, //! File is modified
- deleted, //! File is deleted
- renamed
- };
- /** Notification handler type
- * Notify function callback defiinition
- */
- using NotifyHandler = std::function<void(std::string_view, FsEvent, std::string_view)>;
- /** This method is called by the vfs layer when vfs open file
- * @param[in] filename Opened file path
- * @param[in] mode Open mode
- * @param[in] Handle to opened file
- * @return None
- */
- auto onFileOpen(std::string_view filename, const char *mode, const FILE *file) noexcept -> void;
- /** This method is called by the vfs layer when vfs close file
- * @param[in] filee Closed file handle
- * @return None
- */
- auto onFileClose(const FILE *file) noexcept -> void;
- /** This method is called by the vfs layer when file is removed
- * @param[in] filename Removed file path
- * @return None
- */
- auto onFileRemove(std::string_view filename) noexcept -> void;
- /** This method is called by the vfs layer when the vfs rename file
- * @param[in] new_file New path name for the file
- * @param[in] old_file Old path for the file
- * @return None
- */
- auto onFileRename(std::string_view new_file, std::string_view old_file) noexcept -> void;
- /** This method is called by the vfs layer when the disk is intiialized
- * @return None
- */
- auto onFileSystemInitialized() noexcept -> void
- {
- notify("/", FsEvent::initialized);
- }
- /** Method for register notification handler
- * @note This function is called from the thread contest which use vfs call
- * @param[in] hwnd Notification handler funtion
- * @return None
- */
- auto registerNotificationHandler(NotifyHandler hwnd) -> void
- {
- notificationCallback = hwnd;
- threadHandle = hwnd ? cpp_freertos::Thread::GetCurrentThreadHandle() : nullptr;
- }
-
- private:
- /** Private notification helper internal method
- * @param[in] file Modified file path
- * @param[in] event Notification event type
- * @param[in] old_file Old file path
- * @return None
- */
- auto notify(std::string_view file, FsEvent event, std::string_view old_file = "") -> void
- {
- if (threadHandle != cpp_freertos::Thread::GetCurrentThreadHandle() && notificationCallback)
- notificationCallback(file, event, old_file);
- }
-
- private:
- //! Map for opened handles and paths
- std::unordered_map<const FILE *, std::string> mOpenedMap;
- //! Mutex for unordered map
- cpp_freertos::MutexStandard mMutex;
- //! Notification handler callback
- NotifyHandler notificationCallback;
- TaskHandle_t threadHandle;
- };
-} // namespace vfsn::utility
R module-vfs/include/internal/purefs/fs/directory_handle.hpp => module-vfs/include/user/purefs/fs/directory_handle.hpp +0 -0
R module-vfs/include/internal/purefs/fs/file_handle.hpp => module-vfs/include/user/purefs/fs/file_handle.hpp +1 -1
@@ 14,7 14,7 @@ namespace purefs::fs::internal
public:
file_handle(const file_handle &) = delete;
auto operator=(const file_handle &) = delete;
- virtual ~file_handle() = default;
+ virtual ~file_handle() = default;
file_handle(std::shared_ptr<mount_point> mp, unsigned flags) : m_mount_point(mp), m_flags(flags)
{}
[[nodiscard]] auto error() const noexcept
M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +11 -1
@@ 15,6 15,7 @@
#include <purefs/fs/directory_handle.hpp>
#include <purefs/fs/mount_point.hpp>
#include <purefs/fs/mount_flags.hpp>
+#include <purefs/fs/fsnotify.hpp>
#include <type_traits>
struct statvfs;
@@ 30,6 31,11 @@ namespace cpp_freertos
class MutexRecursive;
}
+namespace sys
+{
+ class Service;
+}
+
namespace purefs::fs
{
/** This is the filesystem class layer
@@ 41,6 47,7 @@ namespace purefs::fs
namespace internal
{
class directory_handle;
+ class notifier;
}
class filesystem
{
@@ 142,6 149,9 @@ namespace purefs::fs
auto getcwd() noexcept -> std::string_view;
auto chdir(std::string_view name) noexcept -> int;
+ /** Inotify API */
+ [[nodiscard]] auto inotify_create(std::shared_ptr<sys::Service> svc) -> std::shared_ptr<inotify>;
+
private:
/** Unregister filesystem driver
* @param[in] fsname Unique filesystem name for example fat
@@ 271,7 281,6 @@ namespace purefs::fs
}
}
}
-
private:
std::weak_ptr<blkdev::disk_manager> m_diskmm;
std::unordered_map<std::string, std::shared_ptr<filesystem_operations>> m_fstypes;
@@ 279,5 288,6 @@ namespace purefs::fs
std::unordered_set<std::string> m_partitions;
internal::handle_mapper<fsfile> m_fds;
std::unique_ptr<cpp_freertos::MutexRecursive> m_lock;
+ std::shared_ptr<internal::notifier> m_notifier;
};
} // namespace purefs::fs
A module-vfs/include/user/purefs/fs/fsnotify.hpp => module-vfs/include/user/purefs/fs/fsnotify.hpp +58 -0
@@ 0,0 1,58 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+#include <string>
+#include <memory>
+#include <purefs/fs/inotify_flags.hpp>
+
+namespace sys
+{
+ class Service;
+}
+namespace cpp_freertos
+{
+ class MutexRecursive;
+}
+namespace purefs::fs
+{
+ namespace internal
+ {
+ class notifier;
+ struct inotify_container;
+ } // namespace internal
+
+ //! Inotifier object returned by the monitoring API
+ class inotify
+ {
+ public:
+ ~inotify();
+ /** Constructor for the inotify user object
+ * @param[in] svc Service owner
+ * @param[in] notifier Master notifier object
+ */
+ inotify(std::shared_ptr<sys::Service> svc, std::shared_ptr<purefs::fs::internal::notifier> notifier);
+ /** Add path for monitoring for monitoring
+ * @param[in] monitored_path Path or file which should be monitored
+ * @param[in] event_mask Event mask for file monitor
+ * @return Error code
+ */
+ int add_watch(std::string_view monitored_path, inotify_flags event_mask);
+ /**
+ * @param[in] monitored_path Monitored path for removal
+ * @return Error code
+ */
+ int rm_watch(std::string_view monitored_path);
+
+ private:
+ //! Owning service
+ std::weak_ptr<sys::Service> m_svc;
+ //! Owner notifier
+ std::weak_ptr<internal::notifier> m_notify;
+ //! Map for the devices
+ std::unique_ptr<internal::inotify_container> m_evlist;
+ //! Lock the object
+ std::unique_ptr<cpp_freertos::MutexRecursive> m_lock;
+ };
+
+} // namespace purefs::fs
R module-vfs/include/internal/purefs/fs/handle_mapper.hpp => module-vfs/include/user/purefs/fs/handle_mapper.hpp +0 -0
A module-vfs/include/user/purefs/fs/inotify.hpp => module-vfs/include/user/purefs/fs/inotify.hpp +22 -0
@@ 0,0 1,22 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#pragma once
+#include <memory>
+#include <purefs/vfs_subsystem.hpp>
+#include <purefs/fs/fsnotify.hpp>
+
+namespace purefs::fs
+{
+ /** Create inotify class which owns the notifier interface
+ * @param[in] svc Owner of the service
+ * @return Inotify object shared ptr or errno if nullptr
+ */
+ inline auto inotify_create(std::shared_ptr<sys::Service> svc) -> std::shared_ptr<inotify>
+ {
+ const auto vfs = subsystem::vfs_core();
+ if (!vfs) {
+ return nullptr;
+ }
+ return vfs->inotify_create(svc);
+ }
+} // namespace purefs::fs
A module-vfs/include/user/purefs/fs/inotify_flags.hpp => module-vfs/include/user/purefs/fs/inotify_flags.hpp +36 -0
@@ 0,0 1,36 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+namespace purefs::fs
+{
+ //! Event monitor flag
+ enum class inotify_flags : unsigned
+ {
+ attrib = 0x01, //! Attribute changed
+ close_write = 0x02, //! File closed after write
+ close_nowrite = 0x04, //! File closed without write
+ del = 0x08, //! File was deleted
+ move_src = 0x10, //! File moved
+ move_dst = 0x20, //! File moved
+ open = 0x40, //! File was opended
+ dmodify = 0x80, //! Directory entry modified
+ };
+ inline auto operator|(inotify_flags fl1, inotify_flags fl2)
+ {
+ return static_cast<inotify_flags>(static_cast<unsigned>(fl1) | static_cast<unsigned>(fl2));
+ }
+ inline auto operator&(inotify_flags fl1, inotify_flags fl2)
+ {
+ return static_cast<inotify_flags>(static_cast<unsigned>(fl1) & static_cast<unsigned>(fl2));
+ }
+ inline auto operator&&(inotify_flags fl1, inotify_flags fl2) -> bool
+ {
+ return static_cast<bool>(static_cast<unsigned>(fl1) & static_cast<unsigned>(fl2));
+ }
+ inline auto operator||(inotify_flags fl1, inotify_flags fl2) -> bool
+ {
+ return static_cast<bool>(static_cast<unsigned>(fl1) | static_cast<unsigned>(fl2));
+ }
+
+} // namespace purefs::fs
A module-vfs/include/user/purefs/fs/inotify_message.hpp => module-vfs/include/user/purefs/fs/inotify_message.hpp +28 -0
@@ 0,0 1,28 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+#include <Service/Message.hpp>
+#include <purefs/fs/inotify_flags.hpp>
+
+namespace purefs::fs::message
+{
+ //! Class message received when on new file event
+ struct inotify final : public ::sys::DataMessage
+ {
+ /**
+ * @brief Construct a new inotify object
+ *
+ * @param _flags Event type
+ * @param _name Filename path
+ * @param _name_prev Old path (when move)
+ */
+ inotify(inotify_flags _flags, std::string_view _name, std::string_view _name_prev)
+ : flags(_flags), name(_name), name_prev(_name_prev)
+ {}
+ virtual ~inotify() = default;
+ const inotify_flags flags;
+ const std::string name;
+ const std::string name_prev;
+ };
+} // namespace purefs::fs::message
R module-vfs/include/internal/purefs/fs/mount_flags.hpp => module-vfs/include/user/purefs/fs/mount_flags.hpp +0 -0
R module-vfs/include/internal/purefs/fs/mount_point.hpp => module-vfs/include/user/purefs/fs/mount_point.hpp +1 -1
@@ 31,7 31,7 @@ namespace purefs::fs::internal
{}
mount_point(const mount_point &) = delete;
auto operator=(const mount_point &) = delete;
- virtual ~mount_point() = default;
+ virtual ~mount_point() = default;
auto disk() const noexcept
{
return m_diskh.lock();
D module-vfs/src/deprecated/vfsNotifier.cpp => module-vfs/src/deprecated/vfsNotifier.cpp +0 -38
@@ 1,38 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include "vfsNotifier.hpp"
-#include <vfs.hpp>
-#include <cstring>
-
-namespace vfsn::utility
-{
-
- auto vfsNotifier::onFileOpen(std::string_view filename, const char *mode, const FILE *file) noexcept -> void
- {
- if (file && std::strpbrk(mode, "+wa")) {
- cpp_freertos::LockGuard _lock(mMutex);
- mOpenedMap.emplace(file, vfs.getAbsolutePath(filename));
- }
- }
- auto vfsNotifier::onFileClose(const FILE *file) noexcept -> void
- {
- cpp_freertos::LockGuard _lock(mMutex);
- const auto item = mOpenedMap.find(file);
- if (item != mOpenedMap.end()) {
- const auto path = item->second;
- mOpenedMap.erase(item);
- notify(path, FsEvent::modified);
- }
- }
-
- auto vfsNotifier::onFileRemove(std::string_view filename) noexcept -> void
- {
- notify(vfs.getAbsolutePath(filename), FsEvent::deleted);
- }
-
- auto vfsNotifier::onFileRename(std::string_view new_file, std::string_view old_file) noexcept -> void
- {
- notify(vfs.getAbsolutePath(new_file), FsEvent::renamed, vfs.getAbsolutePath(old_file));
- }
-} // namespace vfsn::utility
M module-vfs/src/purefs/fs/filesystem.cpp => module-vfs/src/purefs/fs/filesystem.cpp +11 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/fs/filesystem.hpp>
#include <purefs/fs/filesystem_operations.hpp>
@@ 6,6 6,8 @@
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/fs/thread_local_cwd.hpp>
#include <purefs/blkdev/disk_handle.hpp>
+#include <purefs/fs/notifier.hpp>
+#include <purefs/fs/fsnotify.hpp>
#include <log/log.hpp>
#include <split_sv.hpp>
#include <errno.h>
@@ 21,7 23,8 @@ namespace purefs::fs
};
}
filesystem::filesystem(std::shared_ptr<blkdev::disk_manager> diskmm)
- : m_diskmm(diskmm), m_lock(new cpp_freertos::MutexRecursive)
+ : m_diskmm(diskmm), m_lock(std::make_unique<cpp_freertos::MutexRecursive>()),
+ m_notifier(std::make_unique<internal::notifier>())
{}
filesystem::~filesystem()
@@ 308,4 311,10 @@ namespace purefs::fs
return {};
}
}
+
+ auto filesystem::inotify_create(std::shared_ptr<sys::Service> svc) -> std::shared_ptr<inotify>
+ {
+ return std::make_shared<inotify>(svc, m_notifier);
+ }
+
} // namespace purefs::fs
M module-vfs/src/purefs/fs/filesystem_syscalls.cpp => module-vfs/src/purefs/fs/filesystem_syscalls.cpp +47 -10
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/fs/filesystem.hpp>
#include <errno.h>
@@ 7,6 7,7 @@
#include <purefs/fs/file_handle.hpp>
#include <purefs/fs/directory_handle.hpp>
#include <purefs/fs/thread_local_cwd.hpp>
+#include <purefs/fs/notifier.hpp>
#include <fcntl.h>
namespace purefs::fs
@@ 23,12 24,20 @@ namespace purefs::fs
auto filesystem::unlink(std::string_view name) noexcept -> int
{
- return invoke_fops(iaccess::rw, &filesystem_operations::unlink, name);
+ const auto err = invoke_fops(iaccess::rw, &filesystem_operations::unlink, name);
+ if (!err) {
+ m_notifier->notify(name, inotify_flags::del);
+ }
+ return err;
}
auto filesystem::mkdir(std::string_view path, int mode) noexcept -> int
{
- return invoke_fops(iaccess::rw, &filesystem_operations::mkdir, path, mode);
+ const auto err = invoke_fops(iaccess::rw, &filesystem_operations::mkdir, path, mode);
+ if (!err) {
+ m_notifier->notify(path, inotify_flags::dmodify);
+ }
+ return err;
}
auto filesystem::ioctl(std::string_view path, int cmd, void *arg) noexcept -> int
@@ 38,7 47,11 @@ namespace purefs::fs
auto filesystem::utimens(std::string_view path, std::array<timespec, 2> &tv) noexcept -> int
{
- return invoke_fops(iaccess::ro, &filesystem_operations::utimens, path, tv);
+ const auto err = invoke_fops(iaccess::ro, &filesystem_operations::utimens, path, tv);
+ if (!err) {
+ m_notifier->notify(path, inotify_flags::attrib);
+ }
+ return err;
}
auto filesystem::flock(int fd, int cmd) noexcept -> int
@@ 53,7 66,11 @@ namespace purefs::fs
auto filesystem::chmod(std::string_view path, mode_t mode) noexcept -> int
{
- return invoke_fops(iaccess::rw, &filesystem_operations::chmod, path, mode);
+ const auto err = invoke_fops(iaccess::rw, &filesystem_operations::chmod, path, mode);
+ if (!err) {
+ m_notifier->notify(path, inotify_flags::attrib);
+ }
+ return err;
}
auto filesystem::write(int fd, const char *ptr, size_t len) noexcept -> ssize_t
@@ 88,22 105,39 @@ namespace purefs::fs
auto filesystem::fchmod(int fd, mode_t mode) noexcept -> int
{
- return invoke_fops(&filesystem_operations::fchmod, fd, mode);
+ const auto err = invoke_fops(&filesystem_operations::fchmod, fd, mode);
+ if (!err) {
+ m_notifier->notify(fd, inotify_flags::attrib);
+ }
+ return err;
}
auto filesystem::symlink(std::string_view existing, std::string_view newlink) noexcept -> int
{
- return invoke_fops_same_mp(&filesystem_operations::symlink, existing, newlink);
+ const auto err = invoke_fops_same_mp(&filesystem_operations::symlink, existing, newlink);
+ if (!err) {
+ m_notifier->notify(newlink, inotify_flags::dmodify);
+ }
+ return err;
}
auto filesystem::link(std::string_view existing, std::string_view newlink) noexcept -> int
{
- return invoke_fops_same_mp(&filesystem_operations::link, existing, newlink);
+ const auto err = invoke_fops_same_mp(&filesystem_operations::link, existing, newlink);
+ if (!err) {
+ m_notifier->notify(newlink, inotify_flags::dmodify);
+ }
+ return err;
}
auto filesystem::rename(std::string_view oldname, std::string_view newname) noexcept -> int
{
- return invoke_fops_same_mp(&filesystem_operations::rename, oldname, newname);
+ const auto err = invoke_fops_same_mp(&filesystem_operations::rename, oldname, newname);
+ if (!err) {
+ m_notifier->notify(oldname, newname, inotify_flags::move_src);
+ m_notifier->notify(newname, oldname, inotify_flags::move_dst);
+ }
+ return err;
}
auto filesystem::open(std::string_view path, int flags, int mode) noexcept -> int
@@ 129,7 163,9 @@ namespace purefs::fs
if (err) {
return err;
}
- return add_filehandle(fh);
+ const auto fd = add_filehandle(fh);
+ m_notifier->notify_open(path, fd, (flags & O_ACCMODE) == O_RDONLY);
+ return fd;
}
else {
LOG_ERROR("VFS: Unable to lock fops");
@@ 142,6 178,7 @@ namespace purefs::fs
auto ret = invoke_fops(&filesystem_operations::close, fd);
if (!ret) {
ret = (remove_filehandle(fd)) ? (0) : (-EBADF);
+ m_notifier->notify_close(fd);
}
return ret;
}
A module-vfs/src/purefs/fs/fsnotify.cpp => module-vfs/src/purefs/fs/fsnotify.cpp +83 -0
@@ 0,0 1,83 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <purefs/fs/fsnotify.hpp>
+#include <purefs/fs/notifier.hpp>
+#include <log/log.hpp>
+#include <mutex.hpp>
+#include <cerrno>
+
+namespace purefs::fs
+{
+ namespace internal
+ {
+ struct inotify_container
+ {
+ std::map<std::string, internal::notifier::item_it> items;
+ };
+ } // namespace internal
+ inotify::inotify(std::shared_ptr<sys::Service> svc, std::shared_ptr<internal::notifier> notifier)
+ : m_svc(svc), m_notify(notifier), m_evlist(std::make_unique<internal::inotify_container>()),
+ m_lock(std::make_unique<cpp_freertos::MutexRecursive>())
+ {}
+
+ inotify::~inotify()
+ {
+ const auto notifier = m_notify.lock();
+ if (!notifier) {
+ LOG_ERROR("Unable lock notifier");
+ }
+ const auto svc = m_svc.lock();
+ if (!svc) {
+ LOG_ERROR("Unable lock service");
+ }
+ for (const auto &[_, val] : m_evlist->items) {
+ notifier->unregister_path(val);
+ }
+ }
+
+ int inotify::add_watch(std::string_view monitored_path, inotify_flags event_mask)
+ {
+ const auto notifier = m_notify.lock();
+ if (!notifier) {
+ LOG_ERROR("Unable lock notifier");
+ return -ENXIO;
+ }
+ const auto svc = m_svc.lock();
+ if (!svc) {
+ LOG_ERROR("Unable lock service");
+ return -ENXIO;
+ }
+ auto it = notifier->register_path(monitored_path, svc, event_mask);
+ if (!it) {
+ LOG_ERROR("Unable to register path");
+ return -EIO;
+ }
+ cpp_freertos::LockGuard _lck(*m_lock);
+ m_evlist->items.emplace(std::make_pair(std::string(monitored_path), *it));
+ return {};
+ }
+
+ int inotify::rm_watch(std::string_view monitored_path)
+ {
+ const auto notifier = m_notify.lock();
+ if (!notifier) {
+ LOG_ERROR("Unable lock notifier");
+ return -ENXIO;
+ }
+ const auto svc = m_svc.lock();
+ if (!svc) {
+ LOG_ERROR("Unable lock service");
+ return -ENXIO;
+ }
+ cpp_freertos::LockGuard _lck(*m_lock);
+ auto it = m_evlist->items.find(std::string(monitored_path));
+ if (it == std::end(m_evlist->items)) {
+ LOG_ERROR("Unable to find registered path %s", std::string(monitored_path).c_str());
+ return -ENOENT;
+ }
+ notifier->unregister_path(it->second);
+ m_evlist->items.erase(it);
+ return {};
+ }
+} // namespace purefs::fs
A module-vfs/src/purefs/fs/notifier.cpp => module-vfs/src/purefs/fs/notifier.cpp +115 -0
@@ 0,0 1,115 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include <purefs/fs/notifier.hpp>
+#include <purefs/fs/inotify_message.hpp>
+#include <functional>
+#include <Service/Service.hpp>
+#include <purefs/fs/inotify_message.hpp>
+#include <purefs/fs/thread_local_cwd.hpp>
+#include <log/log.hpp>
+
+namespace purefs::fs::internal
+{
+ namespace
+ {
+ void for_path(std::string_view path, std::function<void(std::string_view)> fun)
+ {
+ constexpr auto sep = '/';
+ for (auto it = (path.back() == sep) ? (path.size() - 1) : (path.size()); (it && it != std::string::npos);
+ it = path.rfind(sep, it - 1))
+ fun(path.substr(0, it));
+ }
+ std::string absolute_path(std::string_view path)
+ {
+ using namespace std::string_literals;
+ std::string ret;
+ if (!path.empty() && path[0] != '/') {
+ ret = std::string(internal::get_thread_local_cwd_path()) + "/"s + std::string(path);
+ }
+ else {
+ ret = std::string(path);
+ }
+ if (!ret.empty() && ret.back() == '/') {
+ ret.pop_back();
+ }
+ return ret;
+ }
+ } // namespace
+ notifier::notifier() : m_lock(std::make_unique<cpp_freertos::MutexRecursive>())
+ {}
+ notifier::~notifier()
+ {}
+ auto notifier::register_path(std::string_view path, std::shared_ptr<sys::Service> owner, inotify_flags flags)
+ -> std::optional<item_it>
+ {
+ cpp_freertos::LockGuard _lck(*m_lock);
+ const auto abspath = absolute_path(path);
+ // # Check if it is already registered for same path
+ const auto range = m_events.equal_range(abspath);
+ for (auto i = range.first; i != range.second; ++i) {
+ if (i->second.service.lock() == owner) {
+ return std::nullopt;
+ }
+ }
+ return m_events.emplace(std::make_pair(abspath, service_item(owner, flags)));
+ }
+ auto notifier::unregister_path(item_it item) -> void
+ {
+ cpp_freertos::LockGuard _lck(*m_lock);
+ m_events.erase(item);
+ }
+ auto notifier::notify(int fd, inotify_flags mask) const -> void
+ {
+ cpp_freertos::LockGuard _lck(*m_lock);
+ const auto fname_it = m_fd_map.find(fd);
+ if (fname_it != std::end(m_fd_map)) {
+ notify(fname_it->second.path, mask);
+ }
+ }
+ void notifier::notify(std::string_view path, std::string_view path_prv, inotify_flags mask) const
+ {
+ cpp_freertos::LockGuard _lck(*m_lock);
+ const auto abs_path = absolute_path(path);
+ const auto abs_path_prv = absolute_path(path_prv);
+ for_path(abs_path, [this, abs_path, abs_path_prv, mask](std::string_view path) {
+ const auto range = m_events.equal_range(std::string(path));
+ for (auto i = range.first; i != range.second; ++i) {
+ if (i->second.subscribed_events && mask) {
+ auto svc = i->second.service.lock();
+ if (svc) {
+ send_notification(svc, mask, abs_path, abs_path_prv);
+ }
+ }
+ }
+ });
+ }
+ auto notifier::notify_open(std::string_view path, int fd, bool ro) const -> void
+ {
+ cpp_freertos::LockGuard _lck(*m_lock);
+ m_fd_map.emplace(std::make_pair(fd, path_item(path, ro)));
+ notify(path, inotify_flags::open);
+ }
+ auto notifier::notify_close(int fd) const -> void
+ {
+ cpp_freertos::LockGuard _lck(*m_lock);
+ const auto fname_it = m_fd_map.find(fd);
+ if (fname_it != std::end(m_fd_map)) {
+ notify(fname_it->first,
+ fname_it->second.read_only ? inotify_flags::close_nowrite : inotify_flags::close_write);
+ m_fd_map.erase(fname_it);
+ }
+ }
+ auto notifier::send_notification(std::shared_ptr<sys::Service> svc,
+ inotify_flags flags,
+ std::string_view name,
+ std::string_view name_dst) const -> void
+ {
+ if (svc->GetHandle() != cpp_freertos::Thread::GetCurrentThreadHandle()) {
+ auto msg = std::make_shared<message::inotify>(flags, name, name_dst);
+ svc->bus.sendUnicast(std::move(msg), svc->GetName());
+ }
+ else {
+ LOG_WARN("Sent notification to the same thread is forbidded");
+ }
+ }
+} // namespace purefs::fs::internal
M module-vfs/tests/CMakeLists.txt => module-vfs/tests/CMakeLists.txt +17 -0
@@ 22,6 22,8 @@ add_catch2_executable(
NAME vfs-core-fs
SRCS
${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_core.cpp
+ INCLUDE
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include/internal
LIBS
module-vfs
)
@@ 38,6 40,8 @@ add_catch2_executable(
NAME vfs-littlefs
SRCS
${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_littlefs.cpp
+ INCLUDE
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include/internal
LIBS
module-vfs
DEPS
@@ 48,12 52,25 @@ add_catch2_executable(
NAME vfs-dualmount
SRCS
${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_dualmount.cpp
+ INCLUDE
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include/internal
+
LIBS
module-vfs
DEPS
${LITTLEFS_IMAGE}
)
+add_catch2_executable(
+ NAME vfs-inotify
+ SRCS
+ ${CMAKE_CURRENT_LIST_DIR}/unittest_filesystem_inotify.cpp
+ LIBS
+ module-vfs
+ INCLUDE
+ ${CMAKE_CURRENT_SOURCE_DIR}/../include/internal
+)
+
# prepare test assets
set(ASSETS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/test_dir")
set(ASSETS_TARGET_DIR "${CMAKE_BINARY_DIR}/module-vfs/test_dir")
A module-vfs/tests/unittest_filesystem_inotify.cpp => module-vfs/tests/unittest_filesystem_inotify.cpp +168 -0
@@ 0,0 1,168 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#define CATCH_CONFIG_MAIN
+#include <catch2/catch.hpp>
+#include <purefs/fs/notifier.hpp>
+#include <purefs/fs/inotify_message.hpp>
+
+namespace purefs::fs
+{
+
+ struct notifier_mock final : public internal::notifier
+ {
+ virtual ~notifier_mock() = default;
+ auto send_notification(std::shared_ptr<sys::Service> svc,
+ inotify_flags flags,
+ std::string_view name,
+ std::string_view name_dst) const -> void override
+ {
+ messages.emplace_back(flags, name, name_dst);
+ xsvc.push_back(svc.get());
+ }
+ mutable std::vector<message::inotify> messages;
+ mutable std::vector<sys::Service *> xsvc;
+ };
+} // namespace purefs::fs
+
+namespace sys
+{
+ class Service
+ {};
+} // namespace sys
+
+TEST_CASE("Notifier base class test")
+{
+ using namespace purefs::fs;
+ auto svc = std::make_shared<sys::Service>();
+ notifier_mock notify;
+ notify.register_path("/sys/ala",
+ svc,
+ inotify_flags::open | inotify_flags::close_nowrite | inotify_flags::close_write |
+ inotify_flags::attrib | inotify_flags::move_src | inotify_flags::move_dst);
+ SECTION("open and close simple")
+ {
+ notify.notify_open("/sys/ala", 77, true);
+ notify.notify_close(77);
+ REQUIRE(notify.messages.size() == 2);
+ REQUIRE(notify.messages[0].name == "/sys/ala");
+ REQUIRE(notify.messages[0].name_prev.empty());
+ REQUIRE((notify.messages[0].flags && inotify_flags::open));
+ REQUIRE(notify.messages[1].name == "/sys/ala");
+ REQUIRE(notify.messages[1].name_prev.empty());
+ REQUIRE((notify.messages[1].flags && inotify_flags::close_nowrite));
+ notify.messages.clear();
+ }
+ SECTION("open and close pairing")
+ {
+ notify.notify_open("/sys/ala/1", 100, true);
+ notify.notify_open("/sys/ala/2", 200, false);
+ notify.notify_open("/sys/ala/3", 300, true);
+ REQUIRE(notify.messages.size() == 3);
+ notify.notify(200, inotify_flags::attrib);
+ REQUIRE(notify.messages.size() == 4);
+ notify.notify_close(200);
+ REQUIRE(notify.messages.size() == 5);
+ notify.notify_close(200);
+ REQUIRE(notify.messages.size() == 5);
+ REQUIRE(notify.messages[0].name == "/sys/ala/1");
+ REQUIRE((notify.messages[0].flags && inotify_flags::open));
+ REQUIRE(notify.messages[1].name == "/sys/ala/2");
+ REQUIRE((notify.messages[1].flags && inotify_flags::open));
+ REQUIRE(notify.messages[2].name == "/sys/ala/3");
+ REQUIRE((notify.messages[2].flags && inotify_flags::open));
+ REQUIRE(notify.messages[3].name == "/sys/ala/2");
+ REQUIRE((notify.messages[3].flags && inotify_flags::attrib));
+ REQUIRE(notify.messages[4].name == "/sys/ala/2");
+ REQUIRE((notify.messages[4].flags && inotify_flags::close_write));
+ notify.messages.clear();
+ notify.notify_close(100);
+ notify.notify_close(300);
+ REQUIRE(notify.messages.size() == 2);
+ REQUIRE(notify.messages[0].name == "/sys/ala/1");
+ REQUIRE((notify.messages[0].flags && inotify_flags::close_nowrite));
+ REQUIRE(notify.messages[1].name == "/sys/ala/3");
+ REQUIRE((notify.messages[1].flags && inotify_flags::close_nowrite));
+ notify.notify_close(300);
+ notify.notify_close(300);
+ REQUIRE(notify.messages.size() == 2);
+ notify.messages.clear();
+ }
+ SECTION("Other notifies tests")
+ {
+ notify.notify("/sys/ala/100", "/sys/ala/555", inotify_flags::move_src);
+ notify.notify("/sys/ala/555", "/sys/ala/100", inotify_flags::move_dst);
+ notify.notify("/sys/ala/999/989", inotify_flags::attrib);
+ REQUIRE(notify.messages.size() == 3);
+ REQUIRE(notify.messages[0].name == "/sys/ala/100");
+ REQUIRE(notify.messages[0].name_prev == "/sys/ala/555");
+ REQUIRE((notify.messages[0].flags && inotify_flags::move_src));
+ REQUIRE(notify.messages[1].name == "/sys/ala/555");
+ REQUIRE(notify.messages[1].name_prev == "/sys/ala/100");
+ REQUIRE((notify.messages[1].flags && inotify_flags::move_dst));
+ }
+}
+
+TEST_CASE("Filtering test")
+{
+ using namespace purefs::fs;
+ SECTION("Different mask for services")
+ {
+ notifier_mock notify;
+ auto svc1 = std::make_shared<sys::Service>();
+ auto svc2 = std::make_shared<sys::Service>();
+ notify.register_path(
+ "/sys/path1", svc1, inotify_flags::open | inotify_flags::close_nowrite | inotify_flags::close_write);
+ notify.register_path("/sys/path1/", svc2, inotify_flags::open | inotify_flags::close_write);
+ notify.notify_open("/sys/path1/file.txt", 100, false);
+ notify.notify_open("/sys/path1/file1.txt", 200, true);
+ REQUIRE(notify.messages.size() == 4);
+ notify.notify_close(100);
+ REQUIRE(notify.messages.size() == 6);
+ notify.notify_close(200);
+ REQUIRE(notify.messages.size() == 7);
+ // Checking values in the queue
+ REQUIRE(notify.messages[0].name == "/sys/path1/file.txt");
+ REQUIRE((notify.messages[0].flags && inotify_flags::open));
+ REQUIRE(notify.xsvc[0] == svc1.get());
+ REQUIRE(notify.messages[1].name == "/sys/path1/file.txt");
+ REQUIRE((notify.messages[1].flags && inotify_flags::open));
+ REQUIRE(notify.xsvc[1] == svc2.get());
+ REQUIRE(notify.messages[2].name == "/sys/path1/file1.txt");
+ REQUIRE((notify.messages[2].flags && inotify_flags::open));
+ REQUIRE(notify.xsvc[2] == svc1.get());
+ REQUIRE(notify.messages[3].name == "/sys/path1/file1.txt");
+ REQUIRE((notify.messages[3].flags && inotify_flags::open));
+ REQUIRE(notify.xsvc[3] == svc2.get());
+ REQUIRE(notify.messages[4].name == "/sys/path1/file.txt");
+ REQUIRE((notify.messages[4].flags && inotify_flags::close_write));
+ REQUIRE(notify.xsvc[4] == svc1.get());
+ REQUIRE(notify.messages[5].name == "/sys/path1/file.txt");
+ REQUIRE((notify.messages[5].flags && inotify_flags::close_write));
+ REQUIRE(notify.xsvc[5] == svc2.get());
+ REQUIRE(notify.messages[6].name == "/sys/path1/file1.txt");
+ REQUIRE((notify.messages[6].flags && inotify_flags::close_nowrite));
+ REQUIRE(notify.xsvc[6] == svc1.get());
+ }
+ SECTION("Different paths for services")
+ {
+ notifier_mock notify;
+ auto svc1 = std::make_shared<sys::Service>();
+ auto svc2 = std::make_shared<sys::Service>();
+ notify.register_path("/sys/path1", svc1, inotify_flags::attrib);
+ notify.register_path("/sys/path2", svc2, inotify_flags::attrib);
+ notify.notify("/sys/path1/file.txt", inotify_flags::attrib);
+ REQUIRE(notify.messages.size() == 1);
+ notify.notify("/sys/path1/file2.txt", inotify_flags::attrib);
+ REQUIRE(notify.messages.size() == 2);
+ notify.notify("/sys/path3", inotify_flags::attrib);
+ REQUIRE(notify.messages.size() == 2);
+ notify.notify("/sys/path2/", inotify_flags::attrib);
+ REQUIRE(notify.messages.size() == 3);
+ REQUIRE(notify.messages[0].name == "/sys/path1/file.txt");
+ REQUIRE(notify.xsvc[0] == svc1.get());
+ REQUIRE(notify.messages[1].name == "/sys/path1/file2.txt");
+ REQUIRE(notify.xsvc[1] == svc1.get());
+ REQUIRE(notify.messages[2].name == "/sys/path2");
+ REQUIRE(notify.xsvc[2] == svc2.get());
+ }
+}
M test/pytest/service-desktop/test_messages.py => test/pytest/service-desktop/test_messages.py +11 -3
@@ 4,7 4,6 @@
import pytest
from harness.interface.defs import status
-
MESSAGES_PAGE_SIZE = 4
@@ 19,6 18,15 @@ def test_get_messages_without_pagination(harness):
messages = ret["body"]["entries"]
messages_count = len(messages)
assert messages_count == limit
+ message_types = [1, 2, 4, 8, 16, 18, 255]
+ for message in messages:
+ assert type(message["contactID"]) == int
+ assert type(message["messageBody"]) == str
+ assert type(message["messageID"]) == int
+ assert type(message["messageType"]) == int
+ assert type(message["createdAt"]) == int
+ assert type(message["threadID"]) == int
+ assert message["messageType"] in message_types
@pytest.mark.service_desktop_test
@@ 61,7 69,7 @@ def test_get_all_messages(harness):
if "nextPage" in ret["body"]:
offset = ret["body"]["nextPage"]["offset"]
- messages_left_count = count - len(all_messages)
+ messages_left_count = count - len(all_messages)
body = {"category": "message", "limit": messages_left_count, "offset": offset}
ret = harness.endpoint_request("messages", "get", body)
@@ 136,7 144,7 @@ def test_get_all_messages_by_thread_id(harness):
if "nextPage" in ret["body"]:
offset = ret["body"]["nextPage"]["offset"]
- messages_left_count = messages_by_thread_id_count - len(all_messages)
+ messages_left_count = messages_by_thread_id_count - len(all_messages)
body = {"category": "message", "threadID": thread_id, "limit": messages_left_count, "offset": offset}
ret = harness.endpoint_request("messages", "get", body)
M test/pytest/service-desktop/test_templates.py => test/pytest/service-desktop/test_templates.py +4 -0
@@ 83,6 83,10 @@ class TemplatesTester:
assert ret["status"] == status["OK"]
assert ret["body"]["totalCount"] == count
assert len(ret["body"]["entries"]) == number_of_requested_templates
+ for template in ret["body"]["entries"]:
+ assert type(template["lastUsedAt"]) == int
+ assert type(template["templateBody"]) == str
+ assert type(template["templateID"]) == int
def test_changing_template_body(self):
test_passed = False
M test/pytest/service-desktop/test_threads.py => test/pytest/service-desktop/test_threads.py +13 -0
@@ 12,6 12,19 @@ def test_threads(harness):
ret = harness.endpoint_request("messages", "get", body)
assert ret["status"] == status["OK"]
+ # Check if all fields are present and have proper type
+ message_types = [1, 2, 4, 8, 16, 18, 255]
+ for thread in ret["body"]["entries"]:
+ assert type(thread["contactID"]) == int
+ assert type(thread["isUnread"]) == bool
+ assert type(thread["lastUpdatedAt"]) == int
+ assert type(thread["messageCount"]) == int
+ assert type(thread["messageSnippet"]) == str
+ assert type(thread["messageType"]) == int
+ assert type(thread["numberID"]) == int
+ assert type(thread["threadID"]) == int
+ assert thread["messageType"] in message_types
+
# getting a number of threads
number_of_requested_threads = 3
if ret["body"]["totalCount"] < number_of_requested_threads:
M third-party/CMakeLists.txt => third-party/CMakeLists.txt +6 -0
@@ 5,3 5,9 @@ add_subdirectory(microtar)
add_subdirectory(date)
add_subdirectory(pugixml)
add_subdirectory(sml)
+add_subdirectory(taglib)
+add_subdirectory(minimp3)
+add_subdirectory(tinyexpr)
+add_subdirectory(parallel-hashmap)
+add_subdirectory(protobuf)
+
A third-party/minimp3/CMakeLists.txt => third-party/minimp3/CMakeLists.txt +7 -0
@@ 0,0 1,7 @@
+add_library(minimp3 INTERFACE)
+add_library(minimp3::minimp3 ALIAS minimp3)
+
+target_include_directories(minimp3
+ INTERFACE
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/minimp3>
+)
A third-party/minimp3/minimp3 => third-party/minimp3/minimp3 +1 -0
@@ 0,0 1,1 @@
+Subproject commit 446d3a32d281eb1dcae7726ba0ff594695182908
A third-party/parallel-hashmap/CMakeLists.txt => third-party/parallel-hashmap/CMakeLists.txt +3 -0
@@ 0,0 1,3 @@
+set(CMAKE_POLICY_DEFAULT_CMP0076 NEW)
+
+add_subdirectory(src)
A third-party/parallel-hashmap/src => third-party/parallel-hashmap/src +1 -0
@@ 0,0 1,1 @@
+Subproject commit 1f2671ff0a12710f19c92080693c857f918bda88
A third-party/protobuf/CMakeLists.txt => third-party/protobuf/CMakeLists.txt +3 -0
@@ 0,0 1,3 @@
+add_subdirectory(src/cmake)
+set_target_properties(libprotobuf PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
+target_compile_options(libprotobuf-lite PRIVATE -w)
A third-party/protobuf/src => third-party/protobuf/src +1 -0
@@ 0,0 1,1 @@
+Subproject commit 2555e35fc68441e76618621be0815fe343201fdf
A third-party/taglib => third-party/taglib +1 -0
@@ 0,0 1,1 @@
+Subproject commit 88ec9107c210eb19aaef4e1153460a754578197b
A third-party/tinyexpr/CMakeLists.txt => third-party/tinyexpr/CMakeLists.txt +14 -0
@@ 0,0 1,14 @@
+
+add_library(tinyexpr)
+target_sources(tinyexpr
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tinyexpr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/tinyexpr.h
+)
+
+target_include_directories(tinyexpr
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
+)
+add_library(tinyexpr::tinyexpr ALIAS tinyexpr)
+
A third-party/tinyexpr/src => third-party/tinyexpr/src +1 -0
@@ 0,0 1,1 @@
+Subproject commit 2ef22d228f8760561b8f485f0997ca07fafd0f12