From 3cb24e19f74443f51535bffa18e1395cc037d550 Mon Sep 17 00:00:00 2001 From: Jihoi Kim Date: Wed, 15 Apr 2026 20:34:21 +0900 Subject: [PATCH 1/3] [NUI] Add Tizen.Application.Team into FriendAssembly TeamApplication will create UI with NUI. However, it does not inherit NUIApplication. Instead of inheriting NUIApplcation, it use DALI native in backend. For developes to utilize C# NUI object in TeamApplication, the backend should depend on NUI deeply, require to be friend of the project. Signed-off-by: Jihoi Kim --- src/Tizen.NUI/src/internal/Common/FriendAssembly.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Tizen.NUI/src/internal/Common/FriendAssembly.cs b/src/Tizen.NUI/src/internal/Common/FriendAssembly.cs index 01bf6d0dc70..38ba0ea29fc 100755 --- a/src/Tizen.NUI/src/internal/Common/FriendAssembly.cs +++ b/src/Tizen.NUI/src/internal/Common/FriendAssembly.cs @@ -22,6 +22,7 @@ using System.Runtime.CompilerServices; +[assembly: InternalsVisibleTo("Tizen.Applications.Team, " + Tizen.NUI.PublicKey.TizenFX)] [assembly: InternalsVisibleTo("Tizen.Multimedia, " + Tizen.NUI.PublicKey.TizenFX)] [assembly: InternalsVisibleTo("Tizen.NUI.Wearable, " + Tizen.NUI.PublicKey.TizenFX)] [assembly: InternalsVisibleTo("Tizen.NUI.Components, " + Tizen.NUI.PublicKey.TizenFX)] From 8d8746aaa5c94a04d4a9f5398b9bbc23281dfa22 Mon Sep 17 00:00:00 2001 From: Jihoi Kim Date: Fri, 20 Mar 2026 15:39:05 +0900 Subject: [PATCH 2/3] [APPFW] Implement Team Application C# Interface - Implement Interop, Wrapper Class to implement C# Team Application - Add OnCreate Error Handling - When the application start, TeamManager will hold the application instance to guarantee the object alive until exit. - Implement TeamViewApplication Signed-off-by: Jihoi Kim --- .../CultureInfoHelper.cs | 55 +++ src/Tizen.Applications.Team/GSourceManager.cs | 86 ++++ .../Interop/Interop.ApplicationManager.cs | 404 +++++++++++++++ .../Interop/Interop.BaseUtilsi18n.cs | 54 ++ .../Interop/Interop.Glib.cs | 40 ++ .../Interop/Interop.IniParser.cs | 33 ++ .../Interop/Interop.Libc.cs | 27 + .../Interop/Interop.Libraries.cs | 28 ++ .../Interop/Interop.TeamLoop.cs | 63 +++ .../Interop/Interop.TeamManager.cs | 118 +++++ .../Interop/Interop.TeamMember.cs | 110 +++++ .../ResourceControl.cs | 41 ++ .../SystemLocaleConverter.cs | 343 +++++++++++++ .../TeamApplication.cs | 184 +++++++ .../TeamApplicationInfo.cs | 465 ++++++++++++++++++ .../TeamCoreApplication.cs | 242 +++++++++ .../TeamCoreUiApplication.cs | 58 +++ .../TeamDirectoryInfo.cs | 295 +++++++++++ src/Tizen.Applications.Team/TeamLoop.cs | 257 ++++++++++ src/Tizen.Applications.Team/TeamManager.cs | 272 ++++++++++ .../TeamServiceApplication.cs | 35 ++ .../TeamUiApplication.cs | 32 ++ .../TeamViewApplication.cs | 54 ++ .../TeamCoreBackend.cs | 30 ++ .../TeamServiceCoreBackend.cs | 306 ++++++++++++ .../TeamUICoreBackend.cs | 386 +++++++++++++++ .../TeamViewCoreBackend.cs | 395 +++++++++++++++ .../Tizen.Applications.Team.csproj | 18 + 28 files changed, 4431 insertions(+) create mode 100644 src/Tizen.Applications.Team/CultureInfoHelper.cs create mode 100644 src/Tizen.Applications.Team/GSourceManager.cs create mode 100755 src/Tizen.Applications.Team/Interop/Interop.ApplicationManager.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.BaseUtilsi18n.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.Glib.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.IniParser.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.Libc.cs create mode 100755 src/Tizen.Applications.Team/Interop/Interop.Libraries.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.TeamLoop.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.TeamManager.cs create mode 100644 src/Tizen.Applications.Team/Interop/Interop.TeamMember.cs create mode 100644 src/Tizen.Applications.Team/ResourceControl.cs create mode 100644 src/Tizen.Applications.Team/SystemLocaleConverter.cs create mode 100644 src/Tizen.Applications.Team/TeamApplication.cs create mode 100644 src/Tizen.Applications.Team/TeamApplicationInfo.cs create mode 100644 src/Tizen.Applications.Team/TeamCoreApplication.cs create mode 100644 src/Tizen.Applications.Team/TeamCoreUiApplication.cs create mode 100644 src/Tizen.Applications.Team/TeamDirectoryInfo.cs create mode 100644 src/Tizen.Applications.Team/TeamLoop.cs create mode 100644 src/Tizen.Applications.Team/TeamManager.cs create mode 100644 src/Tizen.Applications.Team/TeamServiceApplication.cs create mode 100644 src/Tizen.Applications.Team/TeamUiApplication.cs create mode 100644 src/Tizen.Applications.Team/TeamViewApplication.cs create mode 100644 src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs create mode 100644 src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs create mode 100644 src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs create mode 100644 src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs create mode 100755 src/Tizen.Applications.Team/Tizen.Applications.Team.csproj diff --git a/src/Tizen.Applications.Team/CultureInfoHelper.cs b/src/Tizen.Applications.Team/CultureInfoHelper.cs new file mode 100644 index 00000000000..24d45c0b218 --- /dev/null +++ b/src/Tizen.Applications.Team/CultureInfoHelper.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Tizen.Applications +{ + internal static class CultureInfoHelper + { + private const string _pathCultureInfoIni = "/usr/share/dotnet.tizen/framework/i18n/CultureInfo.ini"; + private static bool _fileExists = File.Exists(_pathCultureInfoIni); + + public static string GetCultureName(string locale) + { + if (!_fileExists) + { + return string.Empty; + } + + IntPtr dictionary = Interop.LibIniParser.Load(_pathCultureInfoIni); + if (dictionary == IntPtr.Zero) + { + return string.Empty; + } + + string cultureName = string.Empty; +#pragma warning disable CA1308 + string key = "CultureInfo:" + locale.ToLowerInvariant(); +#pragma warning restore CA1308 + IntPtr value = Interop.LibIniParser.GetString(dictionary, key, IntPtr.Zero); + if (value != IntPtr.Zero) + { + cultureName = Marshal.PtrToStringAnsi(value); + } + + Interop.LibIniParser.FreeDict(dictionary); + return cultureName; + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/GSourceManager.cs b/src/Tizen.Applications.Team/GSourceManager.cs new file mode 100644 index 00000000000..e38968f6c82 --- /dev/null +++ b/src/Tizen.Applications.Team/GSourceManager.cs @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Collections.Concurrent; + +namespace Tizen.Applications +{ + internal static class GSourceManager + { + private static readonly GSourceContext _tizenContext = new GSourceContext(); + private static readonly GSourceContext _tizenUIContext = new GSourceContext(); + private static readonly Interop.Glib.GSourceFunc _wrapperHandler = new Interop.Glib.GSourceFunc(Handler); + + public static void Post(Action action) + { + IntPtr context = IntPtr.Zero; + var sourceContext = context == IntPtr.Zero ? _tizenContext : _tizenUIContext; + sourceContext.Post(action, context, _wrapperHandler); + } + + private static bool Handler(IntPtr userData) + { + var sourceContext = userData == IntPtr.Zero ? _tizenContext : _tizenUIContext; + return sourceContext.ProcessQueue(); + } + } + + internal class GSourceContext + { + private readonly ConcurrentQueue _actionQueue = new ConcurrentQueue(); + private readonly object _lock = new object(); + private IntPtr _source = IntPtr.Zero; + + public void Post(Action action, IntPtr context, Interop.Glib.GSourceFunc handler) + { + _actionQueue.Enqueue(action); + + lock (_lock) + { + if (_source != IntPtr.Zero) + { + return; + } + + _source = Interop.Glib.IdleSourceNew(); + Interop.Glib.SourceSetCallback(_source, handler, context, IntPtr.Zero); + _ = Interop.Glib.SourceAttach(_source, context); + Interop.Glib.SourceUnref(_source); + } + } + + public bool ProcessQueue() + { + if (_actionQueue.TryDequeue(out var action)) + { + action?.Invoke(); + } + + lock (_lock) + { + if (!_actionQueue.IsEmpty) + { + return true; + } + + _source = IntPtr.Zero; + } + + return false; + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Interop/Interop.ApplicationManager.cs b/src/Tizen.Applications.Team/Interop/Interop.ApplicationManager.cs new file mode 100755 index 00000000000..24d37b61319 --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.ApplicationManager.cs @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.InteropServices; + +using Tizen.Internals; + +internal static partial class Interop +{ + internal static partial class ApplicationManager + { + internal enum ErrorCode + { + None = Tizen.Internals.Errors.ErrorCode.None, + InvalidParameter = Tizen.Internals.Errors.ErrorCode.InvalidParameter, + OutOfMemory = Tizen.Internals.Errors.ErrorCode.OutOfMemory, + IoError = Tizen.Internals.Errors.ErrorCode.IoError, + NoSuchApp = -0x01110000 | 0x01, + DbFailed = -0x01110000 | 0x03, + InvalidPackage = -0x01110000 | 0x04, + AppNoRunning = -0x01110000 | 0x05, + RequestFailed = -0x01110000 | 0x06, + PermissionDenied = Tizen.Internals.Errors.ErrorCode.PermissionDenied + } + + internal enum AppContextEvent + { + Launched = 0, + Terminated = 1 + } + + internal enum AppManagerEventStatusType + { + All = 0x00, + Enable = 0x01, + Disable = 0x02 + } + + internal enum AppManagerEventType + { + Enable = 0, + Disable = 1 + } + + internal enum AppManagerEventState + { + Started = 0, + Completed = 1, + Failed = 2 + } + + internal enum AppInfoAppComponentType + { + UiApp = 0, + ServiceApp = 1, + WidgetApp = 2, + WatchApp = 3 + } + + internal enum AppLifecycleState + { + Initialized = 0, + Created = 1, + Resumed = 2, + Paused = 3, + Destroyed = 4 + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AppManagerLifecycleStateChangedCallback(string appId, int pid, AppLifecycleState state, bool hasFocus, IntPtr userData); + //void (*app_manager_lifecycle_state_changed_cb)(const char *app_id, pid_t pid, app_manager_lifecycle_state_e state, bool has_focus, void *user_data) + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AppManagerEventCallback(string appType, string appId, AppManagerEventType eventType, AppManagerEventState eventState, IntPtr eventHandle, IntPtr userData); + //void(* app_manager_event_cb)(const char *type, const char *app_id, app_manager_event_type_e event_type, app_manager_event_state_e event_state, app_manager_event_h handle, void *user_data) + + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AppManagerAppContextEventCallback(IntPtr handle, AppContextEvent state, IntPtr userData); + //void(* app_manager_app_context_event_cb)(app_context_h app_context, app_context_event_e event, void *user_data) + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool AppManagerAppInfoCallback(IntPtr handle, IntPtr userData); + //bool(* app_manager_app_info_cb )(app_info_h app_info, void *user_data) + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool AppManagerAppContextCallback(IntPtr handle, IntPtr userData); + //bool(* app_manager_app_context_cb)(app_context_h app_context, void *user_data) + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool AppInfoFilterCallback(IntPtr handle, IntPtr userData); + //bool(* app_info_filter_cb )(app_info_h app_info, void *user_data) + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool AppInfoMetadataCallback(string key, string value, IntPtr userData); + //bool(* app_info_metadata_cb )(const char *metadata_key, const char *metadata_value, void *user_data) + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool AppInfoCategoryCallback(string category, IntPtr userData); + //bool (*app_info_category_cb) (const char *category, void *user_data) + + internal delegate bool AppInfoResControlCallback(string resType, string minResVersion, string maxResVersion, string autoClose, IntPtr userUdata); + //bool (*app_info_res_control_cb) (const char *res_type, const char *min_res_version, const char *max_res_version, const char *auto_close, void *user_data); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_set_app_context_event_cb")] + internal static extern ErrorCode AppManagerSetAppContextEvent(AppManagerAppContextEventCallback callback, IntPtr userData); + //int app_manager_set_app_context_event_cb( app_manager_app_context_event_cb callback, void * user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_unset_app_context_event_cb")] + internal static extern void AppManagerUnSetAppContextEvent(); + //void app_manager_unset_app_context_event_cb (void); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_set_lifecycle_state_changed_cb")] + internal static extern ErrorCode AppManagerSetLifecycleStateChangedCb(AppManagerLifecycleStateChangedCallback callback, IntPtr userData); + //int app_manager_set_lifecycle_state_changed_cb(app_manager_lifecycle_state_changed_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_unset_lifecycle_state_changed_cb")] + internal static extern void AppManagerUnsetLifecycleStateChangedCb(); + //void app_manager_unset_lifecycle_state_changed_cb(void) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_add_lifecycle_state_changed_cb")] + internal static extern ErrorCode AppManagerAddLifecycleStateChangedCb( + AppManagerLifecycleStateChangedCallback callback, IntPtr userData, out IntPtr handle); + // int app_manager_add_lifecycle_state_changed_cb(app_manager_lifecycle_state_changed_cb callback, + // void *user_data, app_manager_lifecycle_noti_h *handle) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_remove_lifecycle_state_changed_cb")] + internal static extern ErrorCode AppManagerRemoveLifecycleStateChangedCb(IntPtr handle); + // int app_manager_remove_lifecycle_state_changed_cb(app_manager_lifecycle_noti_h handle) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_foreach_running_app_context")] + internal static extern ErrorCode AppManagerForeachRunningAppContext(AppManagerAppContextCallback callback, IntPtr userData); + //int app_manager_foreach_running_app_context(app_manager_app_context_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_foreach_app_context")] + internal static extern ErrorCode AppManagerForeachAppContext(AppManagerAppContextCallback callback, IntPtr userData); + //int app_manager_foreach_app_context(app_manager_app_context_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_app_context")] + internal static extern ErrorCode AppManagerGetAppContext(string applicationId, out IntPtr handle); + //int app_manager_get_app_context(const char* app_id, app_context_h *app_context); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_app_id")] + internal static extern ErrorCode AppManagerGetAppId(int processId, out string applicationId); + //int app_manager_get_app_id (pid_t pid, char **appid); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_is_running")] + internal static extern ErrorCode AppManagerIsRunning(string applicationId, out bool running); + //int app_manager_is_running (const char *appid, bool *running); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_resume_app")] + internal static extern ErrorCode AppManagerResumeApp(IntPtr handle); + //int app_manager_resume_app (app_context_h handle); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_request_terminate_bg_app")] + internal static extern ErrorCode AppManagerRequestTerminateBgApp(IntPtr handle); + //int app_manager_request_terminate_bg_app (app_context_h handle); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_foreach_app_info")] + internal static extern ErrorCode AppManagerForeachAppInfo(AppManagerAppInfoCallback callback, IntPtr userData); + //int app_manager_foreach_app_info(app_manager_app_info_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_app_info")] + internal static extern ErrorCode AppManagerGetAppInfo(string applicationId, out IntPtr handle); + //int app_manager_get_app_info(const char * app_id, app_info_h * app_info) + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_shared_data_path")] + internal static extern ErrorCode AppManagerGetSharedDataPath(string applicationId, out string path); + //int app_manager_get_shared_data_path (const char *appid, char **path); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_shared_resource_path")] + internal static extern ErrorCode AppManagerGetSharedResourcePath(string applicationId, out string path); + //int app_manager_get_shared_resource_path (const char *appid, char **path); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_shared_trusted_path")] + internal static extern ErrorCode AppManagerGetSharedTrustedPath(string applicationId, out string path); + //int app_manager_get_shared_trusted_path (const char *appid, char **path); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_common_shared_data_path")] + internal static extern ErrorCode AppManagerGetCommonSharedDataPath(string applicationId, out string path); + //int app_manager_get_common_shared_data_path (const char *appid, char **path); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_common_shared_trusted_path")] + internal static extern ErrorCode AppManagerGetCommonSharedTrustedPath(string applicationId, out string path); + //int app_manager_get_common_shared_trusted_path (const char *appid, char **path); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_external_shared_data_path")] + internal static extern ErrorCode AppManagerGetExternalSharedDataPath(string applicationId, out string path); + //int app_manager_get_external_shared_data_path (const char *appid, char **path); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_event_create")] + internal static extern ErrorCode AppManagerEventCreate(out IntPtr handle); + //int app_manager_event_create (app_manager_event_h *handle); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_event_set_status")] + internal static extern ErrorCode AppManagerEventSetStatus(IntPtr handle, AppManagerEventStatusType statusType); + //int app_manager_event_set_status (app_manager_event_h handle, int status_type); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_set_event_cb")] + internal static extern ErrorCode AppManagerSetEventCallback(IntPtr handle, AppManagerEventCallback callback, IntPtr userData); + //int app_manager_set_event_cb (app_manager_event_h handle, app_manager_event_cb callback, void *user_data); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_unset_event_cb")] + internal static extern ErrorCode AppManagerUnSetEventCallback(IntPtr handle); + //int app_manager_unset_event_cb (app_manager_event_h handle); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_event_destroy")] + internal static extern ErrorCode AppManagerEventDestroy(IntPtr handle); + //int app_manager_event_destroy (app_manager_event_h handle); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_terminate_app")] + internal static extern ErrorCode AppManagerTerminateApp(IntPtr handle); + //int app_manager_terminate_app (app_context_h app_context); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_terminate_app_without_restarting")] + internal static extern ErrorCode AppManagerTerminateAppWithoutRestarting(IntPtr handle); + //int app_manager_terminate_app_without_restarting (app_context_h app_context); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_get_app_context_by_instance_id")] + internal static extern ErrorCode AppManagerGetAppContextByInstanceId(string applicationId, string instanceId, out IntPtr handle); + //int app_manager_get_app_context_by_instance_id (const char *app_id, const char *instance_id, app_context_h *app_context); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_attach_window")] + internal static extern ErrorCode AppManagerAttachWindow(string parentAppId, string childAppId); + //int app_manager_attach_window(const char *parent_app_id, const char *child_app_id); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_detach_window")] + internal static extern ErrorCode AppManagerDetachWindow(string applicationId); + //int app_manager_detach_window(const char *app_id); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_attach_window_below")] + internal static extern ErrorCode AppManagerAttachWindowBelow(string parentAppId, string childAppId); + //int app_manager_attach_window_below(const char *parent_app_id, const char *child_app_id); + + [DllImport(Libraries.AppManager, EntryPoint = "app_manager_request_remount_subsession")] + internal static extern ErrorCode AppManagerRequestRemountSubsession(string subsessionId); + //int app_manager_request_remount_subsession(const char *subsession_id); + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_destroy")] + internal static extern ErrorCode AppContextDestroy(IntPtr handle); + //int app_context_destroy(app_context_h app_context) + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_get_app_id")] + internal static extern ErrorCode AppContextGetAppId(IntPtr handle, out string applicationId); + //int app_context_get_app_id(app_context_h app_context, char **app_id) + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_get_package_id")] + internal static extern ErrorCode AppContextGetPackageId(IntPtr handle, out string packageId); + //int app_context_get_package_id(app_context_h app_context, char **package_id) + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_get_pid")] + internal static extern ErrorCode AppContextGetPid(IntPtr handle, out int processId); + //int app_context_get_pid (app_context_h app_context, pid_t *pid) + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_get_app_state")] + internal static extern ErrorCode AppContextGetAppState(IntPtr handle, out int state); + //int app_context_get_app_state (app_context_h app_context, app_state_e *state) + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_is_terminated")] + internal static extern ErrorCode AppContextIsTerminated(IntPtr handle, out bool terminated); + //int app_context_is_terminated (app_context_h app_context, bool *terminated); + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_is_equal")] + internal static extern ErrorCode AppContextIsEqual(IntPtr first, IntPtr second, out bool equal); + //int app_context_is_equal (app_context_h lhs, app_context_h rhs, bool *equal); + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_is_sub_app")] + internal static extern ErrorCode AppContextIsSubApp(IntPtr handle, out bool is_sub_app); + //int app_context_is_sub_app (app_context_h app_context, bool *is_sub_app); + + [DllImport(Libraries.AppManager, EntryPoint = "app_context_clone")] + internal static extern ErrorCode AppContextClone(out IntPtr destination, IntPtr source); + //int app_context_clone (app_context_h *clone, app_context_h app_context); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_create")] + internal static extern ErrorCode AppInfoCreate(string applicationId, out IntPtr handle); + //int app_info_create (const char *app_id, app_info_h *app_info); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_destroy")] + internal static extern ErrorCode AppInfoDestroy(IntPtr handle); + //int app_info_destroy (app_info_h app_info); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_app_id")] + internal static extern ErrorCode AppInfoGetAppId(IntPtr handle, out string applicationId); + //int app_info_get_app_id (app_info_h app_info, char **app_id); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_exec")] + internal static extern ErrorCode AppInfoGetExec(IntPtr handle, out string exec); + //int app_info_get_exec (app_info_h app_info, char **exec); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_label")] + internal static extern ErrorCode AppInfoGetLabel(IntPtr handle, out string label); + //int app_info_get_label (app_info_h app_info, char **label); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_localed_label")] + internal static extern ErrorCode AppInfoGetLocaledLabel(string applicationId, string locale, out string label); + //int app_info_get_localed_label (const char *app_id, const char *locale, char **label); + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_icon")] + internal static extern ErrorCode AppInfoGetIcon(IntPtr handle, out string path); + //int app_info_get_icon (app_info_h app_info, char **path) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_package")] + internal static extern ErrorCode AppInfoGetPackage(IntPtr handle, out string package); + //int app_info_get_package (app_info_h app_info, char **package) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_type")] + internal static extern ErrorCode AppInfoGetType(IntPtr handle, out string type); + //int app_info_get_type (app_info_h app_info, char **type) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_get_app_component_type")] + internal static extern ErrorCode AppInfoGetAppComponentType(IntPtr handle, out AppInfoAppComponentType type); + //int app_info_get_app_component_type(app_info_h app_info, app_info_app_component_type_e *type) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_foreach_metadata")] + internal static extern ErrorCode AppInfoForeachMetadata(IntPtr handle, AppInfoMetadataCallback callback, IntPtr userData); + //int app_info_foreach_metadata(app_info_h app_info, app_info_metadata_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_is_nodisplay")] + internal static extern ErrorCode AppInfoIsNodisplay(IntPtr handle, out bool noDisplay); + //int app_info_is_nodisplay (app_info_h app_info, bool *nodisplay) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_is_equal")] + internal static extern ErrorCode AppInfoIsEqual(IntPtr first, IntPtr second, out bool equal); + //int app_info_is_equal (app_info_h lhs, app_info_h rhs, bool *equal) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_is_enabled")] + internal static extern ErrorCode AppInfoIsEnabled(IntPtr handle, out bool enabled); + //int app_info_is_enabled (app_info_h app_info, bool *enabled) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_is_onboot")] + internal static extern ErrorCode AppInfoIsOnBoot(IntPtr handle, out bool onBoot); + //int app_info_is_onboot (app_info_h app_info, bool *onboot) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_is_preload")] + internal static extern ErrorCode AppInfoIsPreLoad(IntPtr handle, out bool preLoaded); + //int app_info_is_preload (app_info_h app_info, bool *preload) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_clone")] + internal static extern ErrorCode AppInfoClone(out IntPtr destination, IntPtr source); + //int app_info_clone(app_info_h * clone, app_info_h app_info) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_foreach_category")] + internal static extern ErrorCode AppInfoForeachCategory(IntPtr handle, AppInfoCategoryCallback callback, IntPtr userData); + //int app_info_foreach_category(app_info_h app_info, app_info_category_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_filter_create")] + internal static extern ErrorCode AppInfoFilterCreate(out IntPtr handle); + //int app_info_filter_create(app_info_filter_h * handle) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_filter_destroy")] + internal static extern ErrorCode AppInfoFilterDestroy(IntPtr handle); + //int app_info_filter_destroy(app_info_filter_h handle) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_filter_add_bool")] + internal static extern ErrorCode AppInfoFilterAddBool(IntPtr handle, string property, bool value); + //int app_info_filter_add_bool(app_info_filter_h handle, const char *property, const bool value) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_filter_add_string")] + internal static extern ErrorCode AppInfoFilterAddString(IntPtr handle, string property, string value); + //int app_info_filter_add_string(app_info_filter_h handle, const char *property, const char *value) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_filter_count_appinfo")] + internal static extern ErrorCode AppInfoFilterCountAppinfo(IntPtr handle, out int count); + //int app_info_filter_count_appinfo(app_info_filter_h handle, int *count) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_filter_foreach_appinfo")] + internal static extern ErrorCode AppInfoFilterForeachAppinfo(IntPtr handle, AppInfoFilterCallback callback, IntPtr userData); + //int app_info_filter_foreach_appinfo(app_info_filter_h handle, app_info_filter_cb callback, void * user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_metadata_filter_create")] + internal static extern ErrorCode AppInfoMetadataFilterCreate(out IntPtr handle); + //int app_info_metadata_filter_create (app_info_metadata_filter_h *handle) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_metadata_filter_destroy")] + internal static extern ErrorCode AppInfoMetadataFilterDestroy(IntPtr handle); + //int app_info_metadata_filter_destroy (app_info_metadata_filter_h handle) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_metadata_filter_add")] + internal static extern ErrorCode AppInfoMetadataFilterAdd(IntPtr handle, string key, string value); + //int app_info_metadata_filter_add (app_info_metadata_filter_h handle, const char *key, const char *value) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_metadata_filter_foreach")] + internal static extern ErrorCode AppInfoMetadataFilterForeach(IntPtr handle, AppInfoFilterCallback callback, IntPtr userData); + //int app_info_metadata_filter_foreach (app_info_metadata_filter_h handle, app_info_filter_cb callback, void *user_data) + + [DllImport(Libraries.AppManager, EntryPoint = "app_info_foreach_res_control")] + internal static extern ErrorCode AppInfoForeachResControl(IntPtr handle, AppInfoResControlCallback callback, IntPtr userData); + } +} diff --git a/src/Tizen.Applications.Team/Interop/Interop.BaseUtilsi18n.cs b/src/Tizen.Applications.Team/Interop/Interop.BaseUtilsi18n.cs new file mode 100644 index 00000000000..1bf2e6b9c32 --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.BaseUtilsi18n.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +internal static partial class Interop +{ + internal static partial class BaseUtilsi18n + { + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_canonicalize")] + internal static extern Int32 Canonicalize(string localeID, [Out] StringBuilder name, Int32 nameCapacity); + // int32_t i18n_ulocale_canonicalize(const char *locale_id, char *name, int32_t name_capacity); + + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_get_language")] + internal static extern int GetLanguage(string localeID, [Out] StringBuilder language, Int32 languageCapacity, out int bufSizeLanguage); + // int i18n_ulocale_get_language(const char *locale_id, char *language, int32_t language_capacity, int32_t *buf_size_language); + + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_get_script")] + internal static extern Int32 GetScript(string localeID, [Out] StringBuilder script, Int32 scriptCapacity); + // int32_t i18n_ulocale_get_script(const char *locale_id, char *script, int32_t script_capacity); + + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_get_country")] + internal static extern Int32 GetCountry(string localeID, [Out] StringBuilder country, Int32 countryCapacity, out int err); + // int32_t i18n_ulocale_get_country(const char *locale_id, char *country, int32_t country_capacity, int *error); + + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_get_variant")] + internal static extern Int32 GetVariant(string localeID, [Out] StringBuilder variant, Int32 variantCapacity); + // int32_t i18n_ulocale_get_variant(const char *locale_id, char *variant, int32_t variant_capacity); + + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_get_lcid")] + internal static extern UInt32 GetLCID(string localeID); + // uint32_t i18n_ulocale_get_lcid(const char *locale_id); + + [DllImport(Libraries.BaseUtilsi18n, EntryPoint = "i18n_ulocale_get_default")] + internal static extern int GetDefault(out IntPtr localeID); + // int i18n_ulocale_get_default(const char **locale); + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Interop/Interop.Glib.cs b/src/Tizen.Applications.Team/Interop/Interop.Glib.cs new file mode 100644 index 00000000000..79e4cbc98cf --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.Glib.cs @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Glib + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool GSourceFunc(IntPtr userData); + + [DllImport(Libraries.Glib, EntryPoint = "g_idle_source_new", CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr IdleSourceNew(); + + [DllImport(Libraries.Glib, EntryPoint = "g_source_set_callback", CallingConvention = CallingConvention.Cdecl)] + internal static extern void SourceSetCallback(IntPtr source, GSourceFunc func, IntPtr data, IntPtr notify); + + [DllImport(Libraries.Glib, EntryPoint = "g_source_attach", CallingConvention = CallingConvention.Cdecl)] + internal static extern uint SourceAttach(IntPtr source, IntPtr context); + + [DllImport(Libraries.Glib, EntryPoint = "g_source_unref", CallingConvention = CallingConvention.Cdecl)] + internal static extern void SourceUnref(IntPtr source); + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Interop/Interop.IniParser.cs b/src/Tizen.Applications.Team/Interop/Interop.IniParser.cs new file mode 100644 index 00000000000..7173a2ee185 --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.IniParser.cs @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class LibIniParser + { + [DllImport(Libraries.IniParser, EntryPoint = "iniparser_getstring", CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr GetString(IntPtr d, string key, IntPtr def); + + [DllImport(Libraries.IniParser, EntryPoint = "iniparser_load", CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr Load(string iniName); + + [DllImport(Libraries.IniParser, EntryPoint = "iniparser_freedict", CallingConvention = CallingConvention.Cdecl)] + internal static extern void FreeDict(IntPtr d); + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Interop/Interop.Libc.cs b/src/Tizen.Applications.Team/Interop/Interop.Libc.cs new file mode 100644 index 00000000000..e7609f1f25d --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.Libc.cs @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class Libc + { + [DllImport(Libraries.Libc, EntryPoint = "getenv")] + internal static extern IntPtr GetEnvironmentVariable(string name); + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Interop/Interop.Libraries.cs b/src/Tizen.Applications.Team/Interop/Interop.Libraries.cs new file mode 100755 index 00000000000..c049ed10861 --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.Libraries.cs @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +internal static partial class Interop +{ + internal static partial class Libraries + { + public const string TeamLib = "libteam-application.so.1"; + public const string Glib = "libglib-2.0.so.0"; + public const string Libc = "libc.so.6"; + public const string BaseUtilsi18n = "libbase-utils-i18n.so.0"; + public const string IniParser = "libiniparser.so.1"; + public const string AppManager = "libcapi-appfw-app-manager.so.0"; + } +} diff --git a/src/Tizen.Applications.Team/Interop/Interop.TeamLoop.cs b/src/Tizen.Applications.Team/Interop/Interop.TeamLoop.cs new file mode 100644 index 00000000000..6a1119295a6 --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.TeamLoop.cs @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.InteropServices; +using Tizen.Internals; + +internal static partial class Interop +{ + internal static partial class TeamLoop + { + internal delegate IntPtr TeamLoopOpsLoad([MarshalAs(UnmanagedType.LPStr)] string path); + + internal delegate void TeamLoopOpsUnload(IntPtr loadObj); + + internal delegate IntPtr TeamLoopOpsCreateArgs(IntPtr loadObj); + + internal delegate void TeamLoopOpsCreateLibPath([MarshalAs(UnmanagedType.LPStr)] string path, ref IntPtr output); + + internal delegate void TeamLoopOpsOnLoopCreate(); + + internal delegate void TeamLoopOpsOnLoopTerminate(); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_main")] + internal static extern int Main(int argc, string[] argv, TeamLoopOperations ops); + + [NativeStruct("team_launcher_operation_s", Include="team_common.h", PkgConfig="team-application")] + [StructLayout(LayoutKind.Sequential)] + internal struct TeamLoopOperations + { + [MarshalAs(UnmanagedType.FunctionPtr)] + public TeamLoopOpsLoad Load; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public TeamLoopOpsUnload Unload; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public TeamLoopOpsCreateArgs CreateArgs; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public TeamLoopOpsCreateLibPath CreateLibPath; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public TeamLoopOpsOnLoopCreate OnLoopCreate; + + [MarshalAs(UnmanagedType.FunctionPtr)] + public TeamLoopOpsOnLoopTerminate OnLoopTerminate; + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Interop/Interop.TeamManager.cs b/src/Tizen.Applications.Team/Interop/Interop.TeamManager.cs new file mode 100644 index 00000000000..a4663a1da20 --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.TeamManager.cs @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.InteropServices; +using Tizen.Internals; +using Tizen.Internals.Errors; + +internal static partial class Interop +{ + internal static partial class TeamManager + { + internal enum TeamAppErrorCode + { + None = ErrorCode.None, + InvalidParameter = ErrorCode.InvalidParameter, + OutOfMemory = ErrorCode.OutOfMemory, + InvalidContext = -0x01100000 | 0x01, + AlreadyExist = ErrorCode.FileExists, + AlreadyRunning = ErrorCode.AlreadyInProgress, + NoSuchMember = ErrorCode.NoSuchFile, + IOError = ErrorCode.IoError, + NotSupported = ErrorCode.NotSupported, + } + + [DllImport(Libraries.TeamLib, EntryPoint = "create_wl2_window_by_id")] + internal static extern IntPtr CreateWl2WindowById(int wl2WinId); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_data_path")] + internal static extern TeamAppErrorCode TeamAppGetDataPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_cache_path")] + internal static extern TeamAppErrorCode TeamAppGetCachePath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_resource_path")] + internal static extern TeamAppErrorCode TeamAppGetResourcePath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_tep_resource_path")] + internal static extern TeamAppErrorCode TeamAppGetTepResourcePath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_shared_data_path")] + internal static extern TeamAppErrorCode TeamAppGetSharedDataPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_shared_resource_path")] + internal static extern TeamAppErrorCode TeamAppGetSharedResourcePath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_shared_trusted_path")] + internal static extern TeamAppErrorCode TeamAppGetSharedTrustedPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_res_control_allowed_path")] + internal static extern TeamAppErrorCode TeamAppGetResControlAllowedPath(IntPtr memberHandle, string resType, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_res_control_global_path")] + internal static extern TeamAppErrorCode TeamAppGetResControlGlobalPath(IntPtr memberHandle, string resType, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_common_data_path")] + internal static extern TeamAppErrorCode TeamAppGetCommonDataPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_common_cache_path")] + internal static extern TeamAppErrorCode TeamAppGetCommonCachePath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_common_shared_data_path")] + internal static extern TeamAppErrorCode TeamAppGetCommonSharedDataPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_common_shared_trusted_path")] + internal static extern TeamAppErrorCode TeamAppGetCommonSharedTrustedPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_app_id")] + internal static extern TeamAppErrorCode TeamAppGetAppId(IntPtr memberHandle, out string appId); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_package_id")] + internal static extern TeamAppErrorCode TeamAppGetPackageId(IntPtr memberHandle, out string packageId); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_instance_id")] + internal static extern TeamAppErrorCode TeamAppGetInstanceId(IntPtr memberHandle, out string instId); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_app_instance_id")] + internal static extern TeamAppErrorCode TeamAppGetAppInstanceId(IntPtr memberHandle, out string appInstId); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_name")] + internal static extern TeamAppErrorCode TeamAppGetName(IntPtr memberHandle, out string name); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_version")] + internal static extern TeamAppErrorCode TeamAppGetVersion(IntPtr memberHandle, out string version); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_extern_data_path")] + internal static extern TeamAppErrorCode TeamAppGetExternDataPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_extern_cache_path")] + internal static extern TeamAppErrorCode TeamAppGetExternCachePath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_app_get_extern_shared_data_path")] + internal static extern TeamAppErrorCode TeamAppGetExternSharedDataPath(IntPtr memberHandle, out string path); + + [DllImport(Libraries.TeamLib, EntryPoint = "invoke_view_visibility_event")] + internal static extern void InvokeViewVisibilityEvent(int viewId, bool visible); + + [DllImport(Libraries.TeamLib, EntryPoint = "create_view_by_view_id")] + internal static extern IntPtr CreateViewByViewId(int viewId); + + [DllImport(Libraries.TeamLib, EntryPoint = "destroy_view_by_view_id")] + internal static extern void DestroyViewByViewId(int viewId); + + } +} diff --git a/src/Tizen.Applications.Team/Interop/Interop.TeamMember.cs b/src/Tizen.Applications.Team/Interop/Interop.TeamMember.cs new file mode 100644 index 00000000000..d99752fa8ab --- /dev/null +++ b/src/Tizen.Applications.Team/Interop/Interop.TeamMember.cs @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.InteropServices; +using Tizen.Internals; + +internal static partial class Interop +{ + internal static partial class TeamMember + { + internal delegate void AppTerminateCallback(IntPtr context, IntPtr userdata); + internal delegate void AppControlCallback(IntPtr context, IntPtr appControl, IntPtr userdata); + internal delegate void AppResumeCallback(IntPtr context, IntPtr userdata); + internal delegate void AppPauseCallback(IntPtr context, IntPtr userdata); + internal delegate void AppLowMemoryCallback(IntPtr context, int status, IntPtr userdata); + internal delegate void AppLowBatteryCallback(IntPtr context, int status, IntPtr userdata); + internal delegate void AppLanguageChangedCallback(IntPtr context, + [MarshalAs(UnmanagedType.LPStr)] string language, IntPtr userdata); + internal delegate void AppDeviceOrientationChangedCallback(IntPtr context, int status, IntPtr userdata); + internal delegate void AppRegionFormatChangedCallback(IntPtr context, + [MarshalAs(UnmanagedType.LPStr)] string region, IntPtr userdata); + internal delegate void AppSuspendStateChangedCallback(IntPtr context, int status, IntPtr userdata); + internal delegate void AppTimeZoneChangedCallback(IntPtr context, + [MarshalAs(UnmanagedType.LPStr)] string timeZone, + [MarshalAs(UnmanagedType.LPStr)] string timeZoneId, + IntPtr userdata); + internal delegate IntPtr UIAppCreateCallback(IntPtr context, IntPtr userdata); + internal delegate IntPtr ViewAppCreateCallback(IntPtr context, IntPtr userdata); + internal delegate bool ServiceAppCreateCallback(IntPtr context, IntPtr userdata); + [StructLayout(LayoutKind.Sequential)] + internal struct UIMemberLifecycleCallbacks + { + public UIAppCreateCallback Create; + public AppTerminateCallback Terminate; + public AppControlCallback Control; + public AppResumeCallback Resume; + public AppPauseCallback Pause; + public AppLowMemoryCallback LowMemory; + public AppLowBatteryCallback LowBattery; + public AppLanguageChangedCallback LanguageChanged; + public AppDeviceOrientationChangedCallback DeviceOrientationChanged; + public AppRegionFormatChangedCallback RegionFormatChanged; + public AppSuspendStateChangedCallback SuspendStateChanged; + public AppTimeZoneChangedCallback TimezoneChanged; + } + [StructLayout(LayoutKind.Sequential)] + internal struct ServiceMemberLifecycleCallbacks + { + public ServiceAppCreateCallback Create; + public AppTerminateCallback Terminate; + public AppControlCallback Control; + public AppLowMemoryCallback LowMemory; + public AppLowBatteryCallback LowBattery; + public AppLanguageChangedCallback LanguageChanged; + public AppDeviceOrientationChangedCallback DeviceOrientationChanged; + public AppRegionFormatChangedCallback RegionFormatChanged; + public AppSuspendStateChangedCallback SuspendStateChanged; + public AppTimeZoneChangedCallback TimezoneChanged; + } + + [DllImport(Libraries.TeamLib, EntryPoint = "team_ui_app_teamup")] + internal static extern IntPtr UIMemberTeamup(UIMemberLifecycleCallbacks callbacks, IntPtr userdata); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_ui_app_quit")] + internal static extern void UIMemberQuit(IntPtr member); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_service_app_teamup")] + internal static extern IntPtr ServiceMemberTeamup(ServiceMemberLifecycleCallbacks callbacks, IntPtr userdata); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_service_app_quit")] + internal static extern void ServiceMemberQuit(IntPtr member); + + [StructLayout(LayoutKind.Sequential)] + internal struct ViewMemberLifecycleCallbacks + { + public ViewAppCreateCallback Create; + public AppTerminateCallback Terminate; + public AppControlCallback Control; + public AppResumeCallback Resume; + public AppPauseCallback Pause; + public AppLowMemoryCallback LowMemory; + public AppLowBatteryCallback LowBattery; + public AppLanguageChangedCallback LanguageChanged; + public AppDeviceOrientationChangedCallback DeviceOrientationChanged; + public AppRegionFormatChangedCallback RegionFormatChanged; + public AppSuspendStateChangedCallback SuspendStateChanged; + public AppTimeZoneChangedCallback TimezoneChanged; + } + + [DllImport(Libraries.TeamLib, EntryPoint = "team_view_app_teamup")] + internal static extern IntPtr ViewMemberTeamup(ViewMemberLifecycleCallbacks callbacks, IntPtr userdata); + + [DllImport(Libraries.TeamLib, EntryPoint = "team_view_app_quit")] + internal static extern void ViewMemberQuit(IntPtr member); + } +} diff --git a/src/Tizen.Applications.Team/ResourceControl.cs b/src/Tizen.Applications.Team/ResourceControl.cs new file mode 100644 index 00000000000..cd3f3822eca --- /dev/null +++ b/src/Tizen.Applications.Team/ResourceControl.cs @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tizen.Applications +{ + public class ResourceControl + { + internal ResourceControl(string resourceType, string minResourceVersion, string maxResourceVersion, bool isAutoClose) + { + ResourceType = resourceType; + MinResourceVersion = minResourceVersion ?? null; + MaxResourceVersion = maxResourceVersion ?? null; + IsAutoClose = isAutoClose; + } + + public string ResourceType { get; } + + public string MinResourceVersion { get; } + + public string MaxResourceVersion { get; } + + public bool IsAutoClose { get; } + } +} diff --git a/src/Tizen.Applications.Team/SystemLocaleConverter.cs b/src/Tizen.Applications.Team/SystemLocaleConverter.cs new file mode 100644 index 00000000000..8f04fdd2125 --- /dev/null +++ b/src/Tizen.Applications.Team/SystemLocaleConverter.cs @@ -0,0 +1,343 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Tizen.Applications +{ + internal class SystemLocaleConverter + { + private static readonly string LogTag = "DN_TAM"; + public SystemLocaleConverter() + { + } + + public CultureInfo Convert(string locale) + { + ULocale pLocale = new ULocale(locale); + string cultureName = CultureInfoHelper.GetCultureName(pLocale.Locale.Replace("_", "-")); + + if (!string.IsNullOrEmpty(cultureName)) + { + try + { + return new CultureInfo(cultureName); + } + catch (CultureNotFoundException) + { + Log.Error(LogTag, "CultureNotFoundException occurs. CultureName: " + cultureName); + } + } + + try + { + return new CultureInfo(pLocale.LCID); + } + catch (ArgumentOutOfRangeException) + { + return GetFallback(pLocale); + } + catch (CultureNotFoundException) + { + return GetFallback(pLocale); + } + } + + public string Convert(CultureInfo cultureInfo) + { + if (cultureInfo == null || string.IsNullOrEmpty(cultureInfo.Name)) + { + return string.Empty; + } + return $"{cultureInfo.Name.Replace("-", "_")}.UTF-8"; + } + + private CultureInfo GetFallback(ULocale uLocale) + { + CultureInfo fallbackCultureInfo = null; + string locale = string.Empty; + + if (uLocale.Locale != null) + { + locale = uLocale.Locale.Replace("_", "-"); + fallbackCultureInfo = GetCultureInfo(locale); + } + + if (fallbackCultureInfo == null && uLocale.Language != null && uLocale.Script != null && uLocale.Country != null) + { + locale = uLocale.Language + "-" + uLocale.Script + "-" + uLocale.Country; + fallbackCultureInfo = GetCultureInfo(locale); + } + + if (fallbackCultureInfo == null && uLocale.Language != null && uLocale.Script != null) + { + locale = uLocale.Language + "-" + uLocale.Script; + fallbackCultureInfo = GetCultureInfo(locale); + } + + if (fallbackCultureInfo == null && uLocale.Language != null && uLocale.Country != null) + { + locale = uLocale.Language + "-" + uLocale.Country; + fallbackCultureInfo = GetCultureInfo(locale); + } + + if (fallbackCultureInfo == null && uLocale.Language != null) + { + locale = uLocale.Language; + fallbackCultureInfo = GetCultureInfo(locale); + } + + if (fallbackCultureInfo == null) + { + try + { + fallbackCultureInfo = new CultureInfo("en"); + } + catch (CultureNotFoundException e) + { + Log.Error(LogTag, "Failed to create CultureInfo. err = " + e.Message); + } + } + + return fallbackCultureInfo; + } + + private CultureInfo GetCultureInfo(string locale) + { + if (!Exist(locale)) + { + return null; + } + + try + { + return new CultureInfo(locale); + } + catch (CultureNotFoundException) + { + return null; + } + } + + private bool Exist(string locale) + { + foreach (var cultureInfo in CultureInfo.GetCultures(CultureTypes.AllCultures)) + { + if (cultureInfo.Name == locale) + { + return true; + } + } + return false; + } + + + internal class ULocale + { + private const int ULOC_FULLNAME_CAPACITY = 157; + private const int ULOC_LANG_CAPACITY = 12; + private const int ULOC_SCRIPT_CAPACITY = 6; + private const int ULOC_COUNTRY_CAPACITY = 4; + private const int ULOC_VARIANT_CAPACITY = ULOC_FULLNAME_CAPACITY; + private string locale; + private string _locale; + private string _language; + private string _script; + private string _country; + private string _variant; + private int _lcid; + + internal ULocale(string locale) + { + this.locale = locale; + _locale = _language = _script = _country = _variant = null; + _lcid = -1; + } + + internal string Locale + { + get + { + if (string.IsNullOrEmpty(_locale)) + { + _locale = Canonicalize(locale); + } + return _locale; + } + private set + { + _locale = value; + } + } + internal string Language { + get + { + if (string.IsNullOrEmpty(_language)) + { + _language = GetLanguage(Locale); + } + return _language; + } + private set + { + _language = value; + } + } + internal string Script + { + get + { + if (string.IsNullOrEmpty(_script)) + { + _script = GetScript(Locale); + } + return _script; + } + private set + { + _script = value; + } + } + internal string Country { + get + { + if (string.IsNullOrEmpty(_country)) + { + _country = GetCountry(Locale); + } + return _country; + } + private set + { + _country = value; + } + } + internal string Variant + { + get + { + if (string.IsNullOrEmpty(_variant)) + { + _variant = GetVariant(Locale); + } + return _variant; + } + private set + { + _variant = value; + } + } + internal int LCID { + get + { + if (_lcid == -1) { + _lcid = GetLCID(Locale); + } + return _lcid; + } + private set { + _lcid = value; + } + } + + private string Canonicalize(string localeName) + { + // Get the locale name from ICU + StringBuilder sb = new StringBuilder(ULOC_FULLNAME_CAPACITY); + if (Interop.BaseUtilsi18n.Canonicalize(localeName, sb, sb.Capacity) <= 0) + { + return null; + } + + return sb.ToString(); + } + + private string GetLanguage(string locale) + { + // Get the language name from ICU + StringBuilder sb = new StringBuilder(ULOC_LANG_CAPACITY); + if (Interop.BaseUtilsi18n.GetLanguage(locale, sb, sb.Capacity, out int bufSizeLanguage) != 0) + { + return null; + } + + return sb.ToString(); + } + + private string GetScript(string locale) + { + // Get the script name from ICU + StringBuilder sb = new StringBuilder(ULOC_SCRIPT_CAPACITY); + if (Interop.BaseUtilsi18n.GetScript(locale, sb, sb.Capacity) <= 0) + { + return null; + } + + return sb.ToString(); + } + + private string GetCountry(string locale) + { + int err = 0; + + // Get the country name from ICU + StringBuilder sb = new StringBuilder(ULOC_COUNTRY_CAPACITY); + if (Interop.BaseUtilsi18n.GetCountry(locale, sb, sb.Capacity, out err) <= 0) + { + return null; + } + + return sb.ToString(); + } + + private string GetVariant(string locale) + { + // Get the variant name from ICU + StringBuilder sb = new StringBuilder(ULOC_VARIANT_CAPACITY); + if (Interop.BaseUtilsi18n.GetVariant(locale, sb, sb.Capacity) <= 0) + { + return null; + } + + return sb.ToString(); + } + + private int GetLCID(string locale) + { + // Get the LCID from ICU + uint lcid = Interop.BaseUtilsi18n.GetLCID(locale); + return (int)lcid; + } + + internal static string GetDefaultLocale() + { + IntPtr stringPtr = Interop.Libc.GetEnvironmentVariable("LANG"); + if (stringPtr == IntPtr.Zero) + { + return string.Empty; + } + + return Marshal.PtrToStringAnsi(stringPtr); + } + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/TeamApplication.cs b/src/Tizen.Applications.Team/TeamApplication.cs new file mode 100644 index 00000000000..1b1a90474ff --- /dev/null +++ b/src/Tizen.Applications.Team/TeamApplication.cs @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using Tizen.Applications.CoreBackend; + +namespace Tizen.Applications +{ + public abstract class TeamApplication : IDisposable + { + internal const string LogTag = "DN_TAM"; + + private object _lock = new object(); + + private TeamDirectoryInfo _directoryInfo; + private TeamApplicationInfo _applicationInfo; + protected readonly TeamCoreBackend _backend; + + protected ICoreBackend Backend => _backend; + + protected TeamApplication(TeamCoreBackend backend) + { + Log.Info(LogTag, "TeamApplication constructor called"); + _backend = backend ?? throw new ArgumentNullException(nameof(backend)); + } + + public TeamDirectoryInfo DirectoryInfo + { + get + { + lock (_lock) + { + if (_directoryInfo == null) + { + Log.Info(LogTag, "DirectoryInfo getter called - creating new TeamDirectoryInfo"); + var memberHandle = _backend.MemberHandle; + if (memberHandle != IntPtr.Zero) + { + _directoryInfo = new TeamDirectoryInfo(memberHandle); + } + } + } + return _directoryInfo; + } + } + + public TeamApplicationInfo ApplicationInfo + { + get + { + lock (_lock) + { + if (_applicationInfo == null) + { + Log.Info(LogTag, "ApplicationInfo getter called - creating new TeamApplicationInfo"); + var memberHandle = _backend.MemberHandle; + if (memberHandle != IntPtr.Zero) + { + var err = Interop.TeamManager.TeamAppGetAppId(memberHandle, out string appId); + if (err == 0 && !string.IsNullOrEmpty(appId)) + { + _applicationInfo = new TeamApplicationInfo(memberHandle, appId); + } + else + { + Log.Warn(LogTag, $"Failed to get AppId from memberHandle. err = {err}"); + } + } + else + { + Log.Warn(LogTag, "MemberHandle is zero, cannot get ApplicationInfo"); + } + } + } + return _applicationInfo; + } + } + + public TeamApplication Current { get { return this; } } + + public string Name + { + get + { + var memberHandle = _backend.MemberHandle; + if (memberHandle == IntPtr.Zero) + { + Log.Warn(LogTag, "MemberHandle is zero, cannot get Name"); + return string.Empty; + } + + var err = Interop.TeamManager.TeamAppGetName(memberHandle, out string name); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, $"Failed to get Name. err = {err}"); + return string.Empty; + } + + return name ?? string.Empty; + } + } + + public string Version + { + get + { + var memberHandle = _backend.MemberHandle; + if (memberHandle == IntPtr.Zero) + { + Log.Warn(LogTag, "MemberHandle is zero, cannot get Version"); + return string.Empty; + } + + var err = Interop.TeamManager.TeamAppGetVersion(memberHandle, out string version); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, $"Failed to get Version. err = {err}"); + return string.Empty; + } + + return version ?? string.Empty; + } + } + + public virtual void Run(string[] args) + { + if (args == null) + { + throw new ArgumentNullException(nameof(args)); + } + TeamManager.RegisterRunningTeamApp(this); + } + + public virtual void Exit() + { + TeamManager.UnRegisterRunningTeamApp(this); + _backend.Exit(); + } + + private bool _disposedValue = false; + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + if (_applicationInfo != null) + { + _applicationInfo.Dispose(); + } + Exit(); + } + + _disposedValue = true; + } + } + + ~TeamApplication() + { + Dispose(false); + } + + public void Dispose() + { + Log.Info(LogTag, "TeamApplication.Dispose() called"); + Dispose(true); + GC.SuppressFinalize(this); + } + } +} diff --git a/src/Tizen.Applications.Team/TeamApplicationInfo.cs b/src/Tizen.Applications.Team/TeamApplicationInfo.cs new file mode 100644 index 00000000000..c4f450ed209 --- /dev/null +++ b/src/Tizen.Applications.Team/TeamApplicationInfo.cs @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using Tizen.Internals; +using Tizen.Internals.Errors; + +namespace Tizen.Applications +{ + public class TeamApplicationInfo : IDisposable + { + private const string LogTag = "DN_TAMS"; + private bool _disposed = false; + private IntPtr _infoHandle = IntPtr.Zero; + private IntPtr _memberHandle = IntPtr.Zero; + private string _applicationId = string.Empty; + private Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None; + + // Cached path fields + private string _sharedDataPath = null; + private string _sharedResourcePath = null; + private string _sharedTrustedPath = null; + private string _externalSharedDataPath = null; + private string _commonSharedDataPath = null; + private string _commonSharedTrustedPath = null; + + internal TeamApplicationInfo(IntPtr memberHandle, string applicationId) + { + _memberHandle = memberHandle; + _applicationId = applicationId; + } + + ~TeamApplicationInfo() + { + Dispose(false); + } + + public string ApplicationId + { + get + { + return _applicationId; + } + } + + public string PackageId + { + get + { + IntPtr infoHandle = GetInfoHandle(); + string packageid = string.Empty; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoGetPackage(infoHandle, out packageid); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the package id of " + _applicationId + ". err = " + err); + } + } + return packageid; + } + } + + public string Label + { + get + { + IntPtr infoHandle = GetInfoHandle(); + string label = string.Empty; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoGetLabel(infoHandle, out label); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the app label of " + _applicationId + ". err = " + err); + } + } + return label; + } + } + + public string ExecutablePath + { + get + { + IntPtr infoHandle = GetInfoHandle(); + string exec = string.Empty; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoGetExec(infoHandle, out exec); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the executable file path of " + _applicationId + ". err = " + err); + } + } + return exec; + } + } + + public string IconPath + { + get + { + IntPtr infoHandle = GetInfoHandle(); + string path = string.Empty; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoGetIcon(infoHandle, out path); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the app icon path of " + _applicationId + ". err = " + err); + } + } + return path; + } + } + + public string ApplicationType + { + get + { + IntPtr infoHandle = GetInfoHandle(); + string type = string.Empty; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoGetType(infoHandle, out type); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the application type of " + _applicationId + ". err = " + err); + } + } + return type; + } + } + + public ApplicationComponentType ComponentType + { + get + { + IntPtr infoHandle = GetInfoHandle(); + Interop.ApplicationManager.AppInfoAppComponentType componentType = 0; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoGetAppComponentType(infoHandle, out componentType); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the application component type of " + _applicationId + ". err = " + err); + } + } + return (ApplicationComponentType)componentType; + } + } + + public IDictionary Metadata + { + get + { + IDictionary metadata = new Dictionary(); + + Interop.ApplicationManager.AppInfoMetadataCallback cb = (string key, string value, IntPtr userData) => + { + if (key.Length != 0) + { + if (!metadata.ContainsKey(key)) + metadata.Add(key, value); + } + return true; + }; + + IntPtr infoHandle = GetInfoHandle(); + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoForeachMetadata(infoHandle, cb, IntPtr.Zero); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get application metadata of " + _applicationId + ". err = " + err); + } + } + + GC.KeepAlive(cb); + + return metadata; + } + } + + public bool IsNoDisplay + { + get + { + IntPtr infoHandle = GetInfoHandle(); + bool nodisplay = false; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoIsNodisplay(infoHandle, out nodisplay); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the IsNoDisplay value of " + _applicationId + ". err = " + err); + + } + } + return nodisplay; + } + } + + public bool IsOnBoot + { + get + { + IntPtr infoHandle = GetInfoHandle(); + bool onboot = false; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoIsOnBoot(infoHandle, out onboot); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the IsOnBoot value of " + _applicationId + ". err = " + err); + } + } + return onboot; + } + } + + public bool IsPreload + { + get + { + IntPtr infoHandle = GetInfoHandle(); + bool preloaded = false; + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoIsPreLoad(infoHandle, out preloaded); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the IsPreload value of " + _applicationId + ". err = " + err); + } + } + return preloaded; + } + } + + public IEnumerable Categories + { + get + { + List categories = new List(); + + Interop.ApplicationManager.AppInfoCategoryCallback cb = (string category, IntPtr userData) => + { + categories.Add(category); + return true; + }; + + IntPtr infoHandle = GetInfoHandle(); + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoForeachCategory(infoHandle, cb, IntPtr.Zero); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get application category of " + _applicationId + ". err = " + err); + } + } + + GC.KeepAlive(cb); + + return categories; + } + } + + public string SharedDataPath + { + get + { + if (_sharedDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetSharedDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the SharedDataPath of " + _applicationId + ". err = " + err); + } + _sharedDataPath = path; + } + return _sharedDataPath; + } + } + + public string SharedResourcePath + { + get + { + if (_sharedResourcePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetSharedResourcePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the SharedResourcePath of " + _applicationId + ". err = " + err); + } + _sharedResourcePath = path; + } + return _sharedResourcePath; + } + } + + public string SharedTrustedPath + { + get + { + if (_sharedTrustedPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetSharedTrustedPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the SharedTrustedPath of " + _applicationId + ". err = " + err); + } + _sharedTrustedPath = path; + } + return _sharedTrustedPath; + } + } + + public string ExternalSharedDataPath + { + get + { + if (_externalSharedDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetExternSharedDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the ExternalSharedDataPath of " + _applicationId + ". err = " + err); + } + _externalSharedDataPath = path; + } + return _externalSharedDataPath; + } + } + + public IEnumerable ResourceControls + { + get + { + List resourceControls = new List(); + Interop.ApplicationManager.AppInfoResControlCallback cb = (string resType, string minResourceVersion, string maxResourceVersion, string isAutoClose, IntPtr userData) => + { + resourceControls.Add(new ResourceControl(resType, minResourceVersion, maxResourceVersion, isAutoClose == "true")); + return true; + }; + + IntPtr infoHandle = GetInfoHandle(); + if (infoHandle != IntPtr.Zero) + { + err = Interop.ApplicationManager.AppInfoForeachResControl(infoHandle, cb, IntPtr.Zero); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the resource controls of " + _applicationId + ". err = " + err); + } + } + + GC.KeepAlive(cb); + + return resourceControls; + } + } + + public string GetLocalizedLabel(string locale) + { + string label = string.Empty; + err = Interop.ApplicationManager.AppInfoGetLocaledLabel(ApplicationId, locale, out label); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the GetLocalizedLabel of " + _applicationId + ". err = " + err); + label = Label; + } + return label; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public string CommonSharedDataPath + { + get + { + if (_commonSharedDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCommonSharedDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the CommonSharedDataPath of " + _applicationId + ". err = " + err); + } + _commonSharedDataPath = path; + } + return _commonSharedDataPath; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public string CommonSharedTrustedPath + { + get + { + if (_commonSharedTrustedPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCommonSharedTrustedPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the CommonSharedTrustedPath of " + _applicationId + ". err = " + err); + } + _commonSharedTrustedPath = path; + } + return _commonSharedTrustedPath; + } + } + + private IntPtr GetInfoHandle() + { + if (_infoHandle == IntPtr.Zero) + { + IntPtr infoHandle = IntPtr.Zero; + err = Interop.ApplicationManager.AppManagerGetAppInfo(_applicationId, out infoHandle); + if (err != Interop.ApplicationManager.ErrorCode.None) + { + Log.Warn(LogTag, "Failed to get the handle of the ApplicationInfo. err = " + err); + } + _infoHandle = infoHandle; + } + return _infoHandle; + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + +#pragma warning disable CA1063 + private void Dispose(bool disposing) +#pragma warning restore CA1063 + { + if (_disposed) + return; + if (disposing) + { + } + if (_infoHandle != IntPtr.Zero) + { + Interop.ApplicationManager.AppInfoDestroy(_infoHandle); + _infoHandle = IntPtr.Zero; + } + _disposed = true; + } + } +} diff --git a/src/Tizen.Applications.Team/TeamCoreApplication.cs b/src/Tizen.Applications.Team/TeamCoreApplication.cs new file mode 100644 index 00000000000..64cb0b5acfc --- /dev/null +++ b/src/Tizen.Applications.Team/TeamCoreApplication.cs @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Globalization; +using System.Threading.Tasks; +using Tizen.Applications.CoreBackend; + +namespace Tizen.Applications +{ + public class TeamCoreApplication : TeamApplication + { + protected TeamCoreApplication(TeamCoreBackend backend) : base(backend) + { + Log.Info(LogTag, "TeamCoreApplication constructor called"); + } + public event EventHandler Created; + public event EventHandler Terminated; + public event EventHandler AppControlReceived; + public event EventHandler LowMemory; + public event EventHandler LowBattery; + public event EventHandler LocaleChanged; + public event EventHandler RegionFormatChanged; + public event EventHandler DeviceOrientationChanged; + public event EventHandler TimeZoneChanged; + public override void Run(string[] args) + { + base.Run(args); + + Backend.AddEventHandler(EventType.Created, OnCreate); + Backend.AddEventHandler(EventType.Terminated, OnTerminate); + Backend.AddEventHandler(EventType.AppControlReceived, OnAppControlReceived); + Backend.AddEventHandler(EventType.LowMemory, OnLowMemory); + Backend.AddEventHandler(EventType.LowBattery, OnLowBattery); + Backend.AddEventHandler(EventType.LocaleChanged, OnLocaleChanged); + Backend.AddEventHandler(EventType.RegionFormatChanged, OnRegionFormatChanged); + Backend.AddEventHandler(EventType.DeviceOrientationChanged, OnDeviceOrientationChanged); + Backend.AddEventHandler(EventType.TimeZoneChanged, OnTimeZoneChanged); + + _backend.Run(args); + } + + protected virtual void OnCreate() + { + if (!GlobalizationMode.Invariant) + { + string locale = SystemLocaleConverter.ULocale.GetDefaultLocale(); + + TeamLocaleManager.SetCurrentUICultureInfo(locale); + TeamLocaleManager.SetCurrentCultureInfo(locale); + } + else + { + Log.Warn(LogTag, "Run in invariant mode"); + } + + Created?.Invoke(this, EventArgs.Empty); + } + + protected virtual void OnTerminate() + { + Log.Info(LogTag, "TeamCoreApplication.OnTerminate() called"); + Terminated?.Invoke(this, EventArgs.Empty); + } + + protected virtual void OnAppControlReceived(AppControlReceivedEventArgs e) + { + Log.Info(LogTag, "TeamCoreApplication.OnAppControlReceived() called"); + if (e == null) + { + Log.Error(LogTag, "e is null"); + return; + } + + AppControlReceived?.Invoke(this, e); + } + + protected virtual void OnLowMemory(LowMemoryEventArgs e) + { + Log.Info(LogTag, $"TeamCoreApplication.OnLowMemory() called - Status: {e?.LowMemoryStatus}"); + if (e == null) + { + Log.Error(LogTag, "e is null"); + return; + } + + LowMemory?.Invoke(this, e); + if (e.LowMemoryStatus == LowMemoryStatus.SoftWarning || e.LowMemoryStatus == LowMemoryStatus.HardWarning) + { + GC.Collect(); + } + } + + protected virtual void OnLowBattery(LowBatteryEventArgs e) + { + Log.Info(LogTag, $"TeamCoreApplication.OnLowBattery() called - Status: {e?.LowBatteryStatus}"); + if (e == null) + { + Log.Error(LogTag, "e is null"); + return; + } + + LowBattery?.Invoke(this, e); + } + + protected virtual void OnLocaleChanged(LocaleChangedEventArgs e) + { + Log.Info(LogTag, $"TeamCoreApplication.OnLocaleChanged() called - Locale: {e?.Locale}"); + if (e == null) + { + Log.Error(LogTag, "e is null"); + return; + } + + if (!GlobalizationMode.Invariant) + { + TeamLocaleManager.SetCurrentUICultureInfo(e.Locale); + } + + LocaleChanged?.Invoke(this, e); + } + + protected virtual void OnRegionFormatChanged(RegionFormatChangedEventArgs e) + { + Log.Info(LogTag, $"TeamCoreApplication.OnRegionFormatChanged() called - Region: {e?.Region}"); + if (e == null) + { + Log.Error(LogTag, "e is null"); + return; + } + + if (!GlobalizationMode.Invariant) + { + TeamLocaleManager.SetCurrentCultureInfo(e.Region); + } + + RegionFormatChanged?.Invoke(this, e); + } + + protected virtual void OnDeviceOrientationChanged(DeviceOrientationEventArgs e) + { + Log.Info(LogTag, $"TeamCoreApplication.OnDeviceOrientationChanged() called - Orientation: {e?.DeviceOrientation}"); + DeviceOrientationChanged?.Invoke(this, e); + } + + protected virtual void OnTimeZoneChanged(TimeZoneChangedEventArgs e) + { + Log.Info(LogTag, $"TeamCoreApplication.OnTimeZoneChanged() called - TimeZone: {e?.TimeZone}, ID: {e?.TimeZoneId}"); + CultureInfo.CurrentCulture.ClearCachedData(); + TimeZoneChanged?.Invoke(this, e); + } + + public static void Post(Action runner) + { + Log.Info(LogTag, "TeamCoreApplication.Post(Action) called"); + if (runner == null) + { + throw new ArgumentNullException(nameof(runner)); + } + + GSourceManager.Post(runner); + } + + public static async Task Post(Func runner) + { + Log.Info(LogTag, $"TeamCoreApplication.Post() called - Type: {typeof(T).Name}"); + if (runner == null) + { + throw new ArgumentNullException(nameof(runner)); + } + + var task = new TaskCompletionSource(); + GSourceManager.Post(() => { task.SetResult(runner()); } ); + return await task.Task.ConfigureAwait(false); + } + } + + internal static class GlobalizationMode + { + private static int _invariant = -1; + + internal static bool Invariant + { + get + { + if (_invariant == -1) + { + string value = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_GLOBALIZATION_INVARIANT"); + _invariant = value != null ? (value.Equals("1") ? 1 : 0) : 0; + } + + return _invariant != 0; + } + } + } + + internal static class TeamLocaleManager + { + private static readonly string LogTag = "DN_TAM"; + + internal static void SetCurrentCultureInfo(string locale) + { + var converter = new SystemLocaleConverter(); + CultureInfo cultureInfo = converter.Convert(locale); + if (cultureInfo != null) + { + CultureInfo.CurrentCulture = cultureInfo; + } + else + { + Log.Error(LogTag, $"CultureInfo is null. locale: {locale}"); + } + } + + internal static void SetCurrentUICultureInfo(string locale) + { + var converter = new SystemLocaleConverter(); + CultureInfo cultureInfo = converter.Convert(locale); + if (cultureInfo != null) + { + CultureInfo.CurrentUICulture = cultureInfo; + } + else + { + Log.Error(LogTag, $"CultureInfo is null. locale: {locale}"); + } + } + } +} diff --git a/src/Tizen.Applications.Team/TeamCoreUiApplication.cs b/src/Tizen.Applications.Team/TeamCoreUiApplication.cs new file mode 100644 index 00000000000..09d822fec86 --- /dev/null +++ b/src/Tizen.Applications.Team/TeamCoreUiApplication.cs @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +using System; +using Tizen.Applications.CoreBackend; +using Tizen.NUI; + +namespace Tizen.Applications +{ + public class TeamCoreUiApplication : TeamCoreApplication + { + public TeamCoreUiApplication() : base(new TeamUICoreBackend()) + { + } + + public Window GetDefaultWindow() + { + return ((TeamUICoreBackend)Backend).GetDefaultWindow(); + } + + public event EventHandler Resumed; + public event EventHandler Paused; + public override void Run(string[] args) + { + Backend.AddEventHandler(EventType.Resumed, OnResume); + Backend.AddEventHandler(EventType.Paused, OnPause); + + base.Run(args); + } + + protected override void OnCreate() + { + base.OnCreate(); + } + protected virtual void OnResume() + { + Resumed?.Invoke(this, EventArgs.Empty); + } + protected virtual void OnPause() + { + Paused?.Invoke(this, EventArgs.Empty); + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/TeamDirectoryInfo.cs b/src/Tizen.Applications.Team/TeamDirectoryInfo.cs new file mode 100644 index 00000000000..9c3f592149d --- /dev/null +++ b/src/Tizen.Applications.Team/TeamDirectoryInfo.cs @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.ComponentModel; +using System.IO; +using Tizen.Internals; +using Tizen.Internals.Errors; + +namespace Tizen.Applications +{ + public class TeamDirectoryInfo + { + private IntPtr _memberHandle; + private string _dataPath; + private string _cachePath; + private string _resourcePath; + private string _sharedDataPath; + private string _sharedResourcePath; + private string _sharedTrustedPath; + private string _externalDataPath; + private string _externalCachePath; + private string _externalSharedDataPath; + private string _expansionPackageResourcePath; + private string _commonDataPath; + private string _commonCachePath; + private string _commonSharedDataPath; + private string _commonSharedTrustedPath; + + internal TeamDirectoryInfo(IntPtr memberHandle) + { + _memberHandle = memberHandle; + } + + public string Data + { + get + { + if (_dataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("Data", err); + _dataPath = path; + } + return _dataPath; + } + } + + public string Cache + { + get + { + if (_cachePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCachePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("Cache", err); + _cachePath = path; + } + return _cachePath; + } + } + + public string Resource + { + get + { + if (_resourcePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetResourcePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("Resource", err); + _resourcePath = path; + } + return _resourcePath; + } + } + + public string SharedData + { + get + { + if (_sharedDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetSharedDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("SharedData", err); + _sharedDataPath = path; + } + return _sharedDataPath; + } + } + + public string SharedResource + { + get + { + if (_sharedResourcePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetSharedResourcePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("SharedResource", err); + _sharedResourcePath = path; + } + return _sharedResourcePath; + } + } + + public string SharedTrusted + { + get + { + if (_sharedTrustedPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetSharedTrustedPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("SharedTrusted", err); + _sharedTrustedPath = path; + } + return _sharedTrustedPath; + } + } + + public string ExternalData + { + get + { + if (_externalDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetExternDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("ExternalData", err); + _externalDataPath = path; + } + return _externalDataPath; + } + } + + public string ExternalCache + { + get + { + if (_externalCachePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetExternCachePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("ExternalCache", err); + _externalCachePath = path; + } + return _externalCachePath; + } + } + + public string ExternalSharedData + { + get + { + if (_externalSharedDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetExternSharedDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("ExternalSharedData", err); + _externalSharedDataPath = path; + } + return _externalSharedDataPath; + } + } + + public string ExpansionPackageResource + { + get + { + if (_expansionPackageResourcePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetTepResourcePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("ExpansionPackageResource", err); + _expansionPackageResourcePath = path; + } + return _expansionPackageResourcePath; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public string CommonData + { + get + { + if (_commonDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCommonDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("CommonData", err); + _commonDataPath = path; + } + return _commonDataPath; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public string CommonCache + { + get + { + if (_commonCachePath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCommonCachePath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("CommonCache", err); + _commonCachePath = path; + } + return _commonCachePath; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public string CommonSharedData + { + get + { + if (_commonSharedDataPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCommonSharedDataPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("CommonSharedData", err); + _commonSharedDataPath = path; + } + return _commonSharedDataPath; + } + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public string CommonSharedTrusted + { + get + { + if (_commonSharedTrustedPath == null) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetCommonSharedTrustedPath(_memberHandle, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError("CommonSharedTrusted", err); + _commonSharedTrustedPath = path; + } + return _commonSharedTrustedPath; + } + } + + public string GetResourceControlAllowedResource(string resType) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetResControlAllowedPath(_memberHandle, resType, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError($"GetResourceControlAllowedResource({resType})", err); + return path; + } + + public string GetResourceControlGlobalResource(string resType) + { + Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetResControlGlobalPath(_memberHandle, resType, out string path); + if (err != Interop.TeamManager.TeamAppErrorCode.None) + throw GetExceptionFromError($"GetResourceControlGlobalResource({resType})", err); + return path; + } + + private Exception GetExceptionFromError(string operationName, Interop.TeamManager.TeamAppErrorCode err) + { + switch (err) + { + case Interop.TeamManager.TeamAppErrorCode.InvalidParameter: + return new ArgumentException($"Invalid Arguments for {operationName}"); + case Interop.TeamManager.TeamAppErrorCode.OutOfMemory: + return new OutOfMemoryException($"Out of memory for {operationName}"); + case Interop.TeamManager.TeamAppErrorCode.InvalidContext: + return new InvalidOperationException($"Invalid team member context for {operationName}"); + case Interop.TeamManager.TeamAppErrorCode.NoSuchMember: + return new DirectoryNotFoundException($"{operationName} not found"); + default: + return new InvalidOperationException($"Failed to get {operationName}"); + } + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/TeamLoop.cs b/src/Tizen.Applications.Team/TeamLoop.cs new file mode 100644 index 00000000000..21925328845 --- /dev/null +++ b/src/Tizen.Applications.Team/TeamLoop.cs @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +using System; +using System.Threading; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Text; +using Tizen.NUI; + +namespace Tizen.Applications +{ + public static class TeamLoop + { + private const string LogTag = "DN_TAM"; + private static Interop.TeamLoop.TeamLoopOperations _ops; + private static bool _isRunning = false; + private static string[] _systemArgs = null; + + static TeamLoop() + { + Log.Info(LogTag, "TeamLoop static constructor called"); + _ops.Load = new Interop.TeamLoop.TeamLoopOpsLoad(DoLoad); + _ops.Unload = new Interop.TeamLoop.TeamLoopOpsUnload(DoUnload); + _ops.CreateArgs = new Interop.TeamLoop.TeamLoopOpsCreateArgs(DoCreateArgs); + _ops.CreateLibPath = new Interop.TeamLoop.TeamLoopOpsCreateLibPath(DoCreateLibPath); + _ops.OnLoopCreate = new Interop.TeamLoop.TeamLoopOpsOnLoopCreate(DoOnLoopCreate); + _ops.OnLoopTerminate = new Interop.TeamLoop.TeamLoopOpsOnLoopTerminate(DoOnLoopTerminate); + } + public static void Run(string[] args) + { + Log.Info(LogTag, $"Run() called - Already Running: {_isRunning}"); + if(_isRunning) + { + return; + } + + _isRunning = true; + _systemArgs = args; + + Log.Info("NUI", "[NUI] NUIApplicationInitializer: StaticInitialize"); + Registry.Instance.SavedApplicationThread = Thread.CurrentThread; + PropertyBridge.RegisterStringGetter(); + Log.Info("NUI", "[NUI] NUIApplicationInitializer: StaticInitialize done"); + + var err = Interop.TeamLoop.Main(args.Length, args, _ops); + if (err != 0) + { + Log.Error(LogTag, "Failed to Initialize TeamLoop"); + } + else + { + Log.Info(LogTag, "TeamLoop Run"); + } + } + + public static bool IsRunning() + { + Log.Info(LogTag, $"IsRunning() called - Result: {_isRunning}"); + return _isRunning; + } + + internal static IntPtr DoLoad(string path) + { + if (string.IsNullOrEmpty(path)) + { + Log.Error(LogTag, "Invalid path: null or empty"); + return IntPtr.Zero; + } + + try + { + Log.Info(LogTag, $"Loading assembly: {path}"); + + TeamAssemblyLoadContext context = new TeamAssemblyLoadContext(); + WeakReference contextRef = new WeakReference(context); + + Assembly assembly = context.LoadFromAssemblyPath(path); + + var info = new AssemblyInfo(assembly, path, contextRef); + IntPtr id = TeamManager.RegisterAssemblyInfo(info); + + Log.Info(LogTag, $"Assembly loaded successfully: {path}, ID: {id}"); + return id; + } + catch (Exception e) + { + Log.Error(LogTag, $"Failed to load assembly: {path}, Error: {e.Message}"); + return IntPtr.Zero; + } + } + + internal static void DoUnload(IntPtr loadObj) + { + if (loadObj == IntPtr.Zero) + { + Log.Error(LogTag, "Invalid loadObj: IntPtr.Zero"); + return; + } + + var assemblyInfo = TeamManager.GetAssembly(loadObj); + if (assemblyInfo == null) + { + Log.Error(LogTag, $"Assembly not found for id: {loadObj}"); + return; + } + + Log.Info(LogTag, $"Unloading assembly - ID: {loadObj}, Path: {assemblyInfo.Path}"); + + if (assemblyInfo.LoadContextRef.IsAlive) + { + var context = assemblyInfo.LoadContextRef.Target as TeamAssemblyLoadContext; + context.Unload(); + Log.Info(LogTag, $"AssemblyLoadContext unloaded - ID: {loadObj}"); + } + else + { + Log.Warn(LogTag, $"AssemblyLoadContext already collected - ID: {loadObj}"); + } + + TeamManager.UnregisterAssembly(loadObj); + + GC.Collect(); + GC.WaitForPendingFinalizers(); + + Log.Info(LogTag, $"Assembly unloaded - ID: {loadObj}, Path: {assemblyInfo.Path}"); + } + + internal static IntPtr DoCreateArgs(IntPtr loadObj) + { + if (loadObj == IntPtr.Zero) + { + Log.Error(LogTag, "Invalid loadObj id: IntPtr.Zero"); + return IntPtr.Zero; + } + + var assemblyInfo = TeamManager.GetAssembly(loadObj); + if (assemblyInfo == null) + { + Log.Error(LogTag, $"Assembly not found for id: {loadObj}"); + return IntPtr.Zero; + } + + try + { + var mainMethod = assemblyInfo.Assembly.EntryPoint; + Log.Info(LogTag, $"Main method {mainMethod.Name}"); + + if (mainMethod == null) + { + Log.Error(LogTag, $"Entry point not found in assembly: {assemblyInfo.Path}"); + return IntPtr.Zero; + } + + string[] args = (string[])GetSystemArgs().Clone(); + args[0] = TeamManager.GetAssembly(loadObj).Path; + Log.Info(LogTag, $"args count: {args.Length}"); + for (int i = 0; i < args.Length; i++) + { + Log.Info(LogTag, $" args[{i}] = {args[i]}"); + } + + mainMethod.Invoke(null, new object[] { args }); + + var argHandle = TeamManager.GetArgHandle(loadObj); + Log.Info(LogTag, $"Main method invoked successfully - ID: {loadObj}, Result: {argHandle}"); + return argHandle; + } + catch (Exception e) + { + Log.Error(LogTag, $"Failed to invoke Main method - ID: {loadObj}, Error: {e.Message}"); + return IntPtr.Zero; + } + } + + internal static void DoCreateLibPath(string path, ref IntPtr output) + { + if (string.IsNullOrEmpty(path)) + { + Log.Error(LogTag, "Invalid path: null or empty"); + output = IntPtr.Zero; + return; + } + + int lastDotIndex = path.LastIndexOf('.'); + if (lastDotIndex < 0) + { + Log.Error(LogTag, $"Invalid path format: {path}. Expected format: org.appfw.csteam.{{member_id}}"); + output = IntPtr.Zero; + return; + } + + string memberId = path.Substring(lastDotIndex + 1); + if (string.IsNullOrEmpty(memberId)) + { + Log.Error(LogTag, $"Empty member_id extracted from: {path}"); + output = IntPtr.Zero; + return; + } + + string libPath = $"/usr/share/csteam/dll/{memberId}.dll"; + Log.Info(LogTag, $"Created lib path: {libPath} from {path}"); + + output = Marshal.StringToHGlobalAnsi(libPath); + + if (output == IntPtr.Zero) { + Log.Error(LogTag, "Failed to allocate memory for lib path"); + } + } + + public static string[] GetSystemArgs() + { + Log.Info(LogTag, $"GetSystemArgs() called - Count: {_systemArgs?.Length ?? 0}"); + return _systemArgs; + } + + internal static void DoOnLoopCreate() + { + Log.Info(LogTag, "DoOnLoopCreate() called"); + + Log.Info("NUI", "[NUI] NUIApplicationInitializer: ProcessorController Initialize"); + Tracer.Begin("[NUI] NUIApplicationInitializer: ProcessorController Initialize"); + ProcessorController.Instance.Initialize(); + Tracer.End(); + + // Initialize DisposeQueue Singleton class. This is also required to create DisposeQueue on main thread. + Log.Info("NUI", "[NUI] NUIApplicationInitializer: DisposeQueue Initialize"); + Tracer.Begin("[NUI] NUIApplicationInitializer: DisposeQueue Initialize"); + DisposeQueue.Instance.Initialize(); + Tracer.End(); + + // Empty implementation for C# launcher + } + + internal static void DoOnLoopTerminate() + { + Log.Info(LogTag, "DoOnLoopTerminate() called"); + // Empty implementation for C# launcher + } + + } +} diff --git a/src/Tizen.Applications.Team/TeamManager.cs b/src/Tizen.Applications.Team/TeamManager.cs new file mode 100644 index 00000000000..840f77edfaa --- /dev/null +++ b/src/Tizen.Applications.Team/TeamManager.cs @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.Loader; +using Tizen.NUI.BaseComponents; + +namespace Tizen.Applications +{ + internal class TeamAssemblyLoadContext : AssemblyLoadContext + { + public TeamAssemblyLoadContext() : base(isCollectible: true) { } + + protected override Assembly Load(AssemblyName name) => null; + } + + internal class AssemblyInfo + { + public Assembly Assembly { get; } + public string Path { get; } + public WeakReference LoadContextRef { get; } + + public AssemblyInfo(Assembly assembly, string path, WeakReference contextRef) + { + Assembly = assembly; + Path = path; + LoadContextRef = contextRef; + } + } + + internal class ViewInfo + { + public View View { get; set; } + public string Appid { get; set; } + public bool Owned { get; set; } + } + + public static class TeamManager + { + private const string LogTag = "DN_TAM"; + private static readonly Dictionary _assemblies = new Dictionary(); + private static readonly Dictionary _assembliesByPath = new Dictionary(); + private static readonly Dictionary _argHandles = new Dictionary(); + private static readonly HashSet _runningApps = new HashSet(); + private static readonly object _lock = new object(); + private static int _assemblyId = 1; + + private static readonly Dictionary _viewInfos = new Dictionary(); + private static readonly Dictionary _viewByAppId = new Dictionary(); + private static int _viewIdCounter = 1; + + internal static IntPtr RegisterAssemblyInfo(AssemblyInfo info) + { + lock (_lock) + { + IntPtr id = new IntPtr(_assemblyId); + _assemblies[id] = info; + _assembliesByPath[info.Path] = id; + + Log.Info(LogTag, $"Assembly registered - ID: {_assemblyId}, Path: {info.Path}"); + + _assemblyId++; + return id; + } + } + + internal static void UnregisterAssembly(IntPtr id) + { + lock (_lock) + { + if (_assemblies.TryGetValue(id, out var info)) + { + _assembliesByPath.Remove(info.Path); + } + _assemblies.Remove(id); + } + } + + internal static AssemblyInfo GetAssembly(IntPtr id) + { + lock (_lock) + { + if (_assemblies.TryGetValue(id, out var info)) + { + return info; + } + } + return null; + } + + public static void Init(string[] args) + { + TeamLoop.Run(args); + } + + public static bool IsInit() + { + return TeamLoop.IsRunning(); + } + + internal static IntPtr GetAssemblyIdByPath(string path) + { + lock (_lock) + { + if (_assembliesByPath.TryGetValue(path, out var id)) + { + return id; + } + } + return IntPtr.Zero; + } + + internal static void RegisterArgHandle(IntPtr id, IntPtr argHandle) + { + lock (_lock) + { + _argHandles[id] = argHandle; + Log.Info(LogTag, $"ArgHandle registered - ID: {id}, ArgHandle: {argHandle}"); + } + } + + internal static void UnregisterArgHandle(IntPtr id) + { + lock (_lock) + { + _argHandles.Remove(id); + Log.Info(LogTag, $"ArgHandle unregistered - ID: {id}"); + } + } + + internal static IntPtr GetArgHandle(IntPtr id) + { + lock (_lock) + { + if (_argHandles.TryGetValue(id, out var argHandle)) + { + return argHandle; + } + } + return IntPtr.Zero; + } + + internal static void RegisterRunningTeamApp(TeamApplication app) + { + lock (_lock) + { + if (_runningApps.Add(app)) + { + Log.Info(LogTag, $"TeamApplication registered"); + } + } + } + + internal static void UnRegisterRunningTeamApp(TeamApplication app) + { + lock (_lock) + { + if (_runningApps.Remove(app)) + { + Log.Info(LogTag, $"TeamApplication unregistered"); + } + } + } + + public static int AddView(View view, string appid) + { + if (view == null) + throw new ArgumentNullException(nameof(view)); + if (string.IsNullOrEmpty(appid)) + throw new ArgumentNullException(nameof(appid)); + + lock (_lock) + { + if (_viewByAppId.ContainsKey(appid)) + { + throw new ArgumentException($"AppId '{appid}' already exists.", nameof(appid)); + } + + int id = _viewIdCounter++; + _viewInfos[id] = new ViewInfo { View = view, Appid = appid, Owned = false }; + _viewByAppId[appid] = id; + + Log.Info(LogTag, $"View added - ID: {id}, AppId: {appid}"); + return id; + } + } + + public static bool RemoveView(int id) + { + lock (_lock) + { + if (_viewInfos.TryGetValue(id, out var info)) + { + _viewInfos.Remove(id); + _viewByAppId.Remove(info.Appid); + Log.Info(LogTag, $"View removed - ID: {id}, Appid: {info.Appid}"); + return true; + } + return false; + } + } + + public static View OwnViewApp(string appid) + { + if (string.IsNullOrEmpty(appid)) + throw new ArgumentNullException(nameof(appid)); + + lock (_lock) + { + if (_viewByAppId.TryGetValue(appid, out var id)) + { + if (_viewInfos.TryGetValue(id, out var info)) + { + if (info.Owned) + { + Log.Error(LogTag, $"View already owned - AppId: {appid}"); + return null; + } + info.Owned = true; + Log.Info(LogTag, $"View owned - AppId: {appid}"); + return info.View; + } + } + Log.Warn(LogTag, $"View not found for own - AppId: {appid}"); + return null; + } + } + + public static void DisownViewApp(string appid) + { + if (string.IsNullOrEmpty(appid)) + throw new ArgumentNullException(nameof(appid)); + + lock (_lock) + { + if (_viewByAppId.TryGetValue(appid, out var id)) + { + if (_viewInfos.TryGetValue(id, out var info)) + { + if (!info.Owned) + { + Log.Error(LogTag, $"View already disowned - AppId: {appid}"); + return; + } + info.Owned = false; + Log.Info(LogTag, $"View disowned - AppId: {appid}"); + } + } + else + { + Log.Warn(LogTag, $"View not found for disown - AppId: {appid}"); + } + } + } + + } +} diff --git a/src/Tizen.Applications.Team/TeamServiceApplication.cs b/src/Tizen.Applications.Team/TeamServiceApplication.cs new file mode 100644 index 00000000000..9bb37599867 --- /dev/null +++ b/src/Tizen.Applications.Team/TeamServiceApplication.cs @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using System.Runtime.CompilerServices; +using Tizen.Applications.CoreBackend; + +namespace Tizen.Applications +{ + public class TeamServiceApplication : TeamCoreApplication + { +#pragma warning disable CA2000 + public TeamServiceApplication() : base(new TeamServiceCoreBackend()) +#pragma warning restore CA2000 + { + } + public override void Run(string[] args) + { + base.Run(args); + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/TeamUiApplication.cs b/src/Tizen.Applications.Team/TeamUiApplication.cs new file mode 100644 index 00000000000..b90bdd79506 --- /dev/null +++ b/src/Tizen.Applications.Team/TeamUiApplication.cs @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using Tizen.NUI; + +namespace Tizen.Applications +{ + public class TeamUiApplication : TeamCoreUiApplication + { + public TeamUiApplication() + { + } + public override void Run(string[] args) + { + base.Run(args); + } + } +} diff --git a/src/Tizen.Applications.Team/TeamViewApplication.cs b/src/Tizen.Applications.Team/TeamViewApplication.cs new file mode 100644 index 00000000000..18dd476b2c6 --- /dev/null +++ b/src/Tizen.Applications.Team/TeamViewApplication.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + + +using System; +using Tizen.Applications.CoreBackend; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; + +namespace Tizen.Applications +{ + public class TeamViewApplication : TeamCoreApplication + { + public TeamViewApplication() : base(new TeamViewCoreBackend()) + { + } + + public View GetDefaultView() + { + return ((TeamViewCoreBackend)Backend).GetDefaultView(); + } + + public event EventHandler Resumed; + public event EventHandler Paused; + public override void Run(string[] args) + { + Backend.AddEventHandler(EventType.Resumed, OnResume); + Backend.AddEventHandler(EventType.Paused, OnPause); + + base.Run(args); + } + protected virtual void OnResume() + { + Resumed?.Invoke(this, EventArgs.Empty); + } + protected virtual void OnPause() + { + Paused?.Invoke(this, EventArgs.Empty); + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs new file mode 100644 index 00000000000..d7e603a4225 --- /dev/null +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; + +namespace Tizen.Applications.CoreBackend +{ + public abstract class TeamCoreBackend : DefaultCoreBackend + { + protected IntPtr _memberHandle = IntPtr.Zero; + protected IntPtr _loadObjId = IntPtr.Zero; + protected IntPtr _argHandle = IntPtr.Zero; + internal abstract IntPtr MemberHandle { get; } + internal abstract IntPtr LoadObjId { get; } + internal abstract IntPtr ArgHandle { get; } + } +} diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs new file mode 100644 index 00000000000..5b6f81ea24a --- /dev/null +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using Tizen.Internals; + +namespace Tizen.Applications.CoreBackend +{ + internal class TeamServiceCoreBackend : TeamCoreBackend + { + internal new static string LogTag = "DN_TAM"; + private Interop.TeamMember.ServiceMemberLifecycleCallbacks _callbacks; + private bool _disposedValue = false; + internal override IntPtr MemberHandle => _memberHandle; + internal override IntPtr LoadObjId => _loadObjId; + internal override IntPtr ArgHandle => _argHandle; + + private Interop.TeamMember.ServiceAppCreateCallback _onCreateNative; + private Interop.TeamMember.AppTerminateCallback _onTerminateNative; + private Interop.TeamMember.AppControlCallback _onAppControlNative; + private Interop.TeamMember.AppLowMemoryCallback _onLowMemoryNative; + private Interop.TeamMember.AppLowBatteryCallback _onLowBatteryNative; + private Interop.TeamMember.AppLanguageChangedCallback _onLanguageChangedNative; + private Interop.TeamMember.AppDeviceOrientationChangedCallback _onDeviceOrientationChangedNative; + private Interop.TeamMember.AppRegionFormatChangedCallback _onRegionFormatChangedNative; + private Interop.TeamMember.AppSuspendStateChangedCallback _onSuspendStateChangedNative; + private Interop.TeamMember.AppTimeZoneChangedCallback _onTimeZoneChangedNative; + + public TeamServiceCoreBackend() + { + _onCreateNative = new Interop.TeamMember.ServiceAppCreateCallback(OnCreateNative); + _onTerminateNative = new Interop.TeamMember.AppTerminateCallback(OnTerminateNative); + _onAppControlNative = new Interop.TeamMember.AppControlCallback(OnAppControlNative); + _onLowMemoryNative = new Interop.TeamMember.AppLowMemoryCallback(OnLowMemoryNative); + _onLowBatteryNative = new Interop.TeamMember.AppLowBatteryCallback(OnLowBatteryNative); + _onLanguageChangedNative = new Interop.TeamMember.AppLanguageChangedCallback(OnLanguageChangedNative); + _onDeviceOrientationChangedNative = new Interop.TeamMember.AppDeviceOrientationChangedCallback(OnDeviceOrientationChangedNative); + _onRegionFormatChangedNative = new Interop.TeamMember.AppRegionFormatChangedCallback(OnRegionFormatChangedNative); + _onSuspendStateChangedNative = new Interop.TeamMember.AppSuspendStateChangedCallback(OnSuspendStateChangedNative); + _onTimeZoneChangedNative = new Interop.TeamMember.AppTimeZoneChangedCallback(OnTimeZoneChangedNative); + + _callbacks.Create = _onCreateNative; + _callbacks.Terminate = _onTerminateNative; + _callbacks.Control = _onAppControlNative; + _callbacks.LowMemory = _onLowMemoryNative; + _callbacks.LowBattery = _onLowBatteryNative; + _callbacks.LanguageChanged = _onLanguageChangedNative; + _callbacks.DeviceOrientationChanged = _onDeviceOrientationChangedNative; + _callbacks.RegionFormatChanged = _onRegionFormatChangedNative; + _callbacks.SuspendStateChanged = _onSuspendStateChangedNative; + _callbacks.TimezoneChanged = _onTimeZoneChangedNative; + } + + public override void Exit() + { + if (_memberHandle != IntPtr.Zero) + { + Interop.TeamMember.ServiceMemberQuit(_memberHandle); + _memberHandle = IntPtr.Zero; + } + } + + public override void Run(string[] args) + { + // base.Run() is not required. + if (!TeamManager.IsInit()) + { + string[] argsClone = new string[args == null ? 1 : args.Length + 1]; + if (args != null && args.Length > 1) + { + args.CopyTo(argsClone, 1); + } + argsClone[0] = "Tizen.Applications.Team.dll"; + + TeamManager.Init(argsClone); + Log.Info("DN_TAM", $"Launching Team Loop."); + return; + } + + if (args == null || args.Length == 0) + { + Log.Error(LogTag, "args is null or empty"); + return; + } + + _loadObjId = TeamManager.GetAssemblyIdByPath(args[0]); + _argHandle = Interop.TeamMember.ServiceMemberTeamup(_callbacks, IntPtr.Zero); + TeamManager.RegisterArgHandle(_loadObjId, _argHandle); + Log.Info(LogTag, $"path: {args[0]}, id: {_loadObjId}, arg_h: {_argHandle}"); + } + + protected override void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + // Release disposable objects + } + + if (_memberHandle != IntPtr.Zero) + { + Interop.TeamMember.ServiceMemberQuit(_memberHandle); + _memberHandle = IntPtr.Zero; + } + + _disposedValue = true; + } + } + + private bool OnCreateNative(IntPtr context, IntPtr userdata) + { + if (_memberHandle != IntPtr.Zero) + { + Log.Warn(LogTag, "OnCreate called twice!"); + } + _memberHandle = context; + + if (Handlers.ContainsKey(EventType.Created)) + { + var handler = Handlers[EventType.Created] as Action; + if (handler != null) + { + try + { + handler.Invoke(); + Log.Warn(LogTag, $"Return True"); + return true; + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Created handler: {ex.Message}"); + return false; + } + } + } + + Log.Error(LogTag, "No OnCreate Callback"); + return false; + } + + private void OnTerminateNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Terminated)) + { + var handler = Handlers[EventType.Terminated] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Terminated handler: {ex.Message}"); + } + } + } + + private void OnAppControlNative(IntPtr context, IntPtr appControl, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.AppControlReceived)) + { + using (SafeAppControlHandle safeHandle = new SafeAppControlHandle(appControl, false)) + { + var handler = Handlers[EventType.AppControlReceived] as Action; + try + { + handler?.Invoke(new AppControlReceivedEventArgs(new ReceivedAppControl(safeHandle))); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in AppControlReceived handler: {ex.Message}"); + } + } + } + } + + private void OnLowMemoryNative(IntPtr context, int status, IntPtr userdata) + { + LowMemoryStatus lowMemoryStatus = (LowMemoryStatus)status; + if (Handlers.ContainsKey(EventType.LowMemory)) + { + var handler = Handlers[EventType.LowMemory] as Action; + try + { + handler?.Invoke(new LowMemoryEventArgs(lowMemoryStatus)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LowMemory handler: {ex.Message}"); + } + } + } + + private void OnLowBatteryNative(IntPtr context, int status, IntPtr userdata) + { + LowBatteryStatus lowBatteryStatus = (LowBatteryStatus)status; + if (Handlers.ContainsKey(EventType.LowBattery)) + { + var handler = Handlers[EventType.LowBattery] as Action; + try + { + handler?.Invoke(new LowBatteryEventArgs(lowBatteryStatus)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LowBattery handler: {ex.Message}"); + } + } + } + + private void OnLanguageChangedNative(IntPtr context, string language, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.LocaleChanged)) + { + var handler = Handlers[EventType.LocaleChanged] as Action; + try + { + handler?.Invoke(new LocaleChangedEventArgs(language)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LocaleChanged handler: {ex.Message}"); + } + } + } + + private void OnDeviceOrientationChangedNative(IntPtr context, int status, IntPtr userdata) + { + DeviceOrientation orientation = (DeviceOrientation)status; + if (Handlers.ContainsKey(EventType.DeviceOrientationChanged)) + { + var handler = Handlers[EventType.DeviceOrientationChanged] as Action; + try + { + handler?.Invoke(new DeviceOrientationEventArgs(orientation)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in DeviceOrientationChanged handler: {ex.Message}"); + } + } + } + + private void OnRegionFormatChangedNative(IntPtr context, string region, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.RegionFormatChanged)) + { + var handler = Handlers[EventType.RegionFormatChanged] as Action; + try + { + handler?.Invoke(new RegionFormatChangedEventArgs(region)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in RegionFormatChanged handler: {ex.Message}"); + } + } + } + + private void OnSuspendStateChangedNative(IntPtr context, int status, IntPtr userdata) + { + SuspendedState state = (SuspendedState)status; + if (Handlers.ContainsKey(EventType.SuspendedStateChanged)) + { + var handler = Handlers[EventType.SuspendedStateChanged] as Action; + try + { + handler?.Invoke(new SuspendedStateEventArgs(state)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in SuspendedStateChanged handler: {ex.Message}"); + } + } + } + + private void OnTimeZoneChangedNative(IntPtr context, string timeZone, string timeZoneId, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.TimeZoneChanged)) + { + var handler = Handlers[EventType.TimeZoneChanged] as Action; + try + { + handler?.Invoke(new TimeZoneChangedEventArgs(timeZone, timeZoneId)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in TimeZoneChanged handler: {ex.Message}"); + } + } + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs new file mode 100644 index 00000000000..151e1edd23a --- /dev/null +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using Tizen.Internals; +using Tizen.NUI; + +namespace Tizen.Applications.CoreBackend +{ + internal class TeamUICoreBackend : TeamCoreBackend + { + internal new static string LogTag = "DN_TAM"; + private Interop.TeamMember.UIMemberLifecycleCallbacks _callbacks; + private bool _disposedValue = false; + private int DefaultWindowId = 0; + internal Window defaultWindow; + internal override IntPtr MemberHandle => _memberHandle; + internal override IntPtr LoadObjId => _loadObjId; + internal override IntPtr ArgHandle => _argHandle; + + private Interop.TeamMember.UIAppCreateCallback _onCreateNative; + private Interop.TeamMember.AppTerminateCallback _onTerminateNative; + private Interop.TeamMember.AppControlCallback _onAppControlNative; + private Interop.TeamMember.AppResumeCallback _onResumeNative; + private Interop.TeamMember.AppPauseCallback _onPauseNative; + private Interop.TeamMember.AppLowMemoryCallback _onLowMemoryNative; + private Interop.TeamMember.AppLowBatteryCallback _onLowBatteryNative; + private Interop.TeamMember.AppLanguageChangedCallback _onLanguageChangedNative; + private Interop.TeamMember.AppDeviceOrientationChangedCallback _onDeviceOrientationChangedNative; + private Interop.TeamMember.AppRegionFormatChangedCallback _onRegionFormatChangedNative; + private Interop.TeamMember.AppSuspendStateChangedCallback _onSuspendStateChangedNative; + private Interop.TeamMember.AppTimeZoneChangedCallback _onTimeZoneChangedNative; + + public TeamUICoreBackend() + { + _onCreateNative = new Interop.TeamMember.UIAppCreateCallback(OnCreateNative); + _onTerminateNative = new Interop.TeamMember.AppTerminateCallback(OnTerminateNative); + _onAppControlNative = new Interop.TeamMember.AppControlCallback(OnAppControlNative); + _onResumeNative = new Interop.TeamMember.AppResumeCallback(OnResumeNative); + _onPauseNative = new Interop.TeamMember.AppPauseCallback(OnPauseNative); + _onLowMemoryNative = new Interop.TeamMember.AppLowMemoryCallback(OnLowMemoryNative); + _onLowBatteryNative = new Interop.TeamMember.AppLowBatteryCallback(OnLowBatteryNative); + _onLanguageChangedNative = new Interop.TeamMember.AppLanguageChangedCallback(OnLanguageChangedNative); + _onDeviceOrientationChangedNative = new Interop.TeamMember.AppDeviceOrientationChangedCallback(OnDeviceOrientationChangedNative); + _onRegionFormatChangedNative = new Interop.TeamMember.AppRegionFormatChangedCallback(OnRegionFormatChangedNative); + _onSuspendStateChangedNative = new Interop.TeamMember.AppSuspendStateChangedCallback(OnSuspendStateChangedNative); + _onTimeZoneChangedNative = new Interop.TeamMember.AppTimeZoneChangedCallback(OnTimeZoneChangedNative); + + _callbacks.Create = _onCreateNative; + _callbacks.Terminate = _onTerminateNative; + _callbacks.Control = _onAppControlNative; + _callbacks.Resume = _onResumeNative; + _callbacks.Pause = _onPauseNative; + _callbacks.LowMemory = _onLowMemoryNative; + _callbacks.LowBattery = _onLowBatteryNative; + _callbacks.LanguageChanged = _onLanguageChangedNative; + _callbacks.DeviceOrientationChanged = _onDeviceOrientationChangedNative; + _callbacks.RegionFormatChanged = _onRegionFormatChangedNative; + _callbacks.SuspendStateChanged = _onSuspendStateChangedNative; + _callbacks.TimezoneChanged = _onTimeZoneChangedNative; + } + + internal int GetDefaultWindowId() + { + return DefaultWindowId; + } + internal void SetDefaultWindowId(int windowId) + { + Log.Error(LogTag, $"SetDefaultWindowId: {windowId}"); + DefaultWindowId = windowId; + } + public Window GetDefaultWindow() + { + return defaultWindow; + } + internal void SetDefaultWindow(Window window) + { + defaultWindow = window; + SetDefaultWindowId(window.GetNativeId()); + } + public override void Exit() + { + if (_memberHandle != IntPtr.Zero) + { + Interop.TeamMember.UIMemberQuit(_memberHandle); + _memberHandle = IntPtr.Zero; + } + } + + public override void Run(string[] args) + { + // base.Run() is not required. + if (!TeamManager.IsInit()) + { + string[] argsClone = new string[args == null ? 1 : args.Length + 1]; + if (args != null && args.Length > 1) + { + args.CopyTo(argsClone, 1); + } + argsClone[0] = "Tizen.Applications.Team.dll"; + + TeamManager.Init(argsClone); + Log.Info("DN_TAM", $"Launching Team Loop."); + return; + } + + if (args == null || args.Length == 0) + { + Log.Error(LogTag, "args is null or empty"); + return; + } + + _loadObjId = TeamManager.GetAssemblyIdByPath(args[0]); + _argHandle = Interop.TeamMember.UIMemberTeamup(_callbacks, IntPtr.Zero); + TeamManager.RegisterArgHandle(_loadObjId, _argHandle); + Log.Info(LogTag, $"path: {args[0]}, id: {_loadObjId}, arg_h: {_argHandle}"); + } + + protected override void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + // Release disposable objects + } + + if (_memberHandle != IntPtr.Zero) + { + Interop.TeamMember.UIMemberQuit(_memberHandle); + _memberHandle = IntPtr.Zero; + } + + _disposedValue = true; + } + } + + private IntPtr OnCreateNative(IntPtr context, IntPtr userdata) + { + if (_memberHandle != IntPtr.Zero) + { + Log.Warn(LogTag, "OnCreate called twice!"); + } + _memberHandle = context; + + if (Handlers.ContainsKey(EventType.Created)) + { + var handler = Handlers[EventType.Created] as Action; + if (handler != null) + { + // This function will set default window + try + { + var window = new Window(); + SetDefaultWindow(window); + window.Hide(); + + try { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in User Created handler: {ex.Message}"); + } + + IntPtr window_h = Interop.TeamManager.CreateWl2WindowById(GetDefaultWindowId()); + return window_h; + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Internal Created handler: {ex.Message}"); + return IntPtr.Zero; + } + } + else + { + Log.Error(LogTag, "Invalid OnCreate Callback type"); + return IntPtr.Zero; + } + } + + Log.Error(LogTag, "No OnCreate Callback"); + return IntPtr.Zero; + } + + private void OnTerminateNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Terminated)) + { + var handler = Handlers[EventType.Terminated] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Terminated handler: {ex.Message}"); + } + + defaultWindow?.Hide(); + DefaultWindowId = -1; + defaultWindow = null; + } + } + + private void OnAppControlNative(IntPtr context, IntPtr appControl, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.AppControlReceived)) + { + using (SafeAppControlHandle safeHandle = new SafeAppControlHandle(appControl, false)) + { + var handler = Handlers[EventType.AppControlReceived] as Action; + try + { + handler?.Invoke(new AppControlReceivedEventArgs(new ReceivedAppControl(safeHandle))); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in AppControlReceived handler: {ex.Message}"); + } + } + } + } + + private void OnResumeNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Resumed)) + { + var handler = Handlers[EventType.Resumed] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Resumed handler: {ex.Message}"); + } + } + } + + private void OnPauseNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Paused)) + { + var handler = Handlers[EventType.Paused] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Paused handler: {ex.Message}"); + } + } + } + + private void OnLowMemoryNative(IntPtr context, int status, IntPtr userdata) + { + LowMemoryStatus lowMemoryStatus = (LowMemoryStatus)status; + if (Handlers.ContainsKey(EventType.LowMemory)) + { + var handler = Handlers[EventType.LowMemory] as Action; + try + { + handler?.Invoke(new LowMemoryEventArgs(lowMemoryStatus)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LowMemory handler: {ex.Message}"); + } + } + } + + private void OnLowBatteryNative(IntPtr context, int status, IntPtr userdata) + { + LowBatteryStatus lowBatteryStatus = (LowBatteryStatus)status; + if (Handlers.ContainsKey(EventType.LowBattery)) + { + var handler = Handlers[EventType.LowBattery] as Action; + try + { + handler?.Invoke(new LowBatteryEventArgs(lowBatteryStatus)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LowBattery handler: {ex.Message}"); + } + } + } + + private void OnLanguageChangedNative(IntPtr context, string language, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.LocaleChanged)) + { + var handler = Handlers[EventType.LocaleChanged] as Action; + try + { + handler?.Invoke(new LocaleChangedEventArgs(language)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LocaleChanged handler: {ex.Message}"); + } + } + } + + private void OnDeviceOrientationChangedNative(IntPtr context, int status, IntPtr userdata) + { + DeviceOrientation orientation = (DeviceOrientation)status; + if (Handlers.ContainsKey(EventType.DeviceOrientationChanged)) + { + var handler = Handlers[EventType.DeviceOrientationChanged] as Action; + try + { + handler?.Invoke(new DeviceOrientationEventArgs(orientation)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in DeviceOrientationChanged handler: {ex.Message}"); + } + } + } + + private void OnRegionFormatChangedNative(IntPtr context, string region, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.RegionFormatChanged)) + { + var handler = Handlers[EventType.RegionFormatChanged] as Action; + try + { + handler?.Invoke(new RegionFormatChangedEventArgs(region)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in RegionFormatChanged handler: {ex.Message}"); + } + } + } + + private void OnSuspendStateChangedNative(IntPtr context, int status, IntPtr userdata) + { + SuspendedState state = (SuspendedState)status; + if (Handlers.ContainsKey(EventType.SuspendedStateChanged)) + { + var handler = Handlers[EventType.SuspendedStateChanged] as Action; + try + { + handler?.Invoke(new SuspendedStateEventArgs(state)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in SuspendedStateChanged handler: {ex.Message}"); + } + } + } + + private void OnTimeZoneChangedNative(IntPtr context, string timeZone, string timeZoneId, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.TimeZoneChanged)) + { + var handler = Handlers[EventType.TimeZoneChanged] as Action; + try + { + handler?.Invoke(new TimeZoneChangedEventArgs(timeZone, timeZoneId)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in TimeZoneChanged handler: {ex.Message}"); + } + } + } + } +} diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs new file mode 100644 index 00000000000..69083906271 --- /dev/null +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2026 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +using System; +using Tizen.Internals; +using Tizen.NUI; +using Tizen.NUI.BaseComponents; + +namespace Tizen.Applications.CoreBackend +{ + internal class TeamViewCoreBackend : TeamCoreBackend + { + internal new static string LogTag = "DN_TAM"; + private Interop.TeamMember.ViewMemberLifecycleCallbacks _callbacks; + private bool _disposedValue = false; + private int DefaultViewId = 0; + internal View DefaultView; + internal override IntPtr MemberHandle => _memberHandle; + internal override IntPtr LoadObjId => _loadObjId; + internal override IntPtr ArgHandle => _argHandle; + + private Interop.TeamMember.ViewAppCreateCallback _onCreateNative; + private Interop.TeamMember.AppTerminateCallback _onTerminateNative; + private Interop.TeamMember.AppControlCallback _onAppControlNative; + private Interop.TeamMember.AppResumeCallback _onResumeNative; + private Interop.TeamMember.AppPauseCallback _onPauseNative; + private Interop.TeamMember.AppLowMemoryCallback _onLowMemoryNative; + private Interop.TeamMember.AppLowBatteryCallback _onLowBatteryNative; + private Interop.TeamMember.AppLanguageChangedCallback _onLanguageChangedNative; + private Interop.TeamMember.AppDeviceOrientationChangedCallback _onDeviceOrientationChangedNative; + private Interop.TeamMember.AppRegionFormatChangedCallback _onRegionFormatChangedNative; + private Interop.TeamMember.AppSuspendStateChangedCallback _onSuspendStateChangedNative; + private Interop.TeamMember.AppTimeZoneChangedCallback _onTimeZoneChangedNative; + + public TeamViewCoreBackend() + { + _onCreateNative = new Interop.TeamMember.ViewAppCreateCallback(OnCreateNative); + _onTerminateNative = new Interop.TeamMember.AppTerminateCallback(OnTerminateNative); + _onAppControlNative = new Interop.TeamMember.AppControlCallback(OnAppControlNative); + _onResumeNative = new Interop.TeamMember.AppResumeCallback(OnResumeNative); + _onPauseNative = new Interop.TeamMember.AppPauseCallback(OnPauseNative); + _onLowMemoryNative = new Interop.TeamMember.AppLowMemoryCallback(OnLowMemoryNative); + _onLowBatteryNative = new Interop.TeamMember.AppLowBatteryCallback(OnLowBatteryNative); + _onLanguageChangedNative = new Interop.TeamMember.AppLanguageChangedCallback(OnLanguageChangedNative); + _onDeviceOrientationChangedNative = new Interop.TeamMember.AppDeviceOrientationChangedCallback(OnDeviceOrientationChangedNative); + _onRegionFormatChangedNative = new Interop.TeamMember.AppRegionFormatChangedCallback(OnRegionFormatChangedNative); + _onSuspendStateChangedNative = new Interop.TeamMember.AppSuspendStateChangedCallback(OnSuspendStateChangedNative); + _onTimeZoneChangedNative = new Interop.TeamMember.AppTimeZoneChangedCallback(OnTimeZoneChangedNative); + + _callbacks.Create = _onCreateNative; + _callbacks.Terminate = _onTerminateNative; + _callbacks.Control = _onAppControlNative; + _callbacks.Resume = _onResumeNative; + _callbacks.Pause = _onPauseNative; + _callbacks.LowMemory = _onLowMemoryNative; + _callbacks.LowBattery = _onLowBatteryNative; + _callbacks.LanguageChanged = _onLanguageChangedNative; + _callbacks.DeviceOrientationChanged = _onDeviceOrientationChangedNative; + _callbacks.RegionFormatChanged = _onRegionFormatChangedNative; + _callbacks.SuspendStateChanged = _onSuspendStateChangedNative; + _callbacks.TimezoneChanged = _onTimeZoneChangedNative; + } + public View GetDefaultView() + { + return DefaultView; + } + + public int GetDefaultViewId() + { + return DefaultViewId; + } + internal void SetDefaultView(View view, string memberInstId) + { + DefaultView = view; + DefaultViewId = TeamManager.AddView(view, memberInstId); + } + internal void UnsetDefaultView() + { + TeamManager.RemoveView(DefaultViewId); + } + public override void Exit() + { + if (_memberHandle != IntPtr.Zero) + { + Interop.TeamMember.ViewMemberQuit(_memberHandle); + _memberHandle = IntPtr.Zero; + } + } + + public override void Run(string[] args) + { + // base.Run() is not required. + if (!TeamManager.IsInit()) + { + string[] argsClone = new string[args == null ? 1 : args.Length + 1]; + if (args != null && args.Length > 1) + { + args.CopyTo(argsClone, 1); + } + argsClone[0] = "Tizen.Applications.Team.dll"; + + TeamManager.Init(argsClone); + Log.Info("DN_TAM", $"Launching Team Loop."); + return; + } + + if (args == null || args.Length == 0) + { + Log.Error(LogTag, "args is null or empty"); + return; + } + + _loadObjId = TeamManager.GetAssemblyIdByPath(args[0]); + _argHandle = Interop.TeamMember.ViewMemberTeamup(_callbacks, IntPtr.Zero); + TeamManager.RegisterArgHandle(_loadObjId, _argHandle); + Log.Info(LogTag, $"path: {args[0]}, id: {_loadObjId}, arg_h: {_argHandle}"); + } + + protected override void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + // Release disposable objects + } + + if (_memberHandle != IntPtr.Zero) + { + Interop.TeamMember.ViewMemberQuit(_memberHandle); + _memberHandle = IntPtr.Zero; + } + + _disposedValue = true; + } + } + + private IntPtr OnCreateNative(IntPtr context, IntPtr userdata) + { + if (_memberHandle != IntPtr.Zero) + { + Log.Warn(LogTag, "OnCreate called twice!"); + } + _memberHandle = context; + + if (Handlers.ContainsKey(EventType.Created)) + { + var handler = Handlers[EventType.Created] as Action; + if (handler != null) + { + // This function will set default window + try + { + var view = new View(); + Interop.TeamManager.TeamAppGetAppInstanceId(_memberHandle, out string appInstId); + SetDefaultView(view, appInstId); + + try { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in User Created handler: {ex.Message}"); + } + + IntPtr view_h = Interop.TeamManager.CreateViewByViewId(GetDefaultViewId()); + + if (view_h != IntPtr.Zero) + { + view.AggregatedVisibilityChanged += (sender, e) => + { + Log.Info(LogTag, $"View Visibility Changed: {e.Visibility}"); + Interop.TeamManager.InvokeViewVisibilityEvent(DefaultViewId, e.Visibility); + }; + } + + return view_h; + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Internal Created handler: {ex.Message}"); + return IntPtr.Zero; + } + } + else + { + Log.Error(LogTag, "Invalid OnCreate Callback type"); + return IntPtr.Zero; + } + } + + Log.Error(LogTag, "No OnCreate Callback"); + return IntPtr.Zero; + } + + private void OnTerminateNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Terminated)) + { + var handler = Handlers[EventType.Terminated] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Terminated handler: {ex.Message}"); + } + } + + UnsetDefaultView(); + Interop.TeamManager.DestroyViewByViewId(GetDefaultViewId()); + } + + private void OnAppControlNative(IntPtr context, IntPtr appControl, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.AppControlReceived)) + { + using (SafeAppControlHandle safeHandle = new SafeAppControlHandle(appControl, false)) + { + var handler = Handlers[EventType.AppControlReceived] as Action; + try + { + handler?.Invoke(new AppControlReceivedEventArgs(new ReceivedAppControl(safeHandle))); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in AppControlReceived handler: {ex.Message}"); + } + } + } + } + + private void OnResumeNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Resumed)) + { + var handler = Handlers[EventType.Resumed] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Resumed handler: {ex.Message}"); + } + } + } + + private void OnPauseNative(IntPtr context, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.Paused)) + { + var handler = Handlers[EventType.Paused] as Action; + try + { + handler?.Invoke(); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in Paused handler: {ex.Message}"); + } + } + } + + private void OnLowMemoryNative(IntPtr context, int status, IntPtr userdata) + { + LowMemoryStatus lowMemoryStatus = (LowMemoryStatus)status; + if (Handlers.ContainsKey(EventType.LowMemory)) + { + var handler = Handlers[EventType.LowMemory] as Action; + try + { + handler?.Invoke(new LowMemoryEventArgs(lowMemoryStatus)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LowMemory handler: {ex.Message}"); + } + } + } + + private void OnLowBatteryNative(IntPtr context, int status, IntPtr userdata) + { + LowBatteryStatus lowBatteryStatus = (LowBatteryStatus)status; + if (Handlers.ContainsKey(EventType.LowBattery)) + { + var handler = Handlers[EventType.LowBattery] as Action; + try + { + handler?.Invoke(new LowBatteryEventArgs(lowBatteryStatus)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LowBattery handler: {ex.Message}"); + } + } + } + + private void OnLanguageChangedNative(IntPtr context, string language, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.LocaleChanged)) + { + var handler = Handlers[EventType.LocaleChanged] as Action; + try + { + handler?.Invoke(new LocaleChangedEventArgs(language)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in LocaleChanged handler: {ex.Message}"); + } + } + } + + private void OnDeviceOrientationChangedNative(IntPtr context, int status, IntPtr userdata) + { + DeviceOrientation orientation = (DeviceOrientation)status; + if (Handlers.ContainsKey(EventType.DeviceOrientationChanged)) + { + var handler = Handlers[EventType.DeviceOrientationChanged] as Action; + try + { + handler?.Invoke(new DeviceOrientationEventArgs(orientation)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in DeviceOrientationChanged handler: {ex.Message}"); + } + } + } + + private void OnRegionFormatChangedNative(IntPtr context, string region, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.RegionFormatChanged)) + { + var handler = Handlers[EventType.RegionFormatChanged] as Action; + try + { + handler?.Invoke(new RegionFormatChangedEventArgs(region)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in RegionFormatChanged handler: {ex.Message}"); + } + } + } + + private void OnSuspendStateChangedNative(IntPtr context, int status, IntPtr userdata) + { + SuspendedState state = (SuspendedState)status; + if (Handlers.ContainsKey(EventType.SuspendedStateChanged)) + { + var handler = Handlers[EventType.SuspendedStateChanged] as Action; + try + { + handler?.Invoke(new SuspendedStateEventArgs(state)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in SuspendedStateChanged handler: {ex.Message}"); + } + } + } + + private void OnTimeZoneChangedNative(IntPtr context, string timeZone, string timeZoneId, IntPtr userdata) + { + if (Handlers.ContainsKey(EventType.TimeZoneChanged)) + { + var handler = Handlers[EventType.TimeZoneChanged] as Action; + try + { + handler?.Invoke(new TimeZoneChangedEventArgs(timeZone, timeZoneId)); + } + catch (Exception ex) + { + Log.Error(LogTag, $"Error in TimeZoneChanged handler: {ex.Message}"); + } + } + } + } +} \ No newline at end of file diff --git a/src/Tizen.Applications.Team/Tizen.Applications.Team.csproj b/src/Tizen.Applications.Team/Tizen.Applications.Team.csproj new file mode 100755 index 00000000000..5809df03c80 --- /dev/null +++ b/src/Tizen.Applications.Team/Tizen.Applications.Team.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + + + + + + + + + + + + From f3c21b558c9a36c90e84b4ac5fbf5201fb79c69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=ED=98=84=EC=9A=B1?= <43038815+Hyeon-Uk@users.noreply.github.com> Date: Fri, 17 Apr 2026 16:02:24 +0900 Subject: [PATCH 3/3] [APPFW] Add XML documentation and inhouse markers for Team Application - Add summary, param, returns, exception, remarks XML doc comments to public API surface of Tizen.Applications.Team module. - Mark public types and members with [EditorBrowsable(EditorBrowsableState.Never)] and inhouse comment line until ACR is completed. Co-authored-by: KimHyeonuk --- .../CultureInfoHelper.cs | 3 + src/Tizen.Applications.Team/GSourceManager.cs | 6 + .../ResourceControl.cs | 26 +++ .../SystemLocaleConverter.cs | 6 + .../TeamApplication.cs | 76 ++++++++ .../TeamApplicationInfo.cs | 134 ++++++++++++++ .../TeamCoreApplication.cs | 127 ++++++++++++++ .../TeamCoreUiApplication.cs | 57 +++++- .../TeamDirectoryInfo.cs | 165 +++++++++++++++++- src/Tizen.Applications.Team/TeamLoop.cs | 24 +++ src/Tizen.Applications.Team/TeamManager.cs | 50 ++++++ .../TeamServiceApplication.cs | 20 ++- .../TeamUiApplication.cs | 18 ++ .../TeamViewApplication.cs | 52 +++++- .../TeamCoreBackend.cs | 18 ++ .../TeamServiceCoreBackend.cs | 3 + .../TeamUICoreBackend.cs | 3 + .../TeamViewCoreBackend.cs | 3 + 18 files changed, 786 insertions(+), 5 deletions(-) diff --git a/src/Tizen.Applications.Team/CultureInfoHelper.cs b/src/Tizen.Applications.Team/CultureInfoHelper.cs index 24d45c0b218..5ca0e624ac1 100644 --- a/src/Tizen.Applications.Team/CultureInfoHelper.cs +++ b/src/Tizen.Applications.Team/CultureInfoHelper.cs @@ -20,6 +20,9 @@ namespace Tizen.Applications { + /// + /// Resolves culture names from the platform-provided CultureInfo INI file. + /// internal static class CultureInfoHelper { private const string _pathCultureInfoIni = "/usr/share/dotnet.tizen/framework/i18n/CultureInfo.ini"; diff --git a/src/Tizen.Applications.Team/GSourceManager.cs b/src/Tizen.Applications.Team/GSourceManager.cs index e38968f6c82..d7b1358621e 100644 --- a/src/Tizen.Applications.Team/GSourceManager.cs +++ b/src/Tizen.Applications.Team/GSourceManager.cs @@ -19,6 +19,9 @@ namespace Tizen.Applications { + /// + /// Posts actions onto the GLib main loop used by the Team application. + /// internal static class GSourceManager { private static readonly GSourceContext _tizenContext = new GSourceContext(); @@ -39,6 +42,9 @@ private static bool Handler(IntPtr userData) } } + /// + /// Holds the GLib source state and action queue for a single main loop context. + /// internal class GSourceContext { private readonly ConcurrentQueue _actionQueue = new ConcurrentQueue(); diff --git a/src/Tizen.Applications.Team/ResourceControl.cs b/src/Tizen.Applications.Team/ResourceControl.cs index cd3f3822eca..070070d02a7 100644 --- a/src/Tizen.Applications.Team/ResourceControl.cs +++ b/src/Tizen.Applications.Team/ResourceControl.cs @@ -16,10 +16,16 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Text; namespace Tizen.Applications { + /// + /// Represents the resource control information for a Team application. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class ResourceControl { internal ResourceControl(string resourceType, string minResourceVersion, string maxResourceVersion, bool isAutoClose) @@ -30,12 +36,32 @@ internal ResourceControl(string resourceType, string minResourceVersion, string IsAutoClose = isAutoClose; } + /// + /// Gets the resource type. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ResourceType { get; } + /// + /// Gets the minimum version of the required resource package. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string MinResourceVersion { get; } + /// + /// Gets the maximum version of the required resource package. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string MaxResourceVersion { get; } + /// + /// Gets a value indicating whether the resource is auto-closed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public bool IsAutoClose { get; } } } diff --git a/src/Tizen.Applications.Team/SystemLocaleConverter.cs b/src/Tizen.Applications.Team/SystemLocaleConverter.cs index 8f04fdd2125..72d710622cc 100644 --- a/src/Tizen.Applications.Team/SystemLocaleConverter.cs +++ b/src/Tizen.Applications.Team/SystemLocaleConverter.cs @@ -24,6 +24,9 @@ namespace Tizen.Applications { + /// + /// Converts Tizen system locale strings into values with ICU fallback. + /// internal class SystemLocaleConverter { private static readonly string LogTag = "DN_TAM"; @@ -151,6 +154,9 @@ private bool Exist(string locale) } + /// + /// Wraps ICU uloc_* interop for parsing and canonicalizing locale strings. + /// internal class ULocale { private const int ULOC_FULLNAME_CAPACITY = 157; diff --git a/src/Tizen.Applications.Team/TeamApplication.cs b/src/Tizen.Applications.Team/TeamApplication.cs index 1b1a90474ff..90b251f63fc 100644 --- a/src/Tizen.Applications.Team/TeamApplication.cs +++ b/src/Tizen.Applications.Team/TeamApplication.cs @@ -15,10 +15,20 @@ */ using System; +using System.ComponentModel; using Tizen.Applications.CoreBackend; namespace Tizen.Applications { + /// + /// Represents the abstract base class of a Team application instance. + /// + /// + /// A Team application is a member instance managed by the Team host process. Each instance + /// owns its own lifecycle, directory information, and application information. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public abstract class TeamApplication : IDisposable { internal const string LogTag = "DN_TAM"; @@ -27,16 +37,34 @@ public abstract class TeamApplication : IDisposable private TeamDirectoryInfo _directoryInfo; private TeamApplicationInfo _applicationInfo; + + /// + /// The backend that drives this Team application instance. + /// protected readonly TeamCoreBackend _backend; + /// + /// Gets the backend associated with this Team application instance. + /// protected ICoreBackend Backend => _backend; + /// + /// Initializes the class with the given backend. + /// + /// The backend used to drive this Team application instance. + /// Thrown when is null. protected TeamApplication(TeamCoreBackend backend) { Log.Info(LogTag, "TeamApplication constructor called"); _backend = backend ?? throw new ArgumentNullException(nameof(backend)); } + /// + /// Gets the directory information of the current Team application instance. + /// + /// A instance, or null if the member handle is not yet available. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public TeamDirectoryInfo DirectoryInfo { get @@ -57,6 +85,12 @@ public TeamDirectoryInfo DirectoryInfo } } + /// + /// Gets the application information of the current Team application instance. + /// + /// A instance, or null if the member handle or application id cannot be resolved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public TeamApplicationInfo ApplicationInfo { get @@ -89,8 +123,20 @@ public TeamApplicationInfo ApplicationInfo } } + /// + /// Gets the current Team application instance. + /// + /// The current instance. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public TeamApplication Current { get { return this; } } + /// + /// Gets the name of the current Team application instance. + /// + /// The name string, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string Name { get @@ -113,6 +159,12 @@ public string Name } } + /// + /// Gets the version of the current Team application instance. + /// + /// The version string, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string Version { get @@ -135,6 +187,13 @@ public string Version } } + /// + /// Runs the Team application's main loop and registers this instance with the Team manager. + /// + /// Arguments from commandline. + /// Thrown when is null. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public virtual void Run(string[] args) { if (args == null) @@ -144,6 +203,11 @@ public virtual void Run(string[] args) TeamManager.RegisterRunningTeamApp(this); } + /// + /// Exits the main loop of this Team application instance and unregisters it from the Team manager. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public virtual void Exit() { TeamManager.UnRegisterRunningTeamApp(this); @@ -152,6 +216,10 @@ public virtual void Exit() private bool _disposedValue = false; + /// + /// Releases the resources used by this Team application instance. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { if (!_disposedValue) @@ -169,11 +237,19 @@ protected virtual void Dispose(bool disposing) } } + /// + /// Finalizes the instance. + /// ~TeamApplication() { Dispose(false); } + /// + /// Releases all resources used by this Team application instance. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public void Dispose() { Log.Info(LogTag, "TeamApplication.Dispose() called"); diff --git a/src/Tizen.Applications.Team/TeamApplicationInfo.cs b/src/Tizen.Applications.Team/TeamApplicationInfo.cs index c4f450ed209..9d704ff1ff5 100644 --- a/src/Tizen.Applications.Team/TeamApplicationInfo.cs +++ b/src/Tizen.Applications.Team/TeamApplicationInfo.cs @@ -22,6 +22,15 @@ namespace Tizen.Applications { + /// + /// Represents the installed application information of a Team application instance. + /// + /// + /// The information is obtained lazily from the native application manager and cached for subsequent access. + /// Call to release the underlying native handle. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamApplicationInfo : IDisposable { private const string LogTag = "DN_TAMS"; @@ -45,11 +54,20 @@ internal TeamApplicationInfo(IntPtr memberHandle, string applicationId) _applicationId = applicationId; } + /// + /// Finalizes the instance. + /// ~TeamApplicationInfo() { Dispose(false); } + /// + /// Gets the application id. + /// + /// The application id string. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ApplicationId { get @@ -58,6 +76,12 @@ public string ApplicationId } } + /// + /// Gets the package id of the application. + /// + /// The package id string, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string PackageId { get @@ -76,6 +100,12 @@ public string PackageId } } + /// + /// Gets the label of the application. + /// + /// The application label, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string Label { get @@ -94,6 +124,12 @@ public string Label } } + /// + /// Gets the absolute path of the executable file of the application. + /// + /// The executable file path, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ExecutablePath { get @@ -112,6 +148,12 @@ public string ExecutablePath } } + /// + /// Gets the absolute path of the icon image of the application. + /// + /// The icon image path, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string IconPath { get @@ -130,6 +172,12 @@ public string IconPath } } + /// + /// Gets the application type. + /// + /// The application type string, or if it cannot be retrieved. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ApplicationType { get @@ -148,6 +196,12 @@ public string ApplicationType } } + /// + /// Gets the application component type. + /// + /// The of this application. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public ApplicationComponentType ComponentType { get @@ -166,6 +220,12 @@ public ApplicationComponentType ComponentType } } + /// + /// Gets the metadata key-value pairs declared by the application. + /// + /// A dictionary containing the metadata entries. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public IDictionary Metadata { get @@ -198,6 +258,12 @@ public IDictionary Metadata } } + /// + /// Gets a value indicating whether the application is not displayed on the launcher. + /// + /// true if the application is hidden from the launcher; otherwise, false. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public bool IsNoDisplay { get @@ -217,6 +283,12 @@ public bool IsNoDisplay } } + /// + /// Gets a value indicating whether the application is launched automatically on system boot. + /// + /// true if the application is launched on boot; otherwise, false. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public bool IsOnBoot { get @@ -235,6 +307,12 @@ public bool IsOnBoot } } + /// + /// Gets a value indicating whether the application is preloaded on the device. + /// + /// true if the application is preloaded; otherwise, false. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public bool IsPreload { get @@ -253,6 +331,12 @@ public bool IsPreload } } + /// + /// Gets the categories the application belongs to. + /// + /// An enumerable collection of category names. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public IEnumerable Categories { get @@ -281,6 +365,12 @@ public IEnumerable Categories } } + /// + /// Gets the absolute path of the directory shared with other applications for this Team member. + /// + /// The shared data directory path. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string SharedDataPath { get @@ -298,6 +388,12 @@ public string SharedDataPath } } + /// + /// Gets the absolute path of the read-only resource directory shared with other applications for this Team member. + /// + /// The shared resource directory path. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string SharedResourcePath { get @@ -315,6 +411,12 @@ public string SharedResourcePath } } + /// + /// Gets the absolute path of the directory shared only with trusted applications for this Team member. + /// + /// The shared trusted directory path. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string SharedTrustedPath { get @@ -332,6 +434,12 @@ public string SharedTrustedPath } } + /// + /// Gets the absolute path of the shared directory on the external storage for this Team member. + /// + /// The external shared data directory path. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ExternalSharedDataPath { get @@ -349,6 +457,12 @@ public string ExternalSharedDataPath } } + /// + /// Gets the resource control entries declared by the application. + /// + /// An enumerable collection of entries. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public IEnumerable ResourceControls { get @@ -376,6 +490,13 @@ public IEnumerable ResourceControls } } + /// + /// Gets the localized label of the application for the given locale. + /// + /// The locale in the form of language and country code (for example, "en-US"). + /// The localized label; falls back to if no localized value is available. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string GetLocalizedLabel(string locale) { string label = string.Empty; @@ -388,6 +509,10 @@ public string GetLocalizedLabel(string locale) return label; } + /// + /// Gets the absolute path of the common shared data directory for this Team member. + /// + /// The common shared data directory path. [EditorBrowsable(EditorBrowsableState.Never)] public string CommonSharedDataPath { @@ -406,6 +531,10 @@ public string CommonSharedDataPath } } + /// + /// Gets the absolute path of the common shared trusted directory for this Team member. + /// + /// The common shared trusted directory path. [EditorBrowsable(EditorBrowsableState.Never)] public string CommonSharedTrustedPath { @@ -439,6 +568,11 @@ private IntPtr GetInfoHandle() return _infoHandle; } + /// + /// Releases all resources used by this . + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public void Dispose() { Dispose(true); diff --git a/src/Tizen.Applications.Team/TeamCoreApplication.cs b/src/Tizen.Applications.Team/TeamCoreApplication.cs index 64cb0b5acfc..c3c7460c8d0 100644 --- a/src/Tizen.Applications.Team/TeamCoreApplication.cs +++ b/src/Tizen.Applications.Team/TeamCoreApplication.cs @@ -15,27 +15,103 @@ */ using System; +using System.ComponentModel; using System.Globalization; using System.Threading.Tasks; using Tizen.Applications.CoreBackend; namespace Tizen.Applications { + /// + /// Represents the core Team application with common lifecycle and system events. + /// + /// + /// Subclasses typically add UI- or service-specific behavior on top of the events exposed here. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamCoreApplication : TeamApplication { + /// + /// Initializes the class with the given backend. + /// + /// The backend used to drive this Team application instance. + /// Thrown when is null. protected TeamCoreApplication(TeamCoreBackend backend) : base(backend) { Log.Info(LogTag, "TeamCoreApplication constructor called"); } + + /// + /// Occurs whenever the application is launched. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler Created; + + /// + /// Occurs whenever the application is about to shut down. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler Terminated; + + /// + /// Occurs whenever the application receives an application control request. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler AppControlReceived; + + /// + /// Occurs when a low memory condition is reported by the system. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler LowMemory; + + /// + /// Occurs when a low battery condition is reported by the system. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler LowBattery; + + /// + /// Occurs when the system language is changed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler LocaleChanged; + + /// + /// Occurs when the region format of the system is changed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler RegionFormatChanged; + + /// + /// Occurs when the device orientation is changed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler DeviceOrientationChanged; + + /// + /// Occurs when the system time zone is changed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler TimeZoneChanged; + + /// + /// Runs the Team application's main loop and subscribes to lifecycle and system events. + /// + /// Arguments from commandline. + /// Thrown when is null. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public override void Run(string[] args) { base.Run(args); @@ -53,6 +129,9 @@ public override void Run(string[] args) _backend.Run(args); } + /// + /// Invoked when the application is created. Raises the event. + /// protected virtual void OnCreate() { if (!GlobalizationMode.Invariant) @@ -70,12 +149,19 @@ protected virtual void OnCreate() Created?.Invoke(this, EventArgs.Empty); } + /// + /// Invoked when the application is about to terminate. Raises the event. + /// protected virtual void OnTerminate() { Log.Info(LogTag, "TeamCoreApplication.OnTerminate() called"); Terminated?.Invoke(this, EventArgs.Empty); } + /// + /// Invoked when the application receives an application control request. Raises the event. + /// + /// The event data containing the received application control. protected virtual void OnAppControlReceived(AppControlReceivedEventArgs e) { Log.Info(LogTag, "TeamCoreApplication.OnAppControlReceived() called"); @@ -88,6 +174,11 @@ protected virtual void OnAppControlReceived(AppControlReceivedEventArgs e) AppControlReceived?.Invoke(this, e); } + /// + /// Invoked when a low memory event is reported by the system. Raises the event + /// and triggers on soft/hard warnings. + /// + /// The event data describing the low memory status. protected virtual void OnLowMemory(LowMemoryEventArgs e) { Log.Info(LogTag, $"TeamCoreApplication.OnLowMemory() called - Status: {e?.LowMemoryStatus}"); @@ -104,6 +195,10 @@ protected virtual void OnLowMemory(LowMemoryEventArgs e) } } + /// + /// Invoked when a low battery event is reported by the system. Raises the event. + /// + /// The event data describing the low battery status. protected virtual void OnLowBattery(LowBatteryEventArgs e) { Log.Info(LogTag, $"TeamCoreApplication.OnLowBattery() called - Status: {e?.LowBatteryStatus}"); @@ -116,6 +211,10 @@ protected virtual void OnLowBattery(LowBatteryEventArgs e) LowBattery?.Invoke(this, e); } + /// + /// Invoked when the system language is changed. Updates the current UI culture and raises the event. + /// + /// The event data describing the new locale. protected virtual void OnLocaleChanged(LocaleChangedEventArgs e) { Log.Info(LogTag, $"TeamCoreApplication.OnLocaleChanged() called - Locale: {e?.Locale}"); @@ -133,6 +232,10 @@ protected virtual void OnLocaleChanged(LocaleChangedEventArgs e) LocaleChanged?.Invoke(this, e); } + /// + /// Invoked when the region format is changed. Updates the current culture and raises the event. + /// + /// The event data describing the new region. protected virtual void OnRegionFormatChanged(RegionFormatChangedEventArgs e) { Log.Info(LogTag, $"TeamCoreApplication.OnRegionFormatChanged() called - Region: {e?.Region}"); @@ -150,12 +253,20 @@ protected virtual void OnRegionFormatChanged(RegionFormatChangedEventArgs e) RegionFormatChanged?.Invoke(this, e); } + /// + /// Invoked when the device orientation is changed. Raises the event. + /// + /// The event data describing the new orientation. protected virtual void OnDeviceOrientationChanged(DeviceOrientationEventArgs e) { Log.Info(LogTag, $"TeamCoreApplication.OnDeviceOrientationChanged() called - Orientation: {e?.DeviceOrientation}"); DeviceOrientationChanged?.Invoke(this, e); } + /// + /// Invoked when the system time zone is changed. Clears cached culture data and raises the event. + /// + /// The event data describing the new time zone. protected virtual void OnTimeZoneChanged(TimeZoneChangedEventArgs e) { Log.Info(LogTag, $"TeamCoreApplication.OnTimeZoneChanged() called - TimeZone: {e?.TimeZone}, ID: {e?.TimeZoneId}"); @@ -163,6 +274,13 @@ protected virtual void OnTimeZoneChanged(TimeZoneChangedEventArgs e) TimeZoneChanged?.Invoke(this, e); } + /// + /// Posts an action to be executed on the main loop of the current Team application. + /// + /// The action to be executed on the main loop. + /// Thrown when is null. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static void Post(Action runner) { Log.Info(LogTag, "TeamCoreApplication.Post(Action) called"); @@ -174,6 +292,15 @@ public static void Post(Action runner) GSourceManager.Post(runner); } + /// + /// Posts a function to be executed on the main loop of the current Team application and awaits its result. + /// + /// The type of the result returned by . + /// The function to be executed on the main loop. + /// A task that completes with the result of . + /// Thrown when is null. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static async Task Post(Func runner) { Log.Info(LogTag, $"TeamCoreApplication.Post() called - Type: {typeof(T).Name}"); diff --git a/src/Tizen.Applications.Team/TeamCoreUiApplication.cs b/src/Tizen.Applications.Team/TeamCoreUiApplication.cs index 09d822fec86..bcd068b4879 100644 --- a/src/Tizen.Applications.Team/TeamCoreUiApplication.cs +++ b/src/Tizen.Applications.Team/TeamCoreUiApplication.cs @@ -16,24 +16,60 @@ using System; +using System.ComponentModel; using Tizen.Applications.CoreBackend; using Tizen.NUI; namespace Tizen.Applications { + /// + /// Represents a base class for Team UI applications that own a NUI and expose + /// and lifecycle events. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamCoreUiApplication : TeamCoreApplication { + /// + /// Initializes the class. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public TeamCoreUiApplication() : base(new TeamUICoreBackend()) { } + /// + /// Gets the default window of this application. + /// + /// The default associated with this application. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public Window GetDefaultWindow() { return ((TeamUICoreBackend)Backend).GetDefaultWindow(); } + /// + /// Occurs whenever the application is resumed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler Resumed; + + /// + /// Occurs whenever the application is paused. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler Paused; + + /// + /// Runs the Team UI application's main loop. + /// + /// Arguments from commandline. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public override void Run(string[] args) { Backend.AddEventHandler(EventType.Resumed, OnResume); @@ -42,17 +78,34 @@ public override void Run(string[] args) base.Run(args); } + /// + /// Invoked when the application is created. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] protected override void OnCreate() { - base.OnCreate(); + base.OnCreate(); } + + /// + /// Invoked when the application is resumed. Raises the event. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void OnResume() { Resumed?.Invoke(this, EventArgs.Empty); } + + /// + /// Invoked when the application is paused. Raises the event. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void OnPause() { Paused?.Invoke(this, EventArgs.Empty); } } -} \ No newline at end of file +} diff --git a/src/Tizen.Applications.Team/TeamDirectoryInfo.cs b/src/Tizen.Applications.Team/TeamDirectoryInfo.cs index 9c3f592149d..8f2541f0be9 100644 --- a/src/Tizen.Applications.Team/TeamDirectoryInfo.cs +++ b/src/Tizen.Applications.Team/TeamDirectoryInfo.cs @@ -22,6 +22,15 @@ namespace Tizen.Applications { + /// + /// Represents the directory paths available to a Team application instance. + /// + /// + /// Each path is resolved lazily on first access and cached. Any failure in the native call is translated + /// into a .NET exception; see each property for the specific exceptions that can be thrown. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamDirectoryInfo { private IntPtr _memberHandle; @@ -45,6 +54,16 @@ internal TeamDirectoryInfo(IntPtr memberHandle) _memberHandle = memberHandle; } + /// + /// Gets the absolute path to the private data directory of this Team application. + /// + /// The private data directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string Data { get @@ -60,6 +79,16 @@ public string Data } } + /// + /// Gets the absolute path to the private cache directory of this Team application. + /// + /// The private cache directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string Cache { get @@ -75,6 +104,16 @@ public string Cache } } + /// + /// Gets the absolute path to the read-only resource directory of this Team application. + /// + /// The read-only resource directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string Resource { get @@ -90,6 +129,16 @@ public string Resource } } + /// + /// Gets the absolute path to the directory shared with other applications. + /// + /// The shared data directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string SharedData { get @@ -105,6 +154,16 @@ public string SharedData } } + /// + /// Gets the absolute path to the read-only resource directory shared with other applications. + /// + /// The shared resource directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string SharedResource { get @@ -120,6 +179,16 @@ public string SharedResource } } + /// + /// Gets the absolute path to the directory shared only with trusted applications. + /// + /// The shared trusted directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string SharedTrusted { get @@ -135,6 +204,16 @@ public string SharedTrusted } } + /// + /// Gets the absolute path to the private data directory on the external storage. + /// + /// The external data directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ExternalData { get @@ -150,6 +229,16 @@ public string ExternalData } } + /// + /// Gets the absolute path to the private cache directory on the external storage. + /// + /// The external cache directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ExternalCache { get @@ -165,6 +254,16 @@ public string ExternalCache } } + /// + /// Gets the absolute path to the shared directory on the external storage. + /// + /// The external shared data directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ExternalSharedData { get @@ -180,6 +279,16 @@ public string ExternalSharedData } } + /// + /// Gets the absolute path to the resource directory of the Tizen Expansion Package. + /// + /// The expansion package resource directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string ExpansionPackageResource { get @@ -195,6 +304,14 @@ public string ExpansionPackageResource } } + /// + /// Gets the absolute path to the common data directory shared among users. + /// + /// The common data directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. [EditorBrowsable(EditorBrowsableState.Never)] public string CommonData { @@ -211,6 +328,14 @@ public string CommonData } } + /// + /// Gets the absolute path to the common cache directory shared among users. + /// + /// The common cache directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. [EditorBrowsable(EditorBrowsableState.Never)] public string CommonCache { @@ -227,6 +352,14 @@ public string CommonCache } } + /// + /// Gets the absolute path to the common shared data directory shared among users. + /// + /// The common shared data directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. [EditorBrowsable(EditorBrowsableState.Never)] public string CommonSharedData { @@ -243,6 +376,14 @@ public string CommonSharedData } } + /// + /// Gets the absolute path to the common shared trusted directory shared among users. + /// + /// The common shared trusted directory path. + /// Thrown when the member handle is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. [EditorBrowsable(EditorBrowsableState.Never)] public string CommonSharedTrusted { @@ -259,6 +400,17 @@ public string CommonSharedTrusted } } + /// + /// Gets the absolute path to the resource directory allowed by resource control for the given resource type. + /// + /// The resource type. + /// The path to the allowed resource directory. + /// Thrown when the member handle or is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string GetResourceControlAllowedResource(string resType) { Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetResControlAllowedPath(_memberHandle, resType, out string path); @@ -267,6 +419,17 @@ public string GetResourceControlAllowedResource(string resType) return path; } + /// + /// Gets the absolute path to the global resource directory by resource control for the given resource type. + /// + /// The resource type. + /// The path to the global resource directory. + /// Thrown when the member handle or is invalid. + /// Thrown when the system runs out of memory. + /// Thrown when the team member context is invalid or the path cannot be retrieved. + /// Thrown when the Team member is not found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public string GetResourceControlGlobalResource(string resType) { Interop.TeamManager.TeamAppErrorCode err = Interop.TeamManager.TeamAppGetResControlGlobalPath(_memberHandle, resType, out string path); @@ -292,4 +455,4 @@ private Exception GetExceptionFromError(string operationName, Interop.TeamManage } } } -} \ No newline at end of file +} diff --git a/src/Tizen.Applications.Team/TeamLoop.cs b/src/Tizen.Applications.Team/TeamLoop.cs index 21925328845..09b62f6d4c0 100644 --- a/src/Tizen.Applications.Team/TeamLoop.cs +++ b/src/Tizen.Applications.Team/TeamLoop.cs @@ -16,6 +16,7 @@ using System; +using System.ComponentModel; using System.Threading; using System.Reflection; using System.Runtime.InteropServices; @@ -25,6 +26,11 @@ namespace Tizen.Applications { + /// + /// Provides the entry point to the native Team main loop and the dynamic assembly load/unload callbacks. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static class TeamLoop { private const string LogTag = "DN_TAM"; @@ -42,6 +48,12 @@ static TeamLoop() _ops.OnLoopCreate = new Interop.TeamLoop.TeamLoopOpsOnLoopCreate(DoOnLoopCreate); _ops.OnLoopTerminate = new Interop.TeamLoop.TeamLoopOpsOnLoopTerminate(DoOnLoopTerminate); } + /// + /// Starts the Team main loop. Subsequent calls while the loop is running are no-ops. + /// + /// Arguments passed to the native Team loop. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static void Run(string[] args) { Log.Info(LogTag, $"Run() called - Already Running: {_isRunning}"); @@ -69,6 +81,12 @@ public static void Run(string[] args) } } + /// + /// Gets a value indicating whether the Team main loop is currently running. + /// + /// true if the main loop is running; otherwise, false. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static bool IsRunning() { Log.Info(LogTag, $"IsRunning() called - Result: {_isRunning}"); @@ -223,6 +241,12 @@ internal static void DoCreateLibPath(string path, ref IntPtr output) } } + /// + /// Gets the command line arguments that were passed to . + /// + /// The arguments array, or null if has not been invoked. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static string[] GetSystemArgs() { Log.Info(LogTag, $"GetSystemArgs() called - Count: {_systemArgs?.Length ?? 0}"); diff --git a/src/Tizen.Applications.Team/TeamManager.cs b/src/Tizen.Applications.Team/TeamManager.cs index 840f77edfaa..76ae8d60082 100644 --- a/src/Tizen.Applications.Team/TeamManager.cs +++ b/src/Tizen.Applications.Team/TeamManager.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Reflection; using System.Runtime.Loader; using Tizen.NUI.BaseComponents; @@ -50,6 +51,11 @@ internal class ViewInfo public bool Owned { get; set; } } + /// + /// Provides registration and management of Team application instances, loaded assemblies, and view ownership. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static class TeamManager { private const string LogTag = "DN_TAM"; @@ -103,11 +109,23 @@ internal static AssemblyInfo GetAssembly(IntPtr id) return null; } + /// + /// Initializes the Team application runtime and starts the Team main loop. + /// + /// Arguments from commandline. May be null. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static void Init(string[] args) { TeamLoop.Run(args); } + /// + /// Gets a value indicating whether the Team main loop has been initialized. + /// + /// true if the Team main loop is running; otherwise, false. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static bool IsInit() { return TeamLoop.IsRunning(); @@ -177,6 +195,16 @@ internal static void UnRegisterRunningTeamApp(TeamApplication app) } } + /// + /// Registers a with the Team manager under the given application id. + /// + /// The view to register. + /// The application id that owns the view. + /// A unique identifier assigned to the registered view. + /// Thrown when or is null or empty. + /// Thrown when has already been registered. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static int AddView(View view, string appid) { if (view == null) @@ -200,6 +228,13 @@ public static int AddView(View view, string appid) } } + /// + /// Removes a view previously registered via . + /// + /// The unique identifier returned from . + /// true if the view was removed; false if no matching id was found. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static bool RemoveView(int id) { lock (_lock) @@ -215,6 +250,14 @@ public static bool RemoveView(int id) } } + /// + /// Claims ownership of the view registered under the given application id. + /// + /// The application id that owns the view. + /// The owned , or null if the view is already owned or not found. + /// Thrown when is null or empty. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static View OwnViewApp(string appid) { if (string.IsNullOrEmpty(appid)) @@ -241,6 +284,13 @@ public static View OwnViewApp(string appid) } } + /// + /// Releases ownership of the view registered under the given application id. + /// + /// The application id that owns the view. + /// Thrown when is null or empty. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public static void DisownViewApp(string appid) { if (string.IsNullOrEmpty(appid)) diff --git a/src/Tizen.Applications.Team/TeamServiceApplication.cs b/src/Tizen.Applications.Team/TeamServiceApplication.cs index 9bb37599867..510a63170fb 100644 --- a/src/Tizen.Applications.Team/TeamServiceApplication.cs +++ b/src/Tizen.Applications.Team/TeamServiceApplication.cs @@ -15,21 +15,39 @@ */ using System; +using System.ComponentModel; using System.Runtime.CompilerServices; using Tizen.Applications.CoreBackend; namespace Tizen.Applications { + /// + /// Represents a Team application that runs without a graphical user interface. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamServiceApplication : TeamCoreApplication { + /// + /// Initializes the class. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] #pragma warning disable CA2000 public TeamServiceApplication() : base(new TeamServiceCoreBackend()) #pragma warning restore CA2000 { } + + /// + /// Runs the Team service application's main loop. + /// + /// Arguments from commandline. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public override void Run(string[] args) { base.Run(args); } } -} \ No newline at end of file +} diff --git a/src/Tizen.Applications.Team/TeamUiApplication.cs b/src/Tizen.Applications.Team/TeamUiApplication.cs index b90bdd79506..4ae9daaaad1 100644 --- a/src/Tizen.Applications.Team/TeamUiApplication.cs +++ b/src/Tizen.Applications.Team/TeamUiApplication.cs @@ -15,15 +15,33 @@ */ using System; +using System.ComponentModel; using Tizen.NUI; namespace Tizen.Applications { + /// + /// Represents a Team application that provides a default NUI window. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamUiApplication : TeamCoreUiApplication { + /// + /// Initializes the class. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public TeamUiApplication() { } + + /// + /// Runs the Team UI application's main loop. + /// + /// Arguments from commandline. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public override void Run(string[] args) { base.Run(args); diff --git a/src/Tizen.Applications.Team/TeamViewApplication.cs b/src/Tizen.Applications.Team/TeamViewApplication.cs index 18dd476b2c6..b61d0096015 100644 --- a/src/Tizen.Applications.Team/TeamViewApplication.cs +++ b/src/Tizen.Applications.Team/TeamViewApplication.cs @@ -16,25 +16,63 @@ using System; +using System.ComponentModel; using Tizen.Applications.CoreBackend; using Tizen.NUI; using Tizen.NUI.BaseComponents; namespace Tizen.Applications { + /// + /// Represents a Team application that provides a default NUI . + /// + /// + /// A view application renders into a shared window supplied by the Team host rather than owning its own window. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public class TeamViewApplication : TeamCoreApplication { + /// + /// Initializes the class. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public TeamViewApplication() : base(new TeamViewCoreBackend()) { } + /// + /// Gets the default view attached to this application. + /// + /// The default associated with this application. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public View GetDefaultView() { return ((TeamViewCoreBackend)Backend).GetDefaultView(); } + /// + /// Occurs whenever the application is resumed. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler Resumed; + + /// + /// Occurs whenever the application is paused. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public event EventHandler Paused; + + /// + /// Runs the Team view application's main loop. + /// + /// Arguments from commandline. + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public override void Run(string[] args) { Backend.AddEventHandler(EventType.Resumed, OnResume); @@ -42,13 +80,25 @@ public override void Run(string[] args) base.Run(args); } + + /// + /// Invoked when the application is resumed. Raises the event. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void OnResume() { Resumed?.Invoke(this, EventArgs.Empty); } + + /// + /// Invoked when the application is paused. Raises the event. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] protected virtual void OnPause() { Paused?.Invoke(this, EventArgs.Empty); } } -} \ No newline at end of file +} diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs index d7e603a4225..473bad48ea3 100644 --- a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamCoreBackend.cs @@ -15,14 +15,32 @@ */ using System; +using System.ComponentModel; namespace Tizen.Applications.CoreBackend { + /// + /// Represents the abstract base backend that drives a Team application instance. + /// + /// This will be public opened in next tizen after ACR done. (Before ACR, need to be hidden as inhouse API) + [EditorBrowsable(EditorBrowsableState.Never)] public abstract class TeamCoreBackend : DefaultCoreBackend { + /// + /// The native handle that identifies this Team member instance. + /// protected IntPtr _memberHandle = IntPtr.Zero; + + /// + /// The identifier of the loaded assembly associated with this Team member instance. + /// protected IntPtr _loadObjId = IntPtr.Zero; + + /// + /// The native handle to the arguments passed to this Team member instance. + /// protected IntPtr _argHandle = IntPtr.Zero; + internal abstract IntPtr MemberHandle { get; } internal abstract IntPtr LoadObjId { get; } internal abstract IntPtr ArgHandle { get; } diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs index 5b6f81ea24a..4f688e29708 100644 --- a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamServiceCoreBackend.cs @@ -19,6 +19,9 @@ namespace Tizen.Applications.CoreBackend { + /// + /// Backend implementation for Team service applications that run without a graphical UI. + /// internal class TeamServiceCoreBackend : TeamCoreBackend { internal new static string LogTag = "DN_TAM"; diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs index 151e1edd23a..45e06f4f7d7 100644 --- a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamUICoreBackend.cs @@ -20,6 +20,9 @@ namespace Tizen.Applications.CoreBackend { + /// + /// Backend implementation for Team UI applications that own a default . + /// internal class TeamUICoreBackend : TeamCoreBackend { internal new static string LogTag = "DN_TAM"; diff --git a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs index 69083906271..dbffc71a4bb 100644 --- a/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs +++ b/src/Tizen.Applications.Team/Tizen.Applications.CoreBackend/TeamViewCoreBackend.cs @@ -21,6 +21,9 @@ namespace Tizen.Applications.CoreBackend { + /// + /// Backend implementation for Team view applications that render into a shared host-provided . + /// internal class TeamViewCoreBackend : TeamCoreBackend { internal new static string LogTag = "DN_TAM";