2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
21 using Tizen.Applications;
22 using System.ComponentModel;
23 using System.Runtime.InteropServices;
24 using System.Runtime.Loader;
25 using System.Reflection;
26 using System.Threading.Tasks;
27 using System.Security.AccessControl;
29 using SystemIO = System.IO;
34 /// This class has the methods and events of the NUIGadgetManager.
36 /// <since_tizen> 10 </since_tizen>
37 [EditorBrowsable(EditorBrowsableState.Never)]
38 public static class NUIGadgetManager
40 private static readonly Dictionary<string, NUIGadgetInfo> _gadgetInfos = new Dictionary<string, NUIGadgetInfo>();
41 private static readonly List<NUIGadget> _gadgets = new List<NUIGadget>();
43 static NUIGadgetManager()
45 IntPtr gadgetPkgIds = Interop.Libc.GetEnviornmentVariable("GADGET_PKGIDS");
46 if (gadgetPkgIds != IntPtr.Zero)
48 string packages = Marshal.PtrToStringAnsi(gadgetPkgIds);
49 if (string.IsNullOrEmpty(packages))
51 Log.Warn("There is no resource packages");
55 foreach (string packageId in packages.Split(':').ToList())
57 NUIGadgetInfo info = NUIGadgetInfo.CreateNUIGadgetInfo(packageId);
60 _gadgetInfos.Add(info.ResourceType, info);
67 Log.Warn("Failed to get environment variable");
70 var context = (CoreApplication)CoreApplication.Current;
71 context.AppControlReceived += OnAppControlReceived;
72 context.LowMemory += OnLowMemory;
73 context.LowBattery += OnLowBattery;
74 context.LocaleChanged += OnLocaleChanged;
75 context.RegionFormatChanged += OnRegionFormatChanged;
76 context.DeviceOrientationChanged += OnDeviceOrientationChanged;
79 private static void OnAppControlReceived(object sender, AppControlReceivedEventArgs args)
81 HandleAppControl(args);
84 private static void OnLowMemory(object sender, LowMemoryEventArgs args)
86 HandleEvents(NUIGadgetEventType.LowMemory, args);
89 private static void OnLowBattery(object sender, LowBatteryEventArgs args)
91 HandleEvents(NUIGadgetEventType.LowBattery, args);
94 private static void OnLocaleChanged(object sender, LocaleChangedEventArgs args)
96 HandleEvents(NUIGadgetEventType.LocaleChanged, args);
99 private static void OnRegionFormatChanged(object sender, RegionFormatChangedEventArgs args)
101 HandleEvents(NUIGadgetEventType.RegionFormatChanged, args);
104 private static void OnDeviceOrientationChanged(object sender, DeviceOrientationEventArgs args)
106 HandleEvents(NUIGadgetEventType.DeviceORientationChanged, args);
110 /// Occurs when the lifecycle of the NUIGadget is changed.
112 /// <since_tizen> 10 </since_tizen>
113 public static event EventHandler<NUIGadgetLifecycleChangedEventArgs> NUIGadgetLifecycleChanged;
115 private static void OnNUIGadgetLifecycleChanged(object sender, NUIGadgetLifecycleChangedEventArgs args)
117 NUIGadgetLifecycleChanged?.Invoke(sender, args);
119 if (args.State == NUIGadgetLifecycleState.Destroyed)
121 args.Gadget.LifecycleChanged -= OnNUIGadgetLifecycleChanged;
122 _gadgets.Remove(args.Gadget);
126 private static NUIGadgetInfo Find(string resourceType)
128 if (!_gadgetInfos.TryGetValue(resourceType, out NUIGadgetInfo info))
130 throw new ArgumentException("Failed to find NUIGadgetInfo. resource type: " + resourceType);
137 /// Loads an assembly of the NUIGadget.
139 /// <param name="resourceType">The resource type of the NUIGadget package.</param>
140 /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
141 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
142 /// <since_tizen> 10 </since_tizen>
143 public static void Load(string resourceType)
145 Load(resourceType, true);
149 /// Loads an assembly of the NUIGadget.
151 /// <param name="resourceType">The resource type of the NUIGadget package.</param>
152 /// <param name="useDefaultContext">The flag if ture, use a default load context. Otherwise, use a new load context.</param>
153 /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
154 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
155 /// <since_tizen> 10 </since_tizen>
156 public static void Load(string resourceType, bool useDefaultContext)
158 if (string.IsNullOrEmpty(resourceType))
160 throw new ArgumentException("Invalid argument");
163 NUIGadgetInfo info = Find(resourceType);
164 Load(info, useDefaultContext);
168 /// Unloads the loaded assembly of the NUIGadget.
170 /// <param name="resourceType">The resource type of the NUIGadget package.</param>
171 /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
172 /// <since_tizen> 10 </since_tizen>
173 public static void Unload(string resourceType)
175 if (string.IsNullOrEmpty(resourceType))
177 throw new ArgumentException("Invalid argument");
180 NUIGadgetInfo info = Find(resourceType);
184 private static void Unload(NUIGadgetInfo info)
188 throw new ArgumentException("Invalid argument");
193 if (info.NUIGadgetAssembly != null && info.NUIGadgetAssembly.IsLoaded)
195 info.NUIGadgetAssembly.Unload();
196 info.NUIGadgetAssembly = null;
201 private static void Load(NUIGadgetInfo info, bool useDefaultContext)
205 throw new ArgumentException("Invalid argument");
212 if (useDefaultContext)
214 if (info.Assembly == null)
217 Log.Warn("NUIGadget.Load(): " + info.ResourcePath + info.ExecutableFile + " ++");
218 info.Assembly = Assembly.Load(SystemIO.Path.GetFileNameWithoutExtension(info.ExecutableFile));
219 Log.Warn("NUIGadget.Load(): " + info.ResourcePath + info.ExecutableFile + " --");
224 if (info.NUIGadgetAssembly == null)
226 Log.Warn("NUIGadgetAssembly.Load(): " + info.ResourcePath + info.ExecutableFile + " ++");
227 info.NUIGadgetAssembly = new NUIGadgetAssembly(info.ResourcePath + info.ExecutableFile);
228 info.NUIGadgetAssembly.Load();
229 Log.Warn("NUIGadgetAssembly.Load(): " + info.ResourcePath + info.ExecutableFile + " --");
234 catch (FileLoadException e)
236 throw new InvalidOperationException(e.Message);
238 catch (BadImageFormatException e)
240 throw new InvalidOperationException(e.Message);
245 /// Adds a NUIGadget to the NUIGadgetManager.
247 /// <param name="resourceType">The resource type of the NUIGadget package.</param>
248 /// <param name="className">The class name of the NUIGadget.</param>
249 /// <returns>The NUIGadget object.</returns>
250 /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
251 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
252 /// <since_tizen> 10 </since_tizen>
253 public static NUIGadget Add(string resourceType, string className)
255 return Add(resourceType, className, true);
259 /// Adds a NUIGadget to the NUIGadgetManager.
261 /// <param name="resourceType">The resource type of the NUIGadget package.</param>
262 /// <param name="className">The class name of the NUIGadget.</param>
263 /// <param name="useDefaultContext">The flag it true, use a default context. Otherwise, use a new load context.</param>
264 /// <returns>The NUIGadget object.</returns>
265 /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
266 /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
267 /// <since_tizen> 10 </since_tizen>
268 public static NUIGadget Add(string resourceType, string className, bool useDefaultContext)
270 if (string.IsNullOrEmpty(resourceType) || string.IsNullOrEmpty(className))
272 throw new ArgumentException("Invalid argument");
275 NUIGadgetInfo info = Find(resourceType);
276 Load(info, useDefaultContext);
278 NUIGadget gadget = useDefaultContext ? info.Assembly.CreateInstance(className, true) as NUIGadget : info.NUIGadgetAssembly.CreateInstance(className);
281 throw new InvalidOperationException("Failed to create instance. className: " + className);
284 gadget.NUIGadgetInfo = info;
285 gadget.ClassName = className;
286 gadget.NUIGadgetResourceManager = new NUIGadgetResourceManager(info);
287 gadget.LifecycleChanged += OnNUIGadgetLifecycleChanged;
288 if (!gadget.Create())
290 throw new InvalidOperationException("The View MUST be created");
293 _gadgets.Add(gadget);
298 /// Gets the instance of the running NUIGadgets.
300 /// <returns>The NUIGadget list.</returns>
301 /// <since_tizen> 10 </since_tizen>
302 public static IEnumerable<NUIGadget> GetGadgets()
308 /// Gets the information of the available NUIGadgets.
311 /// This method only returns the available gadget informations, not all installed gadget informations.
312 /// The resource package of the NUIGadget can set the allowed packages using "allowed-package".
313 /// When executing an application, the platform mounts the resource package into the resource path of the application.
315 /// <returns>The NUIGadgetInfo list.</returns>
316 /// <since_tizen> 10 </since_tizen>
317 public static IEnumerable<NUIGadgetInfo> GetGadgetInfos()
319 return _gadgetInfos.Values.ToList();
323 /// Removes the NUIGadget from the NUIGadgetManager.
325 /// <param name="gadget">The NUIGadget object.</param>
326 /// <since_tizen> 10 </since_tizen>
327 public static void Remove(NUIGadget gadget)
329 if (gadget == null || !_gadgets.Contains(gadget))
334 if (gadget.State == NUIGadgetLifecycleState.Destroyed)
339 _gadgets.Remove(gadget);
340 CoreApplication.Post(() => {
341 Log.Warn("ResourceType: " + gadget.NUIGadgetInfo.ResourceType + ", State: " + gadget.State);
347 /// Removes all NUIGadgets from the NUIGadgetManager.
349 /// <since_tizen> 10 </since_tizen>
350 public static void RemoveAll()
352 for (int i = _gadgets.Count - 1; i >= 0; i--)
359 /// Resumes the running NUIGadget.
361 /// <param name="gadget">The NUIGadget object.</param>
362 /// <since_tizen> 10 </since_tizen>
363 public static void Resume(NUIGadget gadget)
365 if (!_gadgets.Contains(gadget))
370 CoreApplication.Post(() =>
372 Log.Warn("ResourceType: " + gadget.NUIGadgetInfo.ResourceType + ", State: " + gadget.State);
378 /// Pauses the running NUIGadget.
380 /// <param name="gadget">The NUIGadget object.</param>
381 /// <since_tizen> 10 </since_tizen>
382 public static void Pause(NUIGadget gadget)
384 if (!_gadgets.Contains(gadget))
389 CoreApplication.Post(() =>
391 Log.Warn("ResourceType: " + gadget.NUIGadgetInfo.ResourceType + ", State: " + gadget.State);
397 /// Sends the appcontrol to the running NUIGadget.
399 /// <param name="gadget">The NUIGadget object.</param>
400 /// <param name="appControl">The appcontrol object.</param>
401 /// <exception cref="ArgumentException">Thrown when failed because of a invalid argument.</exception>
402 /// <exception cref="ArgumentNullException">Thrown when failed because the argument is null.</exception>
403 /// <since_tizen> 10 </since_tizen>
404 public static void SendAppControl(NUIGadget gadget, AppControl appControl)
408 throw new ArgumentNullException(nameof(gadget));
411 if (!_gadgets.Contains(gadget))
413 throw new ArgumentException("Invalid argument");
416 if (appControl == null)
418 throw new ArgumentNullException(nameof(appControl));
421 gadget.HandleAppControlReceivedEvent(new AppControlReceivedEventArgs(new ReceivedAppControl(appControl.SafeAppControlHandle)));
424 internal static bool HandleAppControl(AppControlReceivedEventArgs args)
426 var extraData = args.ReceivedAppControl?.ExtraData;
427 if (extraData == null||!extraData.TryGet("__K_GADGET_RES_TYPE", out string resourceType) ||
428 !extraData.TryGet("__K_GADGET_CLASS_NAME", out string className))
433 foreach (NUIGadget gadget in _gadgets)
435 if (gadget.NUIGadgetInfo.ResourceType == resourceType && gadget.ClassName == className)
437 gadget.HandleAppControlReceivedEvent(args);
445 internal static void HandleEvents(NUIGadgetEventType eventType, EventArgs args)
447 foreach (NUIGadget gadget in _gadgets)
449 gadget.HandleEvents(eventType, args);