Separate rotation implementation from app-core-cpp 21/305121/7
authorHwankyu Jhun <h.jhun@samsung.com>
Mon, 29 Jan 2024 01:56:15 +0000 (10:56 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Tue, 30 Jan 2024 00:38:53 +0000 (09:38 +0900)
The AppCoreRotation class is added to separate the implmenetation
related to using sensor library from the app-core-cpp.
The AppCoreUiBase and the AppCoreMultiWindowBase use the AppCoreRotation.

Change-Id: I0e59ed6c4411b7fb3477c268a8a51a3d59a19c42
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
18 files changed:
CMakeLists.txt
packaging/app-core.spec
tizen-cpp/CMakeLists.txt
tizen-cpp/app-core-cpp/CMakeLists.txt
tizen-cpp/app-core-cpp/app_core_base.cc
tizen-cpp/app-core-cpp/app_core_base.hh
tizen-cpp/app-core-multi-window-cpp/CMakeLists.txt
tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.cc
tizen-cpp/app-core-multi-window-cpp/app_core_multi_window_base.hh
tizen-cpp/app-core-rotation-cpp/CMakeLists.txt [new file with mode: 0644]
tizen-cpp/app-core-rotation-cpp/app-core-rotation-cpp.pc.in [new file with mode: 0644]
tizen-cpp/app-core-rotation-cpp/app_core_rotation.cc [new file with mode: 0644]
tizen-cpp/app-core-rotation-cpp/app_core_rotation.hh [new file with mode: 0644]
tizen-cpp/app-core-ui-cpp/CMakeLists.txt
tizen-cpp/app-core-ui-cpp/app_core_ui_base.cc
tizen-cpp/app-core-ui-cpp/app_core_ui_base.hh
unittests/CMakeLists.txt
unittests/app_core_base_test.cc

index 36b2ac0..c52b31b 100644 (file)
@@ -17,6 +17,7 @@ SET(TARGET_APP_CORE_CPP "app-core-cpp")
 SET(TARGET_APP_CORE_UI_CPP "app-core-ui-cpp")
 SET(TARGET_APP_CORE_EFL_CPP "app-core-efl-cpp")
 SET(TARGET_APP_CORE_MULTI_WINDOW_CPP "app-core-multi-window-cpp")
+SET(TARGET_APP_CORE_ROTATION_CPP "app-core-rotation-cpp")
 
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs -pie" )
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
index 7a5e715..6524eac 100644 (file)
@@ -261,6 +261,7 @@ install -m 0644 %{name}.zip %{buildroot}%{_datadir}/gcov/
 %{_libdir}/libappcore-common.so.*
 
 %{_libdir}/libapp-core-cpp.so.*
+%{_libdir}/libapp-core-rotation-cpp.so.*
 %license LICENSE
 
 %files common-devel
@@ -281,6 +282,10 @@ install -m 0644 %{name}.zip %{buildroot}%{_datadir}/gcov/
 %{_libdir}/libapp-core-cpp.so
 %{_libdir}/pkgconfig/app-core-cpp.pc
 
+%{_includedir}/appcore_cpp/app_core_rotation.hh
+%{_libdir}/libapp-core-rotation-cpp.so
+%{_libdir}/pkgconfig/app-core-rotation-cpp.pc
+
 %files ui
 %manifest %{name}.manifest
 %{_libdir}/libappcore-ui.so.*
index 0814703..569335c 100644 (file)
@@ -2,3 +2,4 @@ ADD_SUBDIRECTORY(app-core-efl-cpp)
 ADD_SUBDIRECTORY(app-core-multi-window-cpp)
 ADD_SUBDIRECTORY(app-core-cpp)
 ADD_SUBDIRECTORY(app-core-ui-cpp)
+ADD_SUBDIRECTORY(app-core-rotation-cpp)
index 6f427fb..0534880 100644 (file)
@@ -18,7 +18,6 @@ APPLY_PKG_CONFIG(${TARGET_APP_CORE_CPP} PUBLIC
   BUNDLE_DEPS
   DLOG_DEPS
   GIO_2_DEPS
-  SENSOR_DEPS
   TTRACE_DEPS
   VCONF_DEPS
 )
index 2e14d8a..021435e 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/limits.h>
 #include <locale.h>
 #include <malloc.h>
-#include <sensor_internal.h>
 #include <signal.h>
 #include <stdbool.h>
 #include <sys/stat.h>
@@ -71,16 +70,7 @@ internal::SigtermHandler sigterm_handler;
 constexpr const char PATH_LOCALE[] = "locale";
 constexpr int SQLITE_FLUSH_MAX = 1024 * 1024;
 
-struct Rotation {
-  int conn;
-  int lock;
-  int ref;
-  tizen_cpp::AppCoreBase::RotationState rm;
-  int charger_status;
-  bool initialized;
-};
-
-Rotation __rotation;
+AppCoreBase::RotationState __rotation_state = AppCoreBase::ROTATION_UNKNOWN;
 AppCoreBase::DisplayState __display_state = AppCoreBase::DISPLAY_STATE_UNKNOWN;
 
 }  // namespace
