Fix ApplicationManagerImpl/MessagePort finalizer
[platform/core/csapi/tizenfx.git] / Tizen.Applications / Tizen.Applications.Managers / ApplicationManagerImpl.cs
1 /// Copyright 2016 by Samsung Electronics, Inc.,
2 ///
3 /// This software is the confidential and proprietary information
4 /// of Samsung Electronics, Inc. ("Confidential Information"). You
5 /// shall not disclose such Confidential Information and shall use
6 /// it only in accordance with the terms of the license agreement
7 /// you entered into with Samsung.
8
9
10 using System;
11 using System.Collections.Generic;
12 using System.Threading.Tasks;
13 using System.Runtime.InteropServices;
14
15 namespace Tizen.Applications.Managers
16 {
17     internal class ApplicationManagerImpl : IDisposable
18     {
19         private static ApplicationManagerImpl s_instance = new ApplicationManagerImpl();
20
21         private bool _disposed = false;
22         private Interop.ApplicationManager.AppManagerAppContextEventCallback _applicationChangedEventCallback;
23
24         private const string LogTag = "Tizen.Applications.Managers";
25
26         private ApplicationManagerImpl()
27         {
28             Log.Debug(LogTag, "ApplicationManagerImpl()");
29             RegisterApplicationChangedEvent();
30         }
31
32
33         ~ApplicationManagerImpl()
34         {
35             Dispose(false);
36         }
37
38         internal event EventHandler<ApplicationChangedEventArgs> ApplicationLaunched;
39         internal event EventHandler<ApplicationChangedEventArgs> ApplicationTerminated;
40
41         internal static ApplicationManagerImpl Instance
42         {
43             get
44             {
45                 return s_instance;
46             }
47         }
48
49         public void Dispose()
50         {
51             Dispose(true);
52             GC.SuppressFinalize(this);
53         }
54
55         private void Dispose(bool disposing)
56         {
57             if (_disposed)
58                 return;
59
60             if (disposing)
61             {
62                 // Free managed objects.
63             }
64             //Free unmanaged objects
65             UnRegisterApplicationChangedEvent();
66             _disposed = true;
67         }
68
69         internal async Task<IEnumerable<InstalledApplication>> GetInstalledAppsAsync()
70         {
71             Log.Debug(LogTag, "GetInstalledAppsAsync()");
72             return await Task.Run(() =>
73             {
74                 List<InstalledApplication> Result = new List<InstalledApplication>();
75
76                 Interop.ApplicationManager.AppManagerAppInfoCallback cb = (IntPtr handle, IntPtr userData) =>
77                 {
78                     if (handle != IntPtr.Zero)
79                     {
80                         IntPtr clonedHandle = IntPtr.Zero;
81                         int result = Interop.ApplicationManager.AppInfoClone(out clonedHandle, handle);
82                         if (result != 0)
83                         {
84                             return false;
85                         }
86                         InstalledApplication app = new InstalledApplication(clonedHandle);
87                         Result.Add(app);
88                         return true;
89                     }
90                     return false;
91                 };
92                 int ret = Interop.ApplicationManager.AppManagerForeachAppInfo(cb, IntPtr.Zero);
93                 if (ret != 0)
94                 {
95                     ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetInstalledAppsAsync() failed.");
96                 }
97                 return Result;
98             });
99         }
100
101         internal async Task<IEnumerable<InstalledApplication>> GetInstalledAppsAsync(InstalledApplicationFilter filter)
102         {
103             Log.Debug(LogTag, "GetInstalledAppsAsync(InstalledApplicationFilter filter)");
104             return await Task.Run(() =>
105             {
106                 List<InstalledApplication> Result = new List<InstalledApplication>();
107
108                 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr handle, IntPtr userData) =>
109                 {
110                     Log.Debug(LogTag, "AppInfoFilterCallback");
111                     if (handle != IntPtr.Zero)
112                     {
113                         IntPtr clonedHandle = IntPtr.Zero;
114                         int ret = Interop.ApplicationManager.AppInfoClone(out clonedHandle, handle);
115                         if (ret != 0)
116                         {
117                             return false;
118                         }
119                         InstalledApplication app = new InstalledApplication(clonedHandle);
120                         Result.Add(app);
121                         return true;
122                     }
123                     return false;
124                 };
125                 filter.Fetch(cb);
126                 return Result;
127             });
128         }
129         internal async Task<IEnumerable<RunningApplication>> GetRunningAppsAsync()
130         {
131             Log.Debug(LogTag, "GetRunningAppsAsync()");
132
133             return await Task.Run(() =>
134             {
135                 List<RunningApplication> Result = new List<RunningApplication>();
136
137                 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr handle, IntPtr userData) =>
138                 {
139                     Log.Debug(LogTag, "AppManagerAppContextCallback");
140                     if (handle != IntPtr.Zero)
141                     {
142                         IntPtr ptr = IntPtr.Zero;
143                         int result = Interop.ApplicationManager.AppContextGetAppId(handle, out ptr);
144                         if (result != 0)
145                         {
146                             return false;
147                         }
148                         string appid = Marshal.PtrToStringAuto(ptr);
149                         int pid = 0;
150                         result = Interop.ApplicationManager.AppContextGetPid(handle, out pid);
151                         if (result != 0)
152                         {
153                             return false;
154                         }
155                         RunningApplication app = new RunningApplication(appid, pid);
156                         Result.Add(app);
157                         return true;
158                     }
159                     return false;
160                 };
161
162                 int ret = Interop.ApplicationManager.AppManagerForeachAppContext(cb, IntPtr.Zero);
163                 if (ret != 0)
164                 {
165                     ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetRunningAppsAsync() failed.");
166                 }
167                 return Result;
168             });
169         }
170
171         internal InstalledApplication GetInstalledApp(string applicationId)
172         {
173             Log.Debug(LogTag, "GetInstalledApp(applicationId)");
174             IntPtr handle = IntPtr.Zero;
175             int ret = Interop.ApplicationManager.AppManagerGetAppInfo(applicationId, out handle);
176             if (ret != 0)
177             {
178                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetInstalledApp(applicationId) failed.");
179             }
180             if (handle != IntPtr.Zero)
181             {
182                 InstalledApplication app = new InstalledApplication(handle);
183                 return app;
184             }
185             return null;
186         }
187
188         internal RunningApplication GetRunningApp(string applicationId)
189         {
190             Log.Debug(LogTag, "GetRunningApp(applicationId)");
191             IntPtr handle = IntPtr.Zero;
192             int ret = Interop.ApplicationManager.AppManagerGetAppContext(applicationId, out handle);
193             if (ret != 0)
194             {
195                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetRunningApp(applicationId) failed.");
196             }
197             if (handle != IntPtr.Zero)
198             {
199                 int pid = 0;
200                 ret = Interop.ApplicationManager.AppContextGetPid(handle, out pid);
201                 if (ret != 0)
202                 {
203                     ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetRunningApp(applicationId) failed.");
204                 }
205                 RunningApplication app = new RunningApplication(applicationId, pid);
206                 return app;
207             }
208             return null;
209         }
210
211         internal RunningApplication GetRunningApp(int processId)
212         {
213             Log.Debug(LogTag, "GetRunningApp(processId)");
214             string appid = "";
215             int ret = Interop.ApplicationManager.AppManagerGetAppId(processId, out appid);
216             if (ret != 0)
217             {
218                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetRunningApp(processId) failed.");
219             }
220             RunningApplication app = new RunningApplication(appid, processId);
221             return app;
222         }
223
224         internal bool IsRunningApp(string applicationId)
225         {
226             Log.Debug(LogTag, "IsRunningApp(applicationId)");
227             bool running = false;
228             int ret = Interop.ApplicationManager.AppManagerIsRunning(applicationId, out running);
229             if (ret != 0)
230             {
231                 Log.Warn(LogTag, "IsRunningApp(applicationId) failed.");
232             }
233             return running;
234         }
235
236         internal bool IsRunningApp(int processId)
237         {
238             Log.Debug(LogTag, "IsRunningApp(processId)");
239             string appid = "";
240             int ret = Interop.ApplicationManager.AppManagerGetAppId(processId, out appid);
241             if (ret != 0)
242             {
243                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "IsRunningApp(processId) failed.");
244             }
245             bool running = false;
246             ret = Interop.ApplicationManager.AppManagerIsRunning(appid, out running);
247             if (ret != 0)
248             {
249                 Log.Warn(LogTag, "IsRunningApp(processId) failed.");
250             }
251             return running;
252         }
253
254         private void RegisterApplicationChangedEvent()
255         {
256             Log.Debug(LogTag, "RegisterApplicationChangedEvent()");
257             _applicationChangedEventCallback = (IntPtr handle, int state, IntPtr userData) =>
258             {
259                 Log.Debug(LogTag, "ApplicationChangedEventCallback");
260                 if (handle == IntPtr.Zero) return;
261
262                 IntPtr ptr = IntPtr.Zero;
263                 int result = Interop.ApplicationManager.AppContextGetAppId(handle, out ptr);
264                 if (result != 0)
265                 {
266                     ApplicationManagerErrorFactory.ExceptionChecker(result, "RegisterApplicationChangedEvent() failed.");
267                 }
268                 string appid = Marshal.PtrToStringAuto(ptr);
269                 int pid = 0;
270                 result = Interop.ApplicationManager.AppContextGetPid(handle, out pid);
271                 if (result != 0)
272                 {
273                     ApplicationManagerErrorFactory.ExceptionChecker(result, "RegisterApplicationChangedEvent() failed.");
274                 }
275                 if (state == 0)
276                 {
277                     var launchedEventCache = ApplicationLaunched;
278                     if (launchedEventCache != null)
279                     {
280                         Log.Debug(LogTag, "Raise up ApplicationLaunched");
281                         ApplicationChangedEventArgs e = new ApplicationChangedEventArgs(appid, pid, state);
282                         launchedEventCache(null, e);
283                     }
284                 }
285                 else if (state == 1)
286                 {
287                     var terminatedEventCache = ApplicationTerminated;
288                     if (terminatedEventCache != null)
289                     {
290                         Log.Debug(LogTag, "Raise up ApplicationTerminated");
291                         ApplicationChangedEventArgs e = new ApplicationChangedEventArgs(appid, pid, state);
292                         terminatedEventCache(null, e);
293                     }
294                 }
295             };
296             int ret = Interop.ApplicationManager.AppManagerSetAppContextEvent(_applicationChangedEventCallback, IntPtr.Zero);
297             if (ret != 0)
298             {
299                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "RegisterApplicationChangedEvent() register failed.");
300             }
301         }
302
303         private void UnRegisterApplicationChangedEvent()
304         {
305             Log.Debug(LogTag, "UnRegisterApplicationChangedEvent()");
306             Interop.ApplicationManager.AppManagerUnSetAppContextEvent();
307         }
308     }
309     internal static class FilterExtension
310     {
311         private const string LogTag = "Tizen.Applications.Managers";
312         internal static void Fetch(this InstalledApplicationFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
313         {
314             if (filter is InstalledApplicationMetadataFilter)
315             {
316                 InstalledApplicationMetadataFilter metaFilter = (InstalledApplicationMetadataFilter)filter;
317                 metaFilter.Fetch(callback);
318                 return;
319             }
320
321             IntPtr nativeHandle = MakeNativeAppInfoFilter(filter.Filter);
322             int ret = Interop.ApplicationManager.AppInfoFilterForeachAppinfo(nativeHandle, callback, IntPtr.Zero);
323             if (nativeHandle != IntPtr.Zero)
324                 Interop.ApplicationManager.AppInfoFilterDestroy(nativeHandle);
325             if (ret != 0)
326             {
327                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetInstalledAppsAsync(InstalledApplicationFilter) failed.");
328             }
329         }
330
331         internal static void Fetch(this InstalledApplicationMetadataFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
332         {
333             IntPtr nativeHandle = MakeNativeAppMetadataFilter(filter.Filter);
334             int ret = Interop.ApplicationManager.AppInfoMetadataFilterForeach(nativeHandle, callback, IntPtr.Zero);
335             if (nativeHandle != IntPtr.Zero)
336                 Interop.ApplicationManager.AppInfoMetadataFilterDestroy(nativeHandle);
337             if (ret != 0)
338             {
339                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "GetInstalledAppsAsync(InstalledApplicationMetadataFilter) failed.");
340             }
341         }
342
343
344         private static IntPtr MakeNativeAppInfoFilter(IDictionary<string, string> filter)
345         {
346             if (filter == null)
347                 throw new ArgumentException("Filter dose not added");
348             IntPtr handle;
349             int ret = Interop.ApplicationManager.AppInfoFilterCreate(out handle);
350             if (ret != 0)
351             {
352                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "AppInfoFilter creation failed.");
353             }
354
355             foreach (var item in filter)
356             {
357                 if ((item.Key == InstalledApplicationFilter.Keys.Id) ||
358                     (item.Key == InstalledApplicationFilter.Keys.Type) ||
359                     (item.Key == InstalledApplicationFilter.Keys.Category))
360                 {
361                     ret = Interop.ApplicationManager.AppInfoFilterAddString(handle, item.Key, item.Value);
362                 }
363                 else if ((item.Key == InstalledApplicationFilter.Keys.NoDisplay) ||
364                          (item.Key == InstalledApplicationFilter.Keys.TaskManage))
365                 {
366                     ret = Interop.ApplicationManager.AppInfoFilterAddBool(handle, item.Key, Convert.ToBoolean(item.Value));
367                 }
368                 else
369                 {
370                     Log.Warn(LogTag, "InstalledApplicationFilter is NOT supported " + item.Key + " key.");
371                 }
372                 if (ret != 0)
373                 {
374                     Interop.ApplicationManager.AppInfoFilterDestroy(handle);
375                     ApplicationManagerErrorFactory.ExceptionChecker(ret, "InstalledApplicationFilter item add failed.");
376                 }
377             }
378             return handle;
379         }
380
381         private static IntPtr MakeNativeAppMetadataFilter(IDictionary<string, string> filter)
382         {
383             if (filter == null)
384                 throw new ArgumentException("Filter dose not added");
385             IntPtr handle;
386             int ret = Interop.ApplicationManager.AppInfoMetadataFilterCreate(out handle);
387             if (ret != 0)
388             {
389                 ApplicationManagerErrorFactory.ExceptionChecker(ret, "InstalledApplicationMetadataFilter creation failed.");
390             }
391             foreach (var item in filter)
392             {
393                 ret = Interop.ApplicationManager.AppInfoMetadataFilterAdd(handle, item.Key, item.Value);
394                 if (ret != 0)
395                 {
396                     Interop.ApplicationManager.AppInfoMetadataFilterDestroy(handle);
397                     ApplicationManagerErrorFactory.ExceptionChecker(ret, "InstalledApplicationMetadataFilter item add failed.");
398                 }
399             }
400             return handle;
401         }
402     }
403 }