[Applications] Fix wrong implementation of AttachWindowBelow method (#3384)
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.Common / Tizen.Applications / ApplicationManager.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 using System;
18 using System.Collections.Generic;
19 using System.ComponentModel;
20 using System.Runtime.InteropServices;
21 using System.Threading.Tasks;
22 using static Interop.ApplicationManager;
23
24 namespace Tizen.Applications
25 {
26     /// <summary>
27     /// This class has the methods and events of the ApplicationManager.
28     /// </summary>
29     /// <since_tizen> 3 </since_tizen>
30     public static class ApplicationManager
31     {
32         private const string LogTag = "Tizen.Applications";
33         private static EventHandler<ApplicationLaunchedEventArgs> s_launchedHandler;
34         private static EventHandler<ApplicationTerminatedEventArgs> s_terminatedHandler;
35         private static Interop.ApplicationManager.AppManagerAppContextEventCallback s_applicationChangedEventCallback;
36         private static EventHandler<ApplicationEnabledEventArgs> s_enabledHandler;
37         private static EventHandler<ApplicationDisabledEventArgs> s_disabledHandler;
38         private static Interop.ApplicationManager.AppManagerEventCallback s_eventCallback;
39         private static IntPtr _eventHandle = IntPtr.Zero;
40         private static readonly object s_eventLock = new object();
41         private static readonly object s_applicationChangedEventLock = new object();
42
43         /// <summary>
44         /// Occurs whenever the installed application is enabled.
45         /// </summary>
46         /// <since_tizen> 3 </since_tizen>
47         public static event EventHandler<ApplicationEnabledEventArgs> ApplicationEnabled
48         {
49             add
50             {
51                 lock (s_eventLock)
52                 {
53                     if (s_eventCallback == null)
54                     {
55                         RegisterApplicationEvent();
56                     }
57                     s_enabledHandler += value;
58                 }
59             }
60             remove
61             {
62                 lock (s_eventLock)
63                 {
64                     s_enabledHandler -= value;
65                     if (s_enabledHandler == null && s_disabledHandler == null && s_eventCallback != null)
66                     {
67                         UnRegisterApplicationEvent();
68                         s_eventCallback = null;
69                     }
70                 }
71             }
72         }
73
74         /// <summary>
75         /// Occurs whenever the installed application is disabled.
76         /// </summary>
77         /// <since_tizen> 3 </since_tizen>
78         public static event EventHandler<ApplicationDisabledEventArgs> ApplicationDisabled
79         {
80             add
81             {
82                 lock (s_eventLock)
83                 {
84                     if (s_eventCallback == null)
85                     {
86                         RegisterApplicationEvent();
87                     }
88                     s_disabledHandler += value;
89                 }
90             }
91             remove
92             {
93                 lock (s_eventLock)
94                 {
95                     s_disabledHandler -= value;
96                     if (s_enabledHandler == null && s_disabledHandler == null && s_eventCallback != null)
97                     {
98                         UnRegisterApplicationEvent();
99                         s_eventCallback = null;
100                     }
101                 }
102             }
103         }
104
105         /// <summary>
106         /// Occurs whenever the installed applications get launched.
107         /// </summary>
108         /// <since_tizen> 3 </since_tizen>
109         public static event EventHandler<ApplicationLaunchedEventArgs> ApplicationLaunched
110         {
111             add
112             {
113                 lock (s_applicationChangedEventLock)
114                 {
115                     if (s_applicationChangedEventCallback == null)
116                     {
117                         RegisterApplicationChangedEvent();
118                     }
119                     s_launchedHandler += value;
120                 }
121             }
122             remove
123             {
124                 lock (s_applicationChangedEventLock)
125                 {
126                     s_launchedHandler -= value;
127                     if (s_launchedHandler == null && s_terminatedHandler == null && s_applicationChangedEventCallback != null)
128                     {
129                         UnRegisterApplicationChangedEvent();
130                         s_applicationChangedEventCallback = null;
131                     }
132                 }
133             }
134         }
135
136         /// <summary>
137         /// Occurs whenever the installed applications get terminated.
138         /// </summary>
139         /// <since_tizen> 3 </since_tizen>
140         public static event EventHandler<ApplicationTerminatedEventArgs> ApplicationTerminated
141         {
142             add
143             {
144                 lock (s_applicationChangedEventLock)
145                 {
146                     if (s_applicationChangedEventCallback == null)
147                     {
148                         RegisterApplicationChangedEvent();
149                     }
150                     s_terminatedHandler += value;
151                 }
152             }
153             remove
154             {
155                 lock (s_applicationChangedEventLock)
156                 {
157                     s_terminatedHandler -= value;
158                     if (s_launchedHandler == null && s_terminatedHandler == null && s_applicationChangedEventCallback != null)
159                     {
160                         UnRegisterApplicationChangedEvent();
161                         s_applicationChangedEventCallback = null;
162                     }
163                 }
164             }
165         }
166
167         /// <summary>
168         /// Gets the information of the installed applications asynchronously.
169         /// </summary>
170         /// <returns>The installed application info list.</returns>
171         /// <since_tizen> 3 </since_tizen>
172         public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync()
173         {
174             return await Task.Run(() =>
175             {
176                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
177                 List<ApplicationInfo> result = new List<ApplicationInfo>();
178
179                 Interop.ApplicationManager.AppManagerAppInfoCallback cb = (IntPtr infoHandle, IntPtr userData) =>
180                 {
181                     if (infoHandle != IntPtr.Zero)
182                     {
183                         IntPtr clonedHandle = IntPtr.Zero;
184                         err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
185                         if (err != Interop.ApplicationManager.ErrorCode.None)
186                         {
187                             Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
188                             return false;
189                         }
190                         ApplicationInfo app = new ApplicationInfo(clonedHandle);
191                         result.Add(app);
192                         return true;
193                     }
194                     return false;
195                 };
196                 err = Interop.ApplicationManager.AppManagerForeachAppInfo(cb, IntPtr.Zero);
197                 if (err != Interop.ApplicationManager.ErrorCode.None)
198                 {
199                     Log.Error(LogTag, "Failed to retrieve the application Info. err " + err.ToString());
200                 }
201                 return result;
202             }).ConfigureAwait(false);
203         }
204
205         /// <summary>
206         /// Terminates the application if it is running on background.
207         /// </summary>
208         /// <param name="app">ApplicationRunningContext object</param>
209         /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
210         /// <exception cref="UnauthorizedAccessException">Thrown when failed because of permission denied.</exception>
211         /// <exception cref="InvalidOperationException">Thrown when failed because of system error.</exception>
212         /// <privilege>http://tizen.org/privilege/appmanager.kill.bgapp</privilege>
213         /// <remarks>
214         /// This function returns after it just sends a request for terminating a background application.
215         /// Platform will decide if the target application could be terminated or not according to the state of the target application.
216         /// </remarks>
217         /// <since_tizen> 6 </since_tizen>
218         public static void TerminateBackgroundApplication(ApplicationRunningContext app)
219         {
220             ErrorCode err = Interop.ApplicationManager.AppManagerRequestTerminateBgApp(app._contextHandle);
221             if (err != Interop.ApplicationManager.ErrorCode.None)
222             {
223                 switch (err)
224                 {
225                     case Interop.ApplicationManager.ErrorCode.InvalidParameter:
226                         throw new ArgumentException("Invalid argument.");
227                     case Interop.ApplicationManager.ErrorCode.PermissionDenied:
228                         throw new UnauthorizedAccessException("Permission denied.");
229                     default:
230                         throw new InvalidOperationException("Invalid Operation.");
231                 }
232             }
233         }
234
235         /// <summary>
236         /// Gets the information of the installed applications with the ApplicationInfoFilter asynchronously.
237         /// </summary>
238         /// <param name="filter">Key-value pairs for filtering.</param>
239         /// <returns>The installed application info list.</returns>
240         /// <since_tizen> 3 </since_tizen>
241         public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync(ApplicationInfoFilter filter)
242         {
243             return await Task.Run(() =>
244             {
245                 List<ApplicationInfo> result = new List<ApplicationInfo>();
246
247                 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr infoHandle, IntPtr userData) =>
248                 {
249                     if (infoHandle != IntPtr.Zero)
250                     {
251                         IntPtr clonedHandle = IntPtr.Zero;
252                         Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
253                         if (err != Interop.ApplicationManager.ErrorCode.None)
254                         {
255                             Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
256                             return false;
257                         }
258                         ApplicationInfo app = new ApplicationInfo(clonedHandle);
259                         result.Add(app);
260                         return true;
261                     }
262                     return false;
263                 };
264
265                 try
266                 {
267                     filter.Fetch(cb);
268                 }
269                 catch (InvalidOperationException)
270                 {
271                     Log.Error(LogTag, "InvalidOperationException occurs");
272                 }
273                 catch (ArgumentException)
274                 {
275                     Log.Error(LogTag, "ArgumentException occurs");
276                 }
277
278                 return result;
279             }).ConfigureAwait(false);
280         }
281
282         /// <summary>
283         /// Gets the information of the installed applications with the ApplicationInfoMetadataFilter asynchronously.
284         /// </summary>
285         /// <param name="filter">Key-value pairs for filtering.</param>
286         /// <returns>The installed application info list.</returns>
287         /// <since_tizen> 3 </since_tizen>
288         public static async Task<IEnumerable<ApplicationInfo>> GetInstalledApplicationsAsync(ApplicationInfoMetadataFilter filter)
289         {
290             return await Task.Run(() =>
291             {
292                 List<ApplicationInfo> result = new List<ApplicationInfo>();
293
294                 Interop.ApplicationManager.AppInfoFilterCallback cb = (IntPtr infoHandle, IntPtr userData) =>
295                 {
296                     if (infoHandle != IntPtr.Zero)
297                     {
298                         IntPtr clonedHandle = IntPtr.Zero;
299                         Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoClone(out clonedHandle, infoHandle);
300                         if (err != Interop.ApplicationManager.ErrorCode.None)
301                         {
302                             Log.Warn(LogTag, "Failed to clone the appinfo. err = " + err);
303                             return false;
304                         }
305                         ApplicationInfo app = new ApplicationInfo(clonedHandle);
306                         result.Add(app);
307                         return true;
308                     }
309                     return false;
310                 };
311
312                 try
313                 {
314                     filter.Fetch(cb);
315                 }
316                 catch (InvalidOperationException)
317                 {
318                     Log.Error(LogTag, "InvalidOperationException occurs");
319                 }
320                 catch (ArgumentException)
321                 {
322                     Log.Error(LogTag, "ArgumentException occurs");
323                 }
324
325                 return result;
326             }).ConfigureAwait(false);
327         }
328
329         /// <summary>
330         /// Gets the information of the running applications asynchronously.
331         /// </summary>
332         /// <returns>The application running context list.</returns>
333         /// <since_tizen> 3 </since_tizen>
334         public static async Task<IEnumerable<ApplicationRunningContext>> GetRunningApplicationsAsync()
335         {
336             return await Task.Run(() =>
337             {
338                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
339                 List<ApplicationRunningContext> result = new List<ApplicationRunningContext>();
340
341                 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr contextHandle, IntPtr userData) =>
342                 {
343                     if (contextHandle != IntPtr.Zero)
344                     {
345                         IntPtr clonedHandle = IntPtr.Zero;
346                         err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
347                         if (err != Interop.ApplicationManager.ErrorCode.None)
348                         {
349                             Log.Warn(LogTag, "Failed to clone the app context. err = " + err);
350                             return false;
351                         }
352                         ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle);
353                         result.Add(context);
354                         return true;
355                     }
356                     return false;
357                 };
358
359                 err = Interop.ApplicationManager.AppManagerForeachAppContext(cb, IntPtr.Zero);
360                 if (err != Interop.ApplicationManager.ErrorCode.None)
361                 {
362                     Log.Error(LogTag, "Failed to retrieve the running app context. err " + err.ToString());
363                 }
364                 return result;
365             }).ConfigureAwait(false);
366         }
367
368         /// <summary>
369         /// Gets the information of the running applications including subapp asynchronously.
370         /// </summary>
371         /// <returns>The application running context list.</returns>
372         /// <since_tizen> 3 </since_tizen>
373         public static async Task<IEnumerable<ApplicationRunningContext>> GetAllRunningApplicationsAsync()
374         {
375             return await Task.Run(() =>
376             {
377                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
378                 List<ApplicationRunningContext> result = new List<ApplicationRunningContext>();
379
380                 Interop.ApplicationManager.AppManagerAppContextCallback cb = (IntPtr contextHandle, IntPtr userData) =>
381                 {
382                     if (contextHandle != IntPtr.Zero)
383                     {
384                         IntPtr clonedHandle = IntPtr.Zero;
385                         err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
386                         if (err != Interop.ApplicationManager.ErrorCode.None)
387                         {
388                             Log.Warn(LogTag, "Failed to clone the app context. err = " + err);
389                             return false;
390                         }
391                         ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle);
392                         result.Add(context);
393                         return true;
394                     }
395                     return false;
396                 };
397
398                 err = Interop.ApplicationManager.AppManagerForeachRunningAppContext(cb, IntPtr.Zero);
399                 if (err != Interop.ApplicationManager.ErrorCode.None)
400                 {
401                     Log.Error(LogTag, "Failed to retrieve the running app context. err " + err.ToString());
402                 }
403                 return result;
404             }).ConfigureAwait(false);
405         }
406
407         /// <summary>
408         /// Gets the information of the specified application with the application ID.
409         /// </summary>
410         /// <param name="applicationId">Application ID.</param>
411         /// <returns>The application info.</returns>
412         /// <since_tizen> 3 </since_tizen>
413         public static ApplicationInfo GetInstalledApplication(string applicationId)
414         {
415             IntPtr infoHandle = IntPtr.Zero;
416             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerGetAppInfo(applicationId, out infoHandle);
417             if (err != Interop.ApplicationManager.ErrorCode.None)
418             {
419                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to get the installed application information of " + applicationId + ".");
420             }
421             ApplicationInfo app = new ApplicationInfo(infoHandle);
422             return app;
423         }
424
425         /// <summary>
426         /// Returns if the specified application is running or not.
427         /// </summary>
428         /// <param name="applicationId">The application ID.</param>
429         /// <returns>Returns true if the given application is running, otherwise false.</returns>
430         /// <exception cref="ArgumentException">Thrown when the given parameter is invalid.</exception>
431         /// <since_tizen> 3 </since_tizen>
432         public static bool IsRunning(string applicationId)
433         {
434             bool isRunning = false;
435             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerIsRunning(applicationId, out isRunning);
436             if (err != Interop.ApplicationManager.ErrorCode.None)
437             {
438                 throw ApplicationManagerErrorFactory.GetException(Interop.ApplicationManager.ErrorCode.InvalidParameter, "Invalid parameter");
439             }
440             return isRunning;
441         }
442
443         /// <summary>
444         /// Returns the application id.
445         /// </summary>
446         /// <param name="processId">The application pid.</param>
447         /// <returns>Returns the application id.</returns>
448         /// <exception cref="ArgumentException">Thrown when the given parameter is invalid.</exception>
449         /// <since_tizen> 6 </since_tizen>
450         public static string GetAppId(int processId)
451         {
452             string appid;
453             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppManagerGetAppId(processId, out appid);
454             if (err != Interop.ApplicationManager.ErrorCode.None)
455             {
456                 throw ApplicationManagerErrorFactory.GetException(err, "fail to get appid(" + processId + ")");
457             }
458             return appid;
459         }
460
461         private static void RegisterApplicationChangedEvent()
462         {
463             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
464             s_applicationChangedEventCallback = (IntPtr contextHandle, Interop.ApplicationManager.AppContextEvent state, IntPtr userData) =>
465             {
466                 if (contextHandle == IntPtr.Zero) return;
467
468                 IntPtr clonedHandle = IntPtr.Zero;
469                 err = Interop.ApplicationManager.AppContextClone(out clonedHandle, contextHandle);
470                 if (err != Interop.ApplicationManager.ErrorCode.None)
471                 {
472                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to register the application context event.");
473                 }
474                 using (ApplicationRunningContext context = new ApplicationRunningContext(clonedHandle))
475                 {
476                     lock (s_applicationChangedEventLock)
477                     {
478                         if (state == Interop.ApplicationManager.AppContextEvent.Launched)
479                         {
480                             s_launchedHandler?.Invoke(null, new ApplicationLaunchedEventArgs { ApplicationRunningContext = context });
481                         }
482                         else if (state == Interop.ApplicationManager.AppContextEvent.Terminated)
483                         {
484                             s_terminatedHandler?.Invoke(null, new ApplicationTerminatedEventArgs { ApplicationRunningContext = context });
485                         }
486                     }
487                 }
488             };
489             err = Interop.ApplicationManager.AppManagerSetAppContextEvent(s_applicationChangedEventCallback, IntPtr.Zero);
490             if (err != Interop.ApplicationManager.ErrorCode.None)
491             {
492                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to register the application context event.");
493             }
494         }
495
496         private static void UnRegisterApplicationChangedEvent()
497         {
498             Interop.ApplicationManager.AppManagerUnSetAppContextEvent();
499         }
500
501         private static void RegisterApplicationEvent()
502         {
503             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
504             err = Interop.ApplicationManager.AppManagerEventCreate(out _eventHandle);
505             if (err != Interop.ApplicationManager.ErrorCode.None)
506             {
507                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the application event handle");
508             }
509
510             err = Interop.ApplicationManager.AppManagerEventSetStatus(_eventHandle, Interop.ApplicationManager.AppManagerEventStatusType.All);
511             if (err != Interop.ApplicationManager.ErrorCode.None)
512             {
513                 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
514                 _eventHandle = IntPtr.Zero;
515                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to set the application event");
516             }
517
518             s_eventCallback = (string appType, string appId, Interop.ApplicationManager.AppManagerEventType eventType, Interop.ApplicationManager.AppManagerEventState eventState, IntPtr eventHandle, IntPtr UserData) =>
519             {
520                 lock (s_eventLock)
521                 {
522                     if (eventType == Interop.ApplicationManager.AppManagerEventType.Enable)
523                     {
524                         s_enabledHandler?.Invoke(null, new ApplicationEnabledEventArgs(appId, (ApplicationEventState)eventState));
525                     }
526                     else if (eventType == Interop.ApplicationManager.AppManagerEventType.Disable)
527                     {
528                         s_disabledHandler?.Invoke(null, new ApplicationDisabledEventArgs(appId, (ApplicationEventState)eventState));
529                     }
530                 }
531             };
532             err = Interop.ApplicationManager.AppManagerSetEventCallback(_eventHandle, s_eventCallback, IntPtr.Zero);
533             if (err != Interop.ApplicationManager.ErrorCode.None)
534             {
535                 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
536                 _eventHandle = IntPtr.Zero;
537                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to set the application event callback");
538             }
539         }
540
541         private static void UnRegisterApplicationEvent()
542         {
543             if (_eventHandle != IntPtr.Zero)
544             {
545                 Interop.ApplicationManager.AppManagerUnSetEventCallback(_eventHandle);
546                 Interop.ApplicationManager.AppManagerEventDestroy(_eventHandle);
547                 _eventHandle = IntPtr.Zero;
548             }
549         }
550
551         /// <summary>
552         /// Gets the information of the recent applications.
553         /// </summary>
554         /// <returns>Returns a dictionary containing all the recent application info.</returns>
555         /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
556         /// <since_tizen> 3 </since_tizen>
557         [EditorBrowsable(EditorBrowsableState.Never)]
558         public static IEnumerable<RecentApplicationInfo> GetRecentApplications()
559         {
560             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
561
562             List<RecentApplicationInfo> result = new List<RecentApplicationInfo>();
563             IntPtr table;
564             int nrows, ncols;
565
566             err = Interop.ApplicationManager.RuaHistoryLoadDb(out table, out nrows, out ncols);
567             if (err != Interop.ApplicationManager.ErrorCode.None)
568             {
569                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to load a table for the recent application list.");
570             }
571
572             for (int row = 0; row < nrows; ++row)
573             {
574                 Interop.ApplicationManager.RuaRec record;
575
576                 err = Interop.ApplicationManager.RuaHistoryGetRecord(out record, table, nrows, ncols, row);
577                 if (err != Interop.ApplicationManager.ErrorCode.None)
578                 {
579                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to get record.");
580                 }
581
582                 RecentApplicationInfo info = new RecentApplicationInfo(record);
583                 result.Add(info);
584             }
585
586             err = Interop.ApplicationManager.RuaHistoryUnLoadDb(ref table);
587             if (err != Interop.ApplicationManager.ErrorCode.None)
588             {
589                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to unload a table for the recent application list.");
590             }
591
592             return result;
593         }
594
595         /// <summary>
596         /// Attaches the window of the child application to the window of the parent application.
597         /// </summary>
598         /// <remarks>
599         /// This method is only available for platform level signed applications.
600         /// </remarks>
601         /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
602         /// <exception cref="UnauthorizedAccessException">Thrown when failed because of permission denied.</exception>
603         /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
604         /// <since_tizen> 8 </since_tizen>
605         [EditorBrowsable(EditorBrowsableState.Never)]
606         public static void AttachWindow(string parentAppId, string childAppId)
607         {
608             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
609
610             err = Interop.ApplicationManager.AppManagerAttachWindow(parentAppId, childAppId);
611             if (err != Interop.ApplicationManager.ErrorCode.None)
612             {
613                 switch (err)
614                 {
615                     case Interop.ApplicationManager.ErrorCode.InvalidParameter:
616                         throw new ArgumentException("Invalid argument.");
617                     case Interop.ApplicationManager.ErrorCode.PermissionDenied:
618                         throw new UnauthorizedAccessException("Permission denied.");
619                     case Interop.ApplicationManager.ErrorCode.IoError:
620                         throw new InvalidOperationException("IO error at unmanaged code.");
621                     case Interop.ApplicationManager.ErrorCode.OutOfMemory:
622                         throw new InvalidOperationException("Out-of-memory at unmanaged code.");
623                     case Interop.ApplicationManager.ErrorCode.NoSuchApp:
624                         throw new InvalidOperationException("No such application.");
625                 }
626             }
627
628         }
629
630         /// <summary>
631         /// Detaches the window of the application from its parent window.
632         /// </summary>
633         /// <remarks>
634         /// This method is only available for platform level signed applications.
635         /// </remarks>
636         /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
637         /// <exception cref="UnauthorizedAccessException">Thrown when failed because of permission denied.</exception>
638         /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
639         /// <since_tizen> 8 </since_tizen>
640         [EditorBrowsable(EditorBrowsableState.Never)]
641         public static void DetachWindow(string applicationId)
642         {
643             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
644
645             err = Interop.ApplicationManager.AppManagerDetachWindow(applicationId);
646             if (err != Interop.ApplicationManager.ErrorCode.None)
647             {
648                 switch (err)
649                 {
650                     case Interop.ApplicationManager.ErrorCode.InvalidParameter:
651                         throw new ArgumentException("Invalid argument.");
652                     case Interop.ApplicationManager.ErrorCode.PermissionDenied:
653                         throw new UnauthorizedAccessException("Permission denied.");
654                     case Interop.ApplicationManager.ErrorCode.IoError:
655                         throw new InvalidOperationException("IO error at unmanaged code.");
656                     case Interop.ApplicationManager.ErrorCode.OutOfMemory:
657                         throw new InvalidOperationException("Out-of-memory at unmanaged code.");
658                     case Interop.ApplicationManager.ErrorCode.NoSuchApp:
659                         throw new InvalidOperationException("No such application.");
660                 }
661             }
662         }
663
664         /// <summary>
665         /// Attaches the window of the child application below the window of the parent application.
666         /// </summary>
667         /// <remarks>
668         /// This method is only available for platform level signed applications.
669         /// </remarks>
670         /// <exception cref="ArgumentException">Thrown when failed of invalid argument.</exception>
671         /// <exception cref="UnauthorizedAccessException">Thrown when failed because of permission denied.</exception>
672         /// <exception cref="InvalidOperationException">Thrown when failed because of an invalid operation.</exception>
673         /// <since_tizen> 9 </since_tizen>
674         [EditorBrowsable(EditorBrowsableState.Never)]
675         public static void AttachWindowBelow(string parentAppId, string childAppId)
676         {
677             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.ErrorCode.None;
678
679             err = Interop.ApplicationManager.AppManagerAttachWindowBelow(parentAppId, childAppId);
680             if (err != Interop.ApplicationManager.ErrorCode.None)
681             {
682                 switch (err)
683                 {
684                     case Interop.ApplicationManager.ErrorCode.InvalidParameter:
685                         throw new ArgumentException("Invalid argument.");
686                     case Interop.ApplicationManager.ErrorCode.PermissionDenied:
687                         throw new UnauthorizedAccessException("Permission denied.");
688                     case Interop.ApplicationManager.ErrorCode.IoError:
689                         throw new InvalidOperationException("IO error at unmanaged code.");
690                     case Interop.ApplicationManager.ErrorCode.OutOfMemory:
691                         throw new InvalidOperationException("Out-of-memory at unmanaged code.");
692                     case Interop.ApplicationManager.ErrorCode.NoSuchApp:
693                         throw new InvalidOperationException("No such application.");
694                 }
695             }
696         }
697     }
698
699     internal static class FilterExtension
700     {
701         private const string LogTag = "Tizen.Applications";
702         internal static void Fetch(this ApplicationInfoFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
703         {
704             if (filter is ApplicationInfoMetadataFilter)
705             {
706                 ApplicationInfoMetadataFilter metaFilter = (ApplicationInfoMetadataFilter)filter;
707                 metaFilter.Fetch(callback);
708                 return;
709             }
710
711             IntPtr nativeHandle = MakeNativeAppInfoFilter(filter.Filter);
712             if (nativeHandle == IntPtr.Zero)
713             {
714                 throw ApplicationManagerErrorFactory.NativeFilterHandleIsInvalid();
715             }
716             try
717             {
718                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoFilterForeachAppinfo(nativeHandle, callback, IntPtr.Zero);
719                 if (err != Interop.ApplicationManager.ErrorCode.None)
720                 {
721                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to get application information list with filter.");
722                 }
723             }
724             finally
725             {
726                 Interop.ApplicationManager.AppInfoFilterDestroy(nativeHandle);
727             }
728         }
729
730         internal static void Fetch(this ApplicationInfoMetadataFilter filter, Interop.ApplicationManager.AppInfoFilterCallback callback)
731         {
732             IntPtr nativeHandle = MakeNativeAppMetadataFilter(filter.Filter);
733             if (nativeHandle == IntPtr.Zero)
734             {
735                 throw ApplicationManagerErrorFactory.NativeFilterHandleIsInvalid();
736             }
737             try
738             {
739                 Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoMetadataFilterForeach(nativeHandle, callback, IntPtr.Zero);
740                 if (err != Interop.ApplicationManager.ErrorCode.None)
741                 {
742                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to get metadata list with filter.");
743                 }
744             }
745             finally
746             {
747                 Interop.ApplicationManager.AppInfoMetadataFilterDestroy(nativeHandle);
748             }
749         }
750
751         private static IntPtr MakeNativeAppInfoFilter(IDictionary<string, string> filter)
752         {
753             if (filter == null || filter.Count == 0)
754             {
755                 throw ApplicationManagerErrorFactory.FilterIsInvalid();
756             }
757
758             IntPtr infoHandle = IntPtr.Zero;
759             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoFilterCreate(out infoHandle);
760             if (err != Interop.ApplicationManager.ErrorCode.None)
761             {
762                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the filter handle.");
763             }
764
765             foreach (var item in filter)
766             {
767                 if ((item.Key == ApplicationInfoFilter.Keys.Id) ||
768                     (item.Key == ApplicationInfoFilter.Keys.Type) ||
769                     (item.Key == ApplicationInfoFilter.Keys.Category) ||
770                     (item.Key == ApplicationInfoFilter.Keys.InstalledStorage))
771                 {
772                     err = Interop.ApplicationManager.AppInfoFilterAddString(infoHandle, item.Key, item.Value);
773                 }
774                 else if ((item.Key == ApplicationInfoFilter.Keys.NoDisplay) ||
775                          (item.Key == ApplicationInfoFilter.Keys.TaskManage))
776                 {
777                     err = Interop.ApplicationManager.AppInfoFilterAddBool(infoHandle, item.Key, Convert.ToBoolean(item.Value));
778                 }
779                 else
780                 {
781                     Log.Warn(LogTag, string.Format("'{0}' is not supported key for the filter.", item.Key));
782                 }
783                 if (err != Interop.ApplicationManager.ErrorCode.None)
784                 {
785                     Interop.ApplicationManager.AppInfoFilterDestroy(infoHandle);
786                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to add item to the filter.");
787                 }
788             }
789             return infoHandle;
790         }
791
792         private static IntPtr MakeNativeAppMetadataFilter(IDictionary<string, string> filter)
793         {
794             if (filter == null || filter.Count == 0)
795             {
796                 throw ApplicationManagerErrorFactory.FilterIsInvalid();
797             }
798
799             IntPtr infoHandle = IntPtr.Zero;
800             Interop.ApplicationManager.ErrorCode err = Interop.ApplicationManager.AppInfoMetadataFilterCreate(out infoHandle);
801             if (err != Interop.ApplicationManager.ErrorCode.None)
802             {
803                 throw ApplicationManagerErrorFactory.GetException(err, "Failed to create the filter for searching with metadata.");
804             }
805             foreach (var item in filter)
806             {
807                 err = Interop.ApplicationManager.AppInfoMetadataFilterAdd(infoHandle, item.Key, item.Value);
808                 if (err != Interop.ApplicationManager.ErrorCode.None)
809                 {
810                     Interop.ApplicationManager.AppInfoMetadataFilterDestroy(infoHandle);
811                     throw ApplicationManagerErrorFactory.GetException(err, "Failed to add the item to the filter.");
812                 }
813             }
814             return infoHandle;
815         }
816     }
817
818     internal static class ApplicationManagerErrorFactory
819     {
820         internal static Exception NativeFilterHandleIsInvalid()
821         {
822             return new InvalidOperationException("The native handle for filtering is invalid.");
823         }
824
825         internal static Exception FilterIsInvalid()
826         {
827             return new ArgumentException("The filter is invalid.");
828         }
829
830         internal static Exception GetException(Interop.ApplicationManager.ErrorCode err, string message)
831         {
832             string errMessage = String.Format("{0} err = {1}", message, err);
833             switch (err)
834             {
835                 case Interop.ApplicationManager.ErrorCode.InvalidParameter:
836                     return new ArgumentException(errMessage);
837                 default:
838                     return new InvalidOperationException(errMessage);
839             }
840         }
841     }
842 }