@@ -98,8 +88,6 @@ class AppCoreBase::Impl : public SuspendEvent::IEventListener {
   explicit Impl(AppCoreBase* parent) : parent_(parent) {}
 
  private:
-  void UnregisterRotationChangedEvent();
-  void RegisterRotationChangedEvent();
   std::string GetAppName(const char* appid);
   std::string GetLocaleResourceDir();
   void UpdateLang();
@@ -134,15 +122,9 @@ class AppCoreBase::Impl : public SuspendEvent::IEventListener {
   static gboolean InvokeLangChangeCb(gpointer data);
   static void OnLowBatteryCb(keynode_t* key, void* data);
   static void OnTimeZoneChangedCb(keynode_t* key, void* data);
-  static void LockCb(keynode_t* node, void* user_data);
-  static void AutoRotationChangedCb(sensor_t sensor, unsigned int event_type,
-      sensor_data_t* data, void* user_data);
   static void LanguageChangeCb(keynode_t* key, void* data);
   static void RegionChangeCb(keynode_t* key, void* data);
   static void LowMemoryCb(keynode_t* key, void* data);
-  void InitRotation();
-  void FiniRotation();
-  RotationState GetRm(sensor_data_t data);
   void VerifyLanguage();
   void SetDefaultEvents();
   void UnsetDefaultEvents();
@@ -246,27 +228,6 @@ void AppCoreBase::Impl::OnFreezerSignal() {
   }
 }
 
-AppCoreBase::RotationState AppCoreBase::Impl::GetRm(sensor_data_t data) {
-  if (data.value_count <= 0) {
-    _E("Failed to get sensor data");
-    return ROTATION_UNKNOWN;
-  }
-
-  int event = data.values[0];
-  switch (event) {
-  case AUTO_ROTATION_DEGREE_0:
-    return ROTATION_PORTRAIT_NORMAL;
-  case AUTO_ROTATION_DEGREE_90:
-    return ROTATION_LANDSCAPE_NORMAL;
-  case AUTO_ROTATION_DEGREE_180:
-    return ROTATION_PORTRAIT_REVERSE;
-  case AUTO_ROTATION_DEGREE_270:
-    return ROTATION_LANDSCAPE_REVERSE;
-  default:
-    return ROTATION_UNKNOWN;
-  }
-}
-
 void AppCoreBase::Impl::InitSuspend() {
   suspend_event_.reset(new SuspendEvent(this));
 }
@@ -324,113 +285,6 @@ void AppCoreBase::Impl::LowMemoryCb(keynode_t* key, void* user_data) {
     malloc_trim(0);
 }
 
-void AppCoreBase::Impl::LockCb(keynode_t* node, void* user_data) {
-  AppCoreBase::RotationState rm;
-  AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
-
-  __rotation.lock = !vconf_keynode_get_bool(node);
-  if (__rotation.lock) {
-    _D("Rotation locked");
-    rm = ROTATION_PORTRAIT_NORMAL;
-  } else {
-    _D("Rotation unlocked");
-    sensor_data_t data;
-    bool r = sensord_get_data(__rotation.conn, AUTO_ROTATION_SENSOR, &data);
-    if (!r) {
-      _E("Failed to get sensor data");
-      return;
-    }
-
-    rm = base->impl_->GetRm(data);
-    if (rm == ROTATION_UNKNOWN) {
-      _E("Unknown mode");
-      return;
-    }
-  }
-
-  if (__rotation.rm == rm)
-    return;
-
-  _D("Rotation: %d -> %d", __rotation.rm, rm);
-  __rotation.rm = rm;
-  base->impl_->InvokeCallback(__rotation.rm,
-      IEvent::Type::DEVICE_ORIENTATION_CHANGED);
-}
-
-void AppCoreBase::Impl::AutoRotationChangedCb(sensor_t sensor,
-    unsigned int event_type, sensor_data_t* data, void* user_data) {
-  if (data == nullptr)
-    return;
-
-  if (__rotation.lock)
-    return;
-
-  if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT)
-    return;
-
-  AppCoreBase* base = reinterpret_cast<AppCoreBase*>(user_data);
-  AppCoreBase::RotationState rm = base->impl_->GetRm(*data);
-  if (rm == ROTATION_UNKNOWN) {
-    _E("Unknown mode");
-    return;
-  }
-
-  _D("Rotation: %d -> %d", __rotation.rm, rm);
-  __rotation.rm = rm;
-  base->impl_->InvokeCallback(__rotation.rm,
-      IEvent::Type::DEVICE_ORIENTATION_CHANGED);
-}
-
-void AppCoreBase::Impl::InitRotation() {
-  if (__rotation.initialized)
-    return;
-
-  sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
-  __rotation.conn = sensord_connect(sensor);
-  if (__rotation.conn < 0) {
-    _E("Failed to connect sensord");
-    return;
-  }
-
-  bool r = sensord_register_event(__rotation.conn,
-      AUTO_ROTATION_CHANGE_STATE_EVENT, SENSOR_INTERVAL_NORMAL, 0,
-      AutoRotationChangedCb, parent_);
-  if (!r) {
-    _E("Failed to register auto rotation change event");
-    sensord_disconnect(__rotation.conn);
-    return;
-  }
-
-  r = sensord_start(__rotation.conn, 0);
-  if (!r) {
-    _E("Failed to start sensord");
-    sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
-    sensord_disconnect(__rotation.conn);
-    return;
-  }
-
-  int lock = 0;
-  vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
-  vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb,
-      parent_);
-
-  __rotation.lock = !lock;
-  __rotation.initialized = true;
-}
-
-void AppCoreBase::Impl::FiniRotation() {
-  if (!__rotation.initialized)
-    return;
-
-  vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, LockCb);
-  sensord_unregister_event(__rotation.conn, AUTO_ROTATION_CHANGE_STATE_EVENT);
-  sensord_stop(__rotation.conn);
-  sensord_disconnect(__rotation.conn);
-
-  __rotation.lock = 0;
-  __rotation.initialized = false;
-}
-
 void AppCoreBase::Impl::VerifyLanguage() {
   const char* env_lang = getenv("LANG");
   if (env_lang == nullptr)
@@ -648,20 +502,6 @@ void AppCoreBase::Impl::OnTimeZoneChangedCb(keynode_t* key, void* data) {
   }
 }
 
-void AppCoreBase::Impl::UnregisterRotationChangedEvent() {
-  if (!__rotation.ref)
-    return;
-
-  __rotation.ref--;
-  if (__rotation.ref == 0) FiniRotation();
-}
-
-void AppCoreBase::Impl::RegisterRotationChangedEvent() {
-  if (__rotation.ref == 0) InitRotation();
-
-  __rotation.ref++;
-}
-
 int AppCoreBase::OnSetEvent(IEvent::Type event) {
   switch (event) {
   case IEvent::Type::LOW_BATTERY:
@@ -669,7 +509,6 @@ int AppCoreBase::OnSetEvent(IEvent::Type event) {
         impl_->OnLowBatteryCb, this);
     break;
   case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
-    impl_->RegisterRotationChangedEvent();
     break;
   case IEvent::Type::SUSPENDED_STATE_CHANGE:
     break;
@@ -687,7 +526,6 @@ int AppCoreBase::OnUnsetEvent(IEvent::Type event) {
         impl_->OnLowBatteryCb);
     break;
   case IEvent::Type::DEVICE_ORIENTATION_CHANGED:
-    impl_->UnregisterRotationChangedEvent();
     break;
   case IEvent::Type::SUSPENDED_STATE_CHANGE:
     break;
@@ -759,10 +597,11 @@ void AppCoreBase::FlushMemory() {
 }
 
 AppCoreBase::RotationState AppCoreBase::GetRotationState() {
-  if (!__rotation.ref)
-    throw std::runtime_error("invalid rotation state");
+  return __rotation_state;
+}
 
-  return __rotation.rm;
+void AppCoreBase::SetRotationState(RotationState state) {
+  __rotation_state = state;
 }
 
 bool AppCoreBase::IsBgAllowed() {
index 815c6ff..d8196a0 100644 (file)
@@ -105,6 +105,7 @@ class EXPORT_API AppCoreBase : public IAppCore, public IMainLoop {
   static int EnableWatchdog();
   static int DisableWatchdog();
   static int KickWatchdog();
+  static void SetRotationState(RotationState state);
 
  protected:
   void SetCoreDelegator(IAppCore* delegator);
index 3cf26f2..65f0299 100644 (file)
@@ -13,6 +13,7 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP} PUBLIC
 
 TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP} PUBLIC
   ${TARGET_APP_CORE_CPP}
+  ${TARGET_APP_CORE_ROTATION_CPP}
   "-L${LIB_INSTALL_DIR}/hal")
 
 SET_TARGET_PROPERTIES(${TARGET_APP_CORE_MULTI_WINDOW_CPP}
index 86261da..f69eca0 100644 (file)
  * limitations under the License.
  */
 
+#include "app-core-multi-window-cpp/app_core_multi_window_base.hh"
+
 #include <list>
 #include <map>
 #include <stdexcept>
 #include <string>
+#include <utility>
 
-#include "app-core-multi-window-cpp/app_core_multi_window_base.hh"
+#include "app-core-rotation-cpp/app_core_rotation.hh"
 #include "common/ecore_handler.hh"
 #include "common/log_private.hh"
 
@@ -39,13 +42,24 @@ class AppCoreMultiWindowBase::Context::Impl {
   AppCoreMultiWindowBase* app_;
 };
 
-class AppCoreMultiWindowBase::Impl {
+class AppCoreMultiWindowBase::Impl : public AppCoreRotation::IEventListener {
+ public:
+  explicit Impl(AppCoreMultiWindowBase* parent) : parent_(parent) {}
+
+ private:
+  void RotationInit();
+  void RotationShutdown();
+  void OnRotationChanged(int degree) override;
+
  private:
   friend class AppCoreMultiWindowBase;
+  AppCoreMultiWindowBase* parent_;
+
   std::shared_ptr<EcoreHandler> handler_;
   std::map<std::string, std::shared_ptr<Context::IFactory>> factory_map_;
   std::list<std::shared_ptr<Context>> contexts_;
   std::unique_ptr<EcoreHandler::ITrim> trim_;
+  std::unique_ptr<AppCoreRotation> rotation_;
 };
 
 AppCoreMultiWindowBase::Context::Context(std::string context_id,
@@ -115,7 +129,7 @@ AppCoreMultiWindowBase* AppCoreMultiWindowBase::Context::GetApp() {
 }
 
 AppCoreMultiWindowBase::AppCoreMultiWindowBase() :
-    impl_(std::make_unique<Impl>()) {}
+    impl_(std::make_unique<Impl>(this)) {}
 
 AppCoreMultiWindowBase::~AppCoreMultiWindowBase() = default;
 
@@ -306,4 +320,36 @@ AppCoreMultiWindowBase::GetContextFactory(const std::string& context_id) {
   return impl_->factory_map_[context_id];
 }
 
+void AppCoreMultiWindowBase::Impl::RotationInit() {
+  if (!rotation_) rotation_.reset(new AppCoreRotation(this));
+
+  rotation_->Init();
+}
+
+void AppCoreMultiWindowBase::Impl::RotationShutdown() {
+  if (rotation_) rotation_->Dispose();
+}
+
+void AppCoreMultiWindowBase::Impl::OnRotationChanged(int degree) {
+  AppCoreBase::SetRotationState(
+      static_cast<AppCoreBase::RotationState>(degree));
+  parent_->RaiseEvent(degree, IEvent::Type::DEVICE_ORIENTATION_CHANGED);
+}
+
+int AppCoreMultiWindowBase::OnSetEvent(IEvent::Type event) {
+  AppCoreBase::OnSetEvent(event);
+  if (event == IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+    impl_->RotationInit();
+
+  return 0;
+}
+
+int AppCoreMultiWindowBase::OnUnsetEvent(IEvent::Type event) {
+  AppCoreBase::OnUnsetEvent(event);
+  if (event == IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+    impl_->RotationShutdown();
+
+  return 0;
+}
+
 }  // namespace tizen_cpp
index d308f0b..8a502df 100644 (file)
@@ -94,6 +94,8 @@ class EXPORT_API AppCoreMultiWindowBase : public AppCoreBase, public IWindow {
   std::shared_ptr<Context::IFactory> GetContextFactory(
       const std::string& context_id);
   void Dispose() override;
+  int OnSetEvent(IEvent::Type event) override;
+  int OnUnsetEvent(IEvent::Type event) override;
 
  private:
   class Impl;
@@ -102,4 +104,4 @@ class EXPORT_API AppCoreMultiWindowBase : public AppCoreBase, public IWindow {
 
 }  // namespace tizen_cpp
 
-#endif  // TIZEN_CPP_APP_CORE_MULTI_WINDOW_CPP__APP_CORE_MULTI_WINDOW_BASE_HH_
+#endif  // TIZEN_CPP_APP_CORE_MULTI_WINDOW_CPP_APP_CORE_MULTI_WINDOW_BASE_HH_
diff --git a/tizen-cpp/app-core-rotation-cpp/CMakeLists.txt b/tizen-cpp/app-core-rotation-cpp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..de705a7
--- /dev/null
@@ -0,0 +1,33 @@
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} APP_CORE_ROTATION_CPP_SRCS)
+
+ADD_LIBRARY(${TARGET_APP_CORE_ROTATION_CPP} SHARED
+  ${APP_CORE_ROTATION_CPP_SRCS})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_ROTATION_CPP} PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/../)
+
+TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_ROTATION_CPP} PUBLIC
+  "-L${LIB_INSTALL_DIR}/hal")
+
+SET_TARGET_PROPERTIES(${TARGET_APP_CORE_ROTATION_CPP}
+  PROPERTIES SOVERSION ${MAJORVER})
+SET_TARGET_PROPERTIES(${TARGET_APP_CORE_ROTATION_CPP}
+  PROPERTIES VERSION ${FULLVER})
+
+APPLY_PKG_CONFIG(${TARGET_APP_CORE_ROTATION_CPP} PUBLIC
+  DLOG_DEPS
+  SENSOR_DEPS
+  VCONF_DEPS
+)
+
+CONFIGURE_FILE(${TARGET_APP_CORE_ROTATION_CPP}.pc.in
+  ${TARGET_APP_CORE_ROTATION_CPP}.pc @ONLY)
+INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_APP_CORE_ROTATION_CPP}.pc
+  DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+
+INSTALL(TARGETS ${TARGET_APP_CORE_ROTATION_CPP} DESTINATION ${LIB_INSTALL_DIR})
+INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION include/appcore_cpp
+  FILES_MATCHING
+  PATTERN "*_private.hh" EXCLUDE
+  PATTERN "*.hh")
diff --git a/tizen-cpp/app-core-rotation-cpp/app-core-rotation-cpp.pc.in b/tizen-cpp/app-core-rotation-cpp/app-core-rotation-cpp.pc.in
new file mode 100644 (file)
index 0000000..48c7bd5
--- /dev/null
@@ -0,0 +1,14 @@
+# Package Information for pkg-config
+
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDEDIR@
+
+Name: app-core-rotation-cpp
+Description: Tizen application core library for rotation event
+Version: @VERSION@
+Requires.private: dlog sensor vconf
+Libs: -L${libdir} -lapp-core-rotation-cpp
+Cflags: -I${includedir} -I${includedir}/appcore_cpp
+cppflags: I${includedir} -I${includedir}/appcore_cpp
diff --git a/tizen-cpp/app-core-rotation-cpp/app_core_rotation.cc b/tizen-cpp/app-core-rotation-cpp/app_core_rotation.cc
new file mode 100644 (file)
index 0000000..c6b08ba
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "app-core-rotation-cpp/app_core_rotation.hh"
+
+#include "common/log_private.hh"
+
+namespace tizen_cpp {
+
+AppCoreRotation::AppCoreRotation(IEventListener* listener)
+    : listener_(listener) {}
+
+AppCoreRotation::~AppCoreRotation() { Dispose(); }
+
+bool AppCoreRotation::Init() {
+  if (!disposed_) {
+    ref_++;
+    return true;
+  }
+
+  sensor_t sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
+  conn_ = sensord_connect(sensor);
+  if (conn_ < 0) {
+    _E("sensord_connect() is failed");
+    return false;
+  }
+
+  if (!sensord_register_event(conn_, AUTO_ROTATION_CHANGE_STATE_EVENT,
+                              SENSOR_INTERVAL_NORMAL, 0, SensorEventCb, this)) {
+    _E("sensord_register_event() is failed");
+    sensord_disconnect(conn_);
+    conn_ = 0;
+    return false;
+  }
+
+  if (!sensord_start(conn_, 0)) {
+    _E("sensord_start() is failed");
+    sensord_unregister_event(conn_, AUTO_ROTATION_CHANGE_STATE_EVENT);
+    sensord_disconnect(conn_);
+    conn_ = 0;
+    return false;
+  }
+
+  int lock = 0;
+  vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &lock);
+  vconf_notify_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, VconfCb,
+                           this);
+
+  lock_ = !lock;
+  ref_++;
+  disposed_ = false;
+  return true;
+}
+
+void AppCoreRotation::Dispose() {
+  if (disposed_) return;
+
+  ref_--;
+  if (ref_ > 0) return;
+
+  vconf_ignore_key_changed(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, VconfCb);
+  sensord_unregister_event(conn_, AUTO_ROTATION_CHANGE_STATE_EVENT);
+  sensord_stop(conn_);
+  sensord_disconnect(conn_);
+  conn_ = 0;
+  lock_ = 0;
+  disposed_ = true;
+}
+
+bool AppCoreRotation::IsLocked() const { return lock_; }
+
+int AppCoreRotation::GetDegree() const { return degree_; }
+
+void AppCoreRotation::SensorEventCb(sensor_t sensor, unsigned int event_type,
+                                    sensor_data_t* data, void* user_data) {
+  if (event_type != AUTO_ROTATION_CHANGE_STATE_EVENT) return;
+
+  auto self = static_cast<AppCoreRotation*>(user_data);
+  if (self->IsLocked()) return;
+
+  int degree = static_cast<int>(data->values[0]);
+  if (degree == static_cast<int>(AUTO_ROTATION_DEGREE_UNKNOWN)) return;
+
+  if (self->degree_ == degree) return;
+
+  _D("Rotation: %d -> %d", self->degree_, degree);
+  self->degree_ = degree;
+  self->listener_->OnRotationChanged(degree);
+}
+
+void AppCoreRotation::VconfCb(keynode_t* node, void* user_data) {
+  int degree;
+  auto self = static_cast<AppCoreRotation*>(user_data);
+  self->lock_ = !vconf_keynode_get_bool(node);
+  if (self->lock_) {
+    _D("Rotation locked");
+    degree = 0;
+  } else {
+    _D("Rotation unlocked");
+    sensor_data_t data;
+    if (!sensord_get_data(self->conn_, AUTO_ROTATION_CHANGE_STATE_EVENT,
+                          &data)) {
+      _E("sensord_get_data() is failed");
+      return;
+    }
+
+    degree = static_cast<int>(data.values[0]);
+    if (degree == static_cast<int>(AUTO_ROTATION_DEGREE_UNKNOWN)) return;
+  }
+
+  if (self->degree_ == degree) return;
+
+  _D("Rotation: %d -> %d", self->degree_, degree);
+  self->degree_ = degree;
+  self->listener_->OnRotationChanged(degree);
+}
+
+}  // namespace tizen_cpp
diff --git a/tizen-cpp/app-core-rotation-cpp/app_core_rotation.hh b/tizen-cpp/app-core-rotation-cpp/app_core_rotation.hh
new file mode 100644 (file)
index 0000000..4798436
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TIZEN_CPP_APP_CORE_ROTATION_CPP_APP_CORE_ROTATION_HH_
+#define TIZEN_CPP_APP_CORE_ROTATION_CPP_APP_CORE_ROTATION_HH_
+
+#include <sensor_internal.h>
+#include <vconf.h>
+
+#undef EXPORT_API
+#define EXPORT_API __attribute__((visibility("default")))
+
+namespace tizen_cpp {
+
+class EXPORT_API AppCoreRotation {
+ public:
+  class IEventListener {
+   public:
+    virtual ~IEventListener() = default;
+    virtual void OnRotationChanged(int degree) = 0;
+  };
+
+  explicit AppCoreRotation(IEventListener* listener);
+  ~AppCoreRotation();
+
+  bool Init();
+  void Dispose();
+
+  bool IsLocked() const;
+  int GetDegree() const;
+
+ private:
+  static void SensorEventCb(sensor_t sensor, unsigned int event_type,
+                            sensor_data_t* data, void* user_data);
+  static void VconfCb(keynode_t* node, void* user_data);
+
+ private:
+  bool disposed_ = true;
+  IEventListener* listener_;
+  int conn_ = 0;
+  int lock_ = 0;
+  uint32_t ref_ = 0;
+  int degree_ = 0;
+};
+
+}  // namespace tizen_cpp
+
+#endif  // TIZEN_CPP_APP_CORE_ROTATION_CPP_APP_CORE_ROTATION_HH_
index 6c52af8..2e5fa17 100644 (file)
@@ -14,6 +14,7 @@ TARGET_INCLUDE_DIRECTORIES(${TARGET_APP_CORE_UI_CPP} PUBLIC
 
 TARGET_LINK_LIBRARIES(${TARGET_APP_CORE_UI_CPP} PUBLIC
   ${TARGET_APP_CORE_CPP}
+  ${TARGET_APP_CORE_ROTATION_CPP}
   "-L${LIB_INSTALL_DIR}/hal")
 
 SET_TARGET_PROPERTIES(${TARGET_APP_CORE_UI_CPP}
index 2eeb488..beeef29 100644 (file)
@@ -35,6 +35,7 @@
 #include <utility>
 
 #include "app-core-cpp/app_core_base.hh"
+#include "app-core-rotation-cpp/app_core_rotation.hh"
 #include "app-core-ui-cpp/api/app_core_ui_base.h"
 #include "app-core-ui-cpp/app_core_task_base.hh"
 #include "app-core-ui-cpp/app_core_ui_delegator_private.hh"
@@ -54,7 +55,7 @@ constexpr const char K_HINT_RECENT_SCREEN_POSITION[] =
     "__K_HINT_RECENT_SCREEN_POSITION";
 const int APPID_MAX = 256;
 
-class AppCoreUiBase::Impl {
+class AppCoreUiBase::Impl : public AppCoreRotation::IEventListener {
  public:
   Impl(AppCoreUiBase* parent, unsigned int hint)
       : parent_(parent),
@@ -122,6 +123,9 @@ class AppCoreUiBase::Impl {
   Ecore_Wl2_Window* GetWindow() const;
   void Run(int argc, char** argv);
   void Exit();
+  void RotationInit();
+  void RotationShutdown();
+  void OnRotationChanged(int degree) override;
 
   std::list<std::shared_ptr<WinNode>> winnode_list_;
   unsigned int hint_;
@@ -142,6 +146,7 @@ class AppCoreUiBase::Impl {
   Ecore_Wl2_Window* window_ = nullptr;
   std::unique_ptr<WindowPositionManager> wp_manager_;
   std::unique_ptr<AppCoreUiThreadBase> thread_;
+  std::unique_ptr<AppCoreRotation> rotation_;
 };
 
 AppCoreUiBase::AppCoreUiBase(unsigned int hint)
@@ -544,6 +549,22 @@ void AppCoreUiBase::Impl::Exit() {
   parent_->DoExit();
 }
 
+void AppCoreUiBase::Impl::RotationInit() {
+  if (!rotation_) rotation_.reset(new AppCoreRotation(this));
+
+  rotation_->Init();
+}
+
+void AppCoreUiBase::Impl::RotationShutdown() {
+  if (rotation_) rotation_->Dispose();
+}
+
+void AppCoreUiBase::Impl::OnRotationChanged(int degree) {
+  AppCoreBase::SetRotationState(
+      static_cast<AppCoreBase::RotationState>(degree));
+  parent_->RaiseEvent(degree, IEvent::Type::DEVICE_ORIENTATION_CHANGED);
+}
+
 void AppCoreUiBase::Run(int argc, char** argv) {
   impl_->Run(argc, argv);
 }
@@ -980,4 +1001,22 @@ int AppCoreUiBase::GetWindowPosition(int* x, int* y, int* w, int* h) {
   return 0;
 }
 
+int AppCoreUiBase::OnSetEvent(IEvent::Type event) {
+  AppCoreBase::OnSetEvent(event);
+
+  if (event == IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+    impl_->RotationInit();
+
+  return 0;
+}
+
+int AppCoreUiBase::OnUnsetEvent(IEvent::Type event) {
+  AppCoreBase::OnUnsetEvent(event);
+
+  if (event == IEvent::Type::DEVICE_ORIENTATION_CHANGED)
+    impl_->RotationShutdown();
+
+  return 0;
+}
+
 }  // namespace tizen_cpp
index 0c4acac..a7f0ec3 100644 (file)
@@ -74,6 +74,8 @@ class EXPORT_API AppCoreUiBase : public AppCoreBase,
   virtual std::unique_ptr<AppCoreTaskBase> CreateTask();
   void Exit() override;
   int GetWindowPosition(int* x, int* y, int* w, int* h);
+  int OnSetEvent(IEvent::Type event) override;
+  int OnUnsetEvent(IEvent::Type event) override;
 
  protected:
   void SetCoreUiDelegator(IAppCoreUi* delegator);
index 2e79bc9..fa272bf 100644 (file)
@@ -2,6 +2,8 @@ SET(TARGET_UNIT_TEST "app-core_unittests")
 
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-cpp
   LIB_APP_CORE_CPP_SRCS)
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-rotation-cpp
+  LIB_APP_CORE_ROTATION_CPP_SRCS)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-ui-cpp
   LIB_APP_CORE_UI_CPP_SRCS)
 AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../tizen-cpp/app-core-ui-cpp/api
@@ -19,6 +21,7 @@ ADD_EXECUTABLE(${TARGET_UNIT_TEST}
   ${MOCK_SRCS}
   ${TEST_SRCS}
   ${LIB_APP_CORE_CPP_SRCS}
+  ${LIB_APP_CORE_ROTATION_CPP_SRCS}
   ${LIB_APP_CORE_UI_CPP_SRCS}
   ${LIB_APP_CORE_UI_CPP_API_SRCS}
   ${LIB_APP_CORE_EFL_CPP_SRCS}
index 08c749d..698daa3 100644 (file)
  * limitations under the License.
  */
 
-#include <gmock/gmock.h>
-#include <stdio.h>
-#include <glib.h>
 #include <bundle_cpp.h>
 #include <bundle_internal.h>
+#include <glib.h>
+#include <gmock/gmock.h>
+#include <stdio.h>
 
-#include "mock/test_fixture.h"
+#include <functional>
+
+#include "mock/app_core_base_mock.h"
 #include "mock/aul_mock.h"
-#include "mock/sensor_mock.h"
-#include "mock/vconf_mock.h"
 #include "mock/dbus_mock.h"
 #include "mock/dl_mock.h"
-#include "mock/app_core_base_mock.h"
-
-#include <functional>
+#include "mock/sensor_mock.h"
+#include "mock/test_fixture.h"
+#include "mock/vconf_mock.h"
 
 using ::testing::_;
 using ::testing::DoAll;
@@ -104,7 +104,7 @@ class DummyArgs {
 
 class TestEvent : public AppCoreBase::EventBase {
  public:
-  TestEvent(Type type) : EventBase(type) {}
+  explicit TestEvent(Type type) : EventBase(type) {}
 
   void OnEvent(const std::string& val) override {
     SetVal(val);
@@ -268,11 +268,12 @@ TEST_F(AppCoreBaseTest, AppCoreBase_AllowBG) {
   EXPECT_CALL(core, OnTerminate())
       .Times(1);
   EXPECT_CALL(core, OnReceive(_, _))
-      .WillOnce(Invoke([&core, &bg](aul_type type, tizen_base::Bundle b) -> int {
-        int ret = core.AppCoreBase::OnReceive(type, std::move(b));
-        bg = core.IsBgAllowed();
-        return ret;
-      }));
+      .WillOnce(
+          Invoke([&core, &bg](aul_type type, tizen_base::Bundle b) -> int {
+            int ret = core.AppCoreBase::OnReceive(type, std::move(b));
+            bg = core.IsBgAllowed();
+            return ret;
+          }));
 
   DummyArgs da(AUL_K_ALLOWED_BG, "ALLOWED_BG");
   core.SetFeature(AppCoreBase::FEATURE_BACKGROUND_MANAGEMENT);
@@ -315,112 +316,6 @@ TEST_F(AppCoreBaseTest, AppCoreBase_FlushMemory) {
   core.Run(da.GetArgc(), da.GetArgv());
 }
 
-TEST_F(AppCoreBaseTest, AppCoreBase_GetRotationState_N) {
-  bool result = false;
-
-  try {
-    AppCoreBase::GetRotationState();
-  } catch (const std::runtime_error& e) {
-    EXPECT_STREQ(e.what(), "invalid rotation state");
-    result = true;
-  }
-
-  EXPECT_TRUE(result);
-}
-
-TEST_F(AppCoreBaseTest, AppCoreBase_GetRotationState) {
-  testing::NiceMock<AppCoreBaseMock> core;
-  AppCoreBase::RotationState rst = AppCoreBase::ROTATION_UNKNOWN;
-
-  EXPECT_CALL(core, OnCreate())
-      .WillOnce(Invoke([&core, &rst]() -> int {
-        core.AppCoreBase::OnCreate();
-        rst = AppCoreBase::GetRotationState();
-        g_idle_add_full(G_PRIORITY_LOW, [](gpointer data) -> gboolean {
-          auto* obj = static_cast<testing::NiceMock<AppCoreBaseMock>*>(data);
-          obj->Exit();
-          return G_SOURCE_REMOVE;
-        }, &core, nullptr);
-        return 0;
-      }));
-  EXPECT_CALL(core, OnTerminate())
-      .Times(1);
-  EXPECT_CALL(GetMock<SensorMock>(), sensord_register_event(_, _, _, _, _, _))
-      .WillOnce(Invoke([](int handle, unsigned int event_type,
-          unsigned int interval, unsigned int max_batch_latency,
-          sensor_cb_t cb, void *user_data) -> bool {
-          sensor_t sensor = { 0, };
-          sensor_data_t data = { 0, };
-          data.value_count = 1;
-          data.values[0] = AUTO_ROTATION_DEGREE_0;
-          cb(sensor, AUTO_ROTATION_CHANGE_STATE_EVENT, &data, user_data);
-        return true;
-      }));
-
-  DummyArgs da;
-  auto ev = std::shared_ptr<AppCoreBase::EventBase>(
-      new TestEvent(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED));
-  core.AddEvent(ev);
-  core.Run(da.GetArgc(), da.GetArgv());
-  EXPECT_EQ(rst, AppCoreBase::ROTATION_PORTRAIT_NORMAL);
-  core.RemoveEvent(ev);
-}
-
-TEST_F(AppCoreBaseTest, AppCoreBase_LockCb) {
-  testing::NiceMock<AppCoreBaseMock> core;
-  AppCoreBase::RotationState rst = AppCoreBase::ROTATION_UNKNOWN;
-
-  EXPECT_CALL(core, OnCreate())
-      .WillOnce(Invoke([&core, &rst]() -> int {
-        core.AppCoreBase::OnCreate();
-        GetMock<VConfMock>().ChangeBool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, true);
-        rst = AppCoreBase::GetRotationState();
-        g_idle_add_full(G_PRIORITY_LOW, [](gpointer data) -> gboolean {
-          auto* obj = static_cast<testing::NiceMock<AppCoreBaseMock>*>(data);
-          obj->Exit();
-          return G_SOURCE_REMOVE;
-        }, &core, nullptr);
-        return 0;
-      }));
-  EXPECT_CALL(core, OnTerminate())
-      .Times(1);
-
-  DummyArgs da;
-  auto ev = std::shared_ptr<AppCoreBase::EventBase>(
-      new TestEvent(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED));
-  core.AddEvent(ev);
-  core.Run(da.GetArgc(), da.GetArgv());
-  EXPECT_EQ(rst, AppCoreBase::ROTATION_PORTRAIT_NORMAL);
-  core.RemoveEvent(ev);
-}
-
-TEST_F(AppCoreBaseTest, AppCoreBase_ChargerStatusChangedCb) {
-  testing::NiceMock<AppCoreBaseMock> core;
-
-  EXPECT_CALL(core, OnCreate())
-      .WillOnce(Invoke([&]() -> int {
-        core.AppCoreBase::OnCreate();
-        GetMock<VConfMock>().ChangeInt(VCONFKEY_SYSMAN_CHARGER_STATUS, 0);
-        GetMock<VConfMock>().ChangeInt(VCONFKEY_SYSMAN_CHARGER_STATUS, 1);
-        g_idle_add_full(G_PRIORITY_LOW, [](gpointer data) -> gboolean {
-          auto* obj = static_cast<testing::NiceMock<AppCoreBaseMock>*>(data);
-          obj->Exit();
-          return G_SOURCE_REMOVE;
-        }, &core, nullptr);
-        return 0;
-      }));
-  EXPECT_CALL(core, OnTerminate())
-      .Times(1);
-
-  DummyArgs da;
-  auto ev = std::shared_ptr<AppCoreBase::EventBase>(
-      new TestEvent(IAppCore::IEvent::Type::DEVICE_ORIENTATION_CHANGED));
-  core.SetFeature(AppCoreBase::FEATURE_CHARGER_STATUS);
-  core.AddEvent(ev);
-  core.Run(da.GetArgc(), da.GetArgv());
-  core.RemoveEvent(ev);
-}
-
 TEST_F(AppCoreBaseTest, AppCoreBase_AddEvent_LanguageChanged) {
   testing::NiceMock<AppCoreBaseMock> core;
 
@@ -785,4 +680,4 @@ TEST_F(AppCoreBaseTest, AppCoreBase_RotationState) {
   EXPECT_EQ(AppCoreBase::GetDisplayState(), AppCoreBase::DISPLAY_STATE_UNKNOWN);
 }
 
-} // namespace tizen_cpp
+}  // namespace tizen_cpp