Merge remote-tracking branch 'origin/master' into tizen
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.PackageManager / Tizen.Applications / PackageManager.cs
1 /*
2  * Copyright (c) 2018 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.Threading.Tasks;
20 using System.IO;
21 using System.Linq;
22 using System.ComponentModel;
23
24 namespace Tizen.Applications
25 {
26     /// <summary>
27     /// PackageManager class. This class has the methods and events of the PackageManager.
28     /// </summary>
29     /// <remarks>
30     /// The package manager is one of the core modules of the Tizen application framework and responsible for getting their information.
31     /// You can also retrieve information related to the packages that are installed on the device.
32     /// </remarks>
33     /// <since_tizen> 3 </since_tizen>
34     public static class PackageManager
35     {
36         private const string LogTag = "Tizen.Applications.PackageManager";
37
38         private static SafePackageManagerHandle s_handle = new SafePackageManagerHandle();
39         private static Interop.PackageManager.EventStatus s_eventStatus = Interop.PackageManager.EventStatus.All;
40         private static Interop.PackageManager.EventStatus s_registered_eventStatus = Interop.PackageManager.EventStatus.All;
41         private static event EventHandler<PackageManagerEventArgs> s_installEventHandler;
42         private static event EventHandler<PackageManagerEventArgs> s_uninstallEventHandler;
43         private static event EventHandler<PackageManagerEventArgs> s_updateEventHandler;
44         private static event EventHandler<PackageManagerEventArgs> s_moveEventHandler;
45         private static event EventHandler<PackageManagerEventArgs> s_clearDataEventHandler;
46
47         private static readonly object s_pkgEventLock = new object();
48         private static Interop.PackageManager.PackageManagerEventCallback s_packageManagerEventCallback = new Interop.PackageManager.PackageManagerEventCallback(InternalEventCallback);
49
50         private static Dictionary<IntPtr, Interop.PackageManager.PackageManagerTotalSizeInfoCallback> s_totalSizeInfoCallbackDict = new Dictionary<IntPtr, Interop.PackageManager.PackageManagerTotalSizeInfoCallback>();
51         private static int s_callbackId = 0;
52
53         /// <summary>
54         /// Event callback method for the request.
55         /// </summary>
56         /// <param name="type">Type of the package which was requested.</param>
57         /// <param name="packageId">ID of the package which was requested.</param>
58         /// <param name="eventType">Event type of the request.</param>
59         /// <param name="eventState">Current event state of the request.</param>
60         /// <param name="progress">Progress for the request being processed by the package manager (in percent).</param>
61         /// <since_tizen> 3 </since_tizen>
62         public delegate void RequestEventCallback(string type, string packageId, PackageEventType eventType, PackageEventState eventState, int progress);
63
64         private static Dictionary<int, RequestEventCallback> RequestCallbacks = new Dictionary<int, RequestEventCallback>();
65         private static Dictionary<int, SafePackageManagerRequestHandle> RequestHandles = new Dictionary<int, SafePackageManagerRequestHandle>();
66         private static Dictionary<int, int> RequestPackageCount = new Dictionary<int, int>();
67
68         private delegate Interop.PackageManager.ErrorCode InstallMethodWithCallback(SafePackageManagerRequestHandle requestHandle, string pkgPath, Interop.PackageManager.PackageManagerRequestEventCallback requestCallback, IntPtr userData, out int requestID);
69         private delegate Interop.PackageManager.ErrorCode InstallPackagesMethodWithCallback(SafePackageManagerRequestHandle requestHandle, string[] pkgPaths, int pathsCount, Interop.PackageManager.PackageManagerRequestEventCallback requestCallback, IntPtr userData, out int requestId);
70         private delegate Interop.PackageManager.ErrorCode InstallMethod(SafePackageManagerRequestHandle requestHandle, string pkgPath, out int requestID);
71         private delegate Interop.PackageManager.ErrorCode InstallPackagesMethod(SafePackageManagerRequestHandle requestHandle, string[] pkgPaths, int pathsCount, out int requestID);
72
73         /// <summary>
74         /// InstallProgressChanged event. This event occurs when a package is getting installed and the progress of the request to the package manager is changed.
75         /// </summary>
76         /// <exception cref="IOException">Thrown when subscribing to package manager event failed.</exception>
77         /// <since_tizen> 3 </since_tizen>
78         public static event EventHandler<PackageManagerEventArgs> InstallProgressChanged
79         {
80             add
81             {
82                 lock (s_pkgEventLock)
83                 {
84                     SetPackageManagerEventStatus(Interop.PackageManager.EventStatus.Install);
85                     RegisterPackageManagerEventIfNeeded();
86                     s_installEventHandler += value;
87                 }
88             }
89             remove
90             {
91                 lock (s_pkgEventLock)
92                 {
93                     s_installEventHandler -= value;
94                     UnregisterPackageManagerEventIfNeeded();
95                     UnsetPackageManagerEventStatus();
96                 }
97             }
98         }
99
100         /// <summary>
101         /// UninstallProgressChanged event. This event occurs when a package is getting uninstalled and the progress of the request to the package manager is changed.
102         /// </summary>
103         /// <exception cref="IOException">Thrown when subscribing to package manager event failed.</exception>
104         /// <since_tizen> 3 </since_tizen>
105         public static event EventHandler<PackageManagerEventArgs> UninstallProgressChanged
106         {
107             add
108             {
109                 lock (s_pkgEventLock)
110                 {
111                     SetPackageManagerEventStatus(Interop.PackageManager.EventStatus.Uninstall);
112                     RegisterPackageManagerEventIfNeeded();
113                     s_uninstallEventHandler += value;
114                 }
115             }
116             remove
117             {
118                 lock (s_pkgEventLock)
119                 {
120                     s_uninstallEventHandler -= value;
121                     UnregisterPackageManagerEventIfNeeded();
122                     UnsetPackageManagerEventStatus();
123                 }
124            }
125         }
126
127         /// <summary>
128         /// UpdateProgressChanged event. This event occurs when a package is getting updated and the progress of the request to the package manager is changed.
129         /// </summary>
130         /// <exception cref="IOException">Thrown when subscribing to package manager event failed.</exception>
131         /// <since_tizen> 3 </since_tizen>
132         public static event EventHandler<PackageManagerEventArgs> UpdateProgressChanged
133         {
134             add
135             {
136                 lock (s_pkgEventLock)
137                 {
138                     SetPackageManagerEventStatus(Interop.PackageManager.EventStatus.Upgrade);
139                     RegisterPackageManagerEventIfNeeded();
140                     s_updateEventHandler += value;
141                 }
142             }
143             remove
144             {
145                 lock (s_pkgEventLock)
146                 {
147                     s_updateEventHandler -= value;
148                     UnregisterPackageManagerEventIfNeeded();
149                     UnsetPackageManagerEventStatus();
150                 }
151             }
152         }
153
154         /// <summary>
155         /// MoveProgressChanged event. This event occurs when a package is getting moved and the progress of the request to the package manager is changed.
156         /// </summary>
157         /// <exception cref="IOException">Thrown when subscribing to package manager event failed.</exception>
158         /// <since_tizen> 3 </since_tizen>
159         public static event EventHandler<PackageManagerEventArgs> MoveProgressChanged
160         {
161             add
162             {
163                 lock (s_pkgEventLock)
164                 {
165                     SetPackageManagerEventStatus(Interop.PackageManager.EventStatus.Move);
166                     RegisterPackageManagerEventIfNeeded();
167                     s_moveEventHandler += value;
168                 }
169             }
170             remove
171             {
172                 lock (s_pkgEventLock)
173                 {
174                     s_moveEventHandler -= value;
175                     UnregisterPackageManagerEventIfNeeded();
176                     UnsetPackageManagerEventStatus();
177                 }
178             }
179         }
180
181         /// <summary>
182         /// ClearDataProgressChanged event. This event occurs when data directories are cleared in the given package.
183         /// </summary>
184         /// <exception cref="IOException">Thrown when subscribing to package manager event failed.</exception>
185         /// <since_tizen> 3 </since_tizen>
186         public static event EventHandler<PackageManagerEventArgs> ClearDataProgressChanged
187         {
188             add
189             {
190                 lock (s_pkgEventLock)
191                 {
192                     SetPackageManagerEventStatus(Interop.PackageManager.EventStatus.ClearData);
193                     RegisterPackageManagerEventIfNeeded();
194                     s_clearDataEventHandler += value;
195                 }
196             }
197             remove
198             {
199                 lock (s_pkgEventLock)
200                 {
201                     s_clearDataEventHandler -= value;
202                     UnregisterPackageManagerEventIfNeeded();
203                     UnsetPackageManagerEventStatus();
204                 }
205             }
206         }
207
208         private static SafePackageManagerHandle Handle
209         {
210             get
211             {
212                 if (s_handle.IsInvalid)
213                 {
214                     var err = Interop.PackageManager.PackageManagerCreate(out s_handle);
215                     if (err != Interop.PackageManager.ErrorCode.None)
216                     {
217                         Log.Warn(LogTag, string.Format("Failed to create package manager handle. err = {0}", err));
218                     }
219                 }
220                 return s_handle;
221             }
222         }
223
224         private static Interop.PackageManager.PackageManagerRequestEventCallback internalRequestEventCallback = (id, packageType, packageId, eventType, eventState, progress, error, userData) =>
225         {
226             if (RequestCallbacks.ContainsKey(id))
227             {
228                 try
229                 {
230                     RequestCallbacks[id](packageType, packageId, (PackageEventType)eventType, (PackageEventState)eventState, progress);
231                     if (eventState == Interop.PackageManager.PackageEventState.Completed || eventState == Interop.PackageManager.PackageEventState.Failed)
232                     {
233                         RequestPackageCount[id] -= 1;
234                         if (RequestPackageCount[id] < 1)
235                         {
236                             Log.Debug(LogTag, string.Format("release request handle for id : {0}", id));
237                             RequestHandles[id].Dispose();
238                             RequestHandles.Remove(id);
239                             RequestCallbacks.Remove(id);
240                             RequestPackageCount.Remove(id);
241                         }
242                     }
243                 }
244                 catch (Exception e)
245                 {
246                     Log.Warn(LogTag, e.Message);
247                     RequestHandles[id].Dispose();
248                     RequestHandles.Remove(id);
249                     RequestCallbacks.Remove(id);
250                     RequestPackageCount.Remove(id);
251                 }
252             }
253         };
254
255         /// <summary>
256         /// Gets the package ID for the given application ID.
257         /// </summary>
258         /// <param name="applicationId">The ID of the application.</param>
259         /// <returns>Returns the ID of the package.</returns>
260         /// <remarks>It returns null if the input is null.</remarks>
261         /// <exception cref="ArgumentException">Thrown when input application ID does not exist.</exception>
262         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
263         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
264         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
265         /// <since_tizen> 3 </since_tizen>
266         public static string GetPackageIdByApplicationId(string applicationId)
267         {
268             string packageId;
269             var err = Interop.PackageManager.PackageManagerGetPackageIdByAppId(applicationId, out packageId);
270             if (err != Interop.PackageManager.ErrorCode.None)
271             {
272                 Log.Warn(LogTag, string.Format("Failed to get package Id of {0}. err = {1}", applicationId, err));
273                 if (err != Interop.PackageManager.ErrorCode.InvalidParameter)
274                 {
275                     throw PackageManagerErrorFactory.GetException(err, "Failed to get package Id");
276                 }
277             }
278             return packageId;
279         }
280
281         /// <summary>
282         /// Gets the package information for the given package.
283         /// </summary>
284         /// <param name="packageId">The ID of the package.</param>
285         /// <returns>Returns the package information for the given package ID.</returns>
286         /// <exception cref="ArgumentException">Thrown when the failed input package ID is invalid.</exception>
287         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
288         /// <exception cref="System.IO.IOException">Thrown when the method fails due to an internal I/O error.</exception>
289         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
290         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
291         /// <since_tizen> 3 </since_tizen>
292         public static Package GetPackage(string packageId)
293         {
294             return Package.GetPackage(packageId);
295         }
296
297         /// <summary>
298         /// Clears the application's internal and external cache directories.
299         /// </summary>
300         /// <param name="packageId">ID of the package.</param>
301         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
302         /// <exception cref="System.IO.IOException">Thrown when the method fails due to an internal I/O error.</exception>
303         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
304         /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
305         /// <privilege>http://tizen.org/privilege/packagemanager.clearcache</privilege>
306         /// <since_tizen> 3 </since_tizen>
307         public static void ClearCacheDirectory(string packageId)
308         {
309             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerClearCacheDir(packageId);
310             if (err != Interop.PackageManager.ErrorCode.None)
311             {
312                 Log.Warn(LogTag, string.Format("Failed to clear cache directory for {0}. err = {1}", packageId, err));
313                 throw PackageManagerErrorFactory.GetException(err, "Failed to clear cache directory");
314             }
315         }
316
317         /// <summary>
318         /// Clears all the application's internal and external cache directories.
319         /// </summary>
320         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
321         /// <exception cref="System.IO.IOException">Thrown when the method fails due to an internal IO error.</exception>
322         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
323         /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
324         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
325         /// <privlevel>platform</privlevel>
326         /// <since_tizen> 3 </since_tizen>
327         public static void ClearAllCacheDirectory()
328         {
329             var err = Interop.PackageManager.PackageManagerClearAllCacheDir();
330             if (err != Interop.PackageManager.ErrorCode.None)
331             {
332                 Log.Warn(LogTag, string.Format("Failed to clear all cache directories. err = {0}", err));
333                 throw PackageManagerErrorFactory.GetException(err, "Failed to clear all cache directories");
334             }
335         }
336
337         /// <summary>
338         /// Clears the application's internal and external data directories.
339         /// </summary>
340         /// <remarks>
341         /// All files under data, shared/data, and shared/trusted in the internal storage are removed.
342         /// And, if the external storage exists, then all files under data and shared/trusted in the external storage are removed.
343         /// </remarks>
344         /// <param name="packageId">ID of the package.</param>
345         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
346         /// <exception cref="System.IO.IOException">Thrown when the method failed due to an internal IO error.</exception>
347         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
348         /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
349         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
350         /// <privlevel>platform</privlevel>
351         /// <since_tizen> 3 </since_tizen>
352         public static void ClearDataDirectory(string packageId)
353         {
354             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerClearDataDir(packageId);
355             if (err != Interop.PackageManager.ErrorCode.None)
356             {
357                 Log.Warn(LogTag, string.Format("Failed to clear data directory for {0}. err = {1}", packageId, err));
358                 throw PackageManagerErrorFactory.GetException(err, "Failed to clear data directory");
359             }
360         }
361
362         /// <summary>
363         /// Removes a file or directory specified with <paramref name="path"/> from user data internal storage for the application.
364         /// </summary>
365         /// <param name="packageId">ID of the package.</param>
366         /// <param name="path">The path of the file or directory in the package user data folder.</param>
367         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
368         /// <exception cref="System.IO.IOException">Thrown when the method failed due to an internal IO error.</exception>
369         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
370         /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
371         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
372         /// <privlevel>platform</privlevel>
373         /// <since_tizen> 11 </since_tizen>
374         public static void ClearUserData(string packageId, string path)
375         {
376             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerClearUserDataWithPath(packageId, path);
377             if (err != Interop.PackageManager.ErrorCode.None)
378             {
379                 Log.Warn(LogTag, string.Format("Failed to clear user data for {0} of {1}. err = {2}", path, packageId, err));
380                 throw PackageManagerErrorFactory.GetException(err, "Failed to clear user data");
381             }
382         }
383
384         /// <summary>
385         /// Retrieves the package information of all installed packages.
386         /// </summary>
387         /// <returns>Returns the list of packages.</returns>
388         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
389         /// <since_tizen> 3 </since_tizen>
390         public static IEnumerable<Package> GetPackages()
391         {
392             return GetPackages(null);
393         }
394
395         /// <summary>
396         /// Retrieves the package information of all the installed packages satisfying the filter conditions.
397         /// </summary>
398         /// <param name="filter">Optional - package filters.</param>
399         /// <returns>Returns the list of packages.</returns>
400         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
401         /// <since_tizen> 3 </since_tizen>
402         public static IEnumerable<Package> GetPackages(PackageFilter filter)
403         {
404             List<Package> packageList = new List<Package>();
405
406             IntPtr filterHandle;
407             var err = Interop.PackageManager.PackageManagerFilterCreate(out filterHandle);
408             if (err != Interop.PackageManager.ErrorCode.None)
409             {
410                 Log.Warn(LogTag, string.Format("Failed to create package filter handle. err = {0}", err));
411                 return packageList;
412             }
413
414             if (filter != null && filter.Filters != null)
415             {
416                 foreach (KeyValuePair<string, bool> entry in filter?.Filters)
417                 {
418                     err = Interop.PackageManager.PackageManagerFilterAdd(filterHandle, entry.Key, entry.Value);
419                     if (err != Interop.PackageManager.ErrorCode.None)
420                     {
421                         Log.Warn(LogTag, string.Format("Failed to configure package filter. err = {0}", err));
422                         break;
423                     }
424                 }
425
426             }
427
428             if (filter != null && filter.StringFilters != null)
429             {
430                 foreach (KeyValuePair<string, string> entry in filter?.StringFilters)
431                 {
432                     err = Interop.PackageManager.PackageManagerFilterAdd(filterHandle, entry.Key, entry.Value);
433                     if (err != Interop.PackageManager.ErrorCode.None)
434                     {
435                         Log.Warn(LogTag, string.Format("Failed to configure package filter. err = {0}", err));
436                         break;
437                     }
438                 }
439             }
440
441             if (err == Interop.PackageManager.ErrorCode.None)
442             {
443                 Interop.PackageManager.PackageManagerPackageInfoCallback cb = (handle, userData) =>
444                 {
445                     packageList.Add(Package.GetPackage(handle));
446                     return true;
447                 };
448
449                 err = Interop.PackageManager.PackageManagerFilterForeachPackageInfo(filterHandle, cb, IntPtr.Zero);
450                 if (err != Interop.PackageManager.ErrorCode.None)
451                 {
452                     Log.Warn(LogTag, string.Format("Failed to get package Informations. err = {0}", err));
453                 }
454             }
455
456             err = Interop.PackageManager.PackageManagerFilterDestroy(filterHandle);
457             if (err != Interop.PackageManager.ErrorCode.None)
458             {
459                 Log.Warn(LogTag, string.Format("Failed to destroy package filter handle. err = {0}", err));
460             }
461             return packageList;
462         }
463
464         /// <summary>
465         /// Gets the total package size information.
466         /// </summary>
467         /// <returns>Returns the total package size information asynchronously.</returns>
468         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
469         /// <since_tizen> 3 </since_tizen>
470         public static async Task<PackageSizeInformation> GetTotalSizeInformationAsync()
471         {
472             TaskCompletionSource<PackageSizeInformation> tcs = new TaskCompletionSource<PackageSizeInformation>();
473
474             Interop.PackageManager.PackageManagerTotalSizeInfoCallback cb = (handle, userData) =>
475             {
476                 if (handle != IntPtr.Zero)
477                 {
478                     tcs.TrySetResult(PackageSizeInformation.GetPackageSizeInformation(handle));
479                 }
480
481                 lock (s_totalSizeInfoCallbackDict)
482                 {
483                     s_totalSizeInfoCallbackDict.Remove(userData);
484                 }
485             };
486
487             IntPtr callbackId;
488             lock (s_totalSizeInfoCallbackDict)
489             {
490                 callbackId = (IntPtr)s_callbackId++;
491                 s_totalSizeInfoCallbackDict[callbackId] = cb;
492             }
493
494             var err = Interop.PackageManager.PackageManagerGetTotalSizeInfo(cb, callbackId);
495             if (err != Interop.PackageManager.ErrorCode.None)
496             {
497                 tcs.TrySetException(PackageManagerErrorFactory.GetException(err, "Failed to get total package size info"));
498             }
499             return await tcs.Task.ConfigureAwait(false);
500         }
501
502         /// <summary>
503         /// Installs the package located at the given path.
504         /// </summary>
505         /// <param name="packagePath">Absolute path for the package to be installed.</param>
506         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
507         /// <returns>Returns true if the installation request is successful, otherwise false.</returns>
508         /// <remarks>
509         /// The 'true' means that the request for installation is successful.
510         /// To check the result of the installation, the caller should check the progress using the InstallProgressChanged event.
511         /// </remarks>
512         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
513         /// <privlevel>platform</privlevel>
514         /// <since_tizen> 3 </since_tizen>
515         public static bool Install(string packagePath, InstallationMode installMode = InstallationMode.Normal)
516         {
517             return Install(packagePath, null, PackageType.UNKNOWN, null, installMode);
518         }
519
520         /// <summary>
521         /// Installs the package located at the given path.
522         /// </summary>
523         /// <param name="packagePath">Absolute path for the package to be installed.</param>
524         /// <param name="eventCallback">The event callback will be invoked only for the current request.</param>
525         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
526         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
527         /// <remarks>
528         /// The 'true' means that the request for installation is successful.
529         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event or eventCallback.
530         /// </remarks>
531         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
532         /// <privlevel>platform</privlevel>
533         /// <since_tizen> 3 </since_tizen>
534         public static bool Install(string packagePath, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
535         {
536             return Install(packagePath, null, PackageType.UNKNOWN, eventCallback, installMode);
537         }
538
539         /// <summary>
540         /// Installs the package located at the given path.
541         /// </summary>
542         /// <param name="packagePath">Absolute path for the package to be installed.</param>
543         /// <param name="type">Package type for the package to be installed.</param>
544         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
545         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
546         /// <remarks>
547         /// The 'true' means that the request for installation is successful.
548         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event.
549         /// </remarks>
550         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
551         /// <privlevel>platform</privlevel>
552         /// <since_tizen> 3 </since_tizen>
553         public static bool Install(string packagePath, PackageType type, InstallationMode installMode = InstallationMode.Normal)
554         {
555             return Install(packagePath, null, type, null, installMode);
556         }
557
558         /// <summary>
559         /// Installs the package located at the given path.
560         /// </summary>
561         /// <param name="packagePath">Absolute path for the package to be installed.</param>
562         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed.</param>
563         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
564         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
565         /// <remarks>
566         /// The 'true' means that the request for installation is successful.
567         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event.
568         /// </remarks>
569         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
570         /// <privlevel>platform</privlevel>
571         /// <since_tizen> 3 </since_tizen>
572         public static bool Install(string packagePath, string expansionPackagePath, InstallationMode installMode = InstallationMode.Normal)
573         {
574             return Install(packagePath, expansionPackagePath, PackageType.UNKNOWN, null, installMode);
575         }
576
577         /// <summary>
578         /// Installs the package located at the given path.
579         /// </summary>
580         /// <param name="packagePath">Absolute path for the package to be installed.</param>
581         /// <param name="type">Package type for the package to be installed.</param>
582         /// <param name="eventCallback">The event callback will be invoked only for the current request.</param>
583         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
584         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
585         /// <remarks>
586         /// The 'true' means that the request for installation is successful.
587         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event or eventCallback.
588         /// </remarks>
589         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
590         /// <privlevel>platform</privlevel>
591         /// <since_tizen> 3 </since_tizen>
592         public static bool Install(string packagePath, PackageType type, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
593         {
594             return Install(packagePath, null, type, eventCallback, installMode);
595         }
596
597         /// <summary>
598         /// Installs the package located at the given path.
599         /// </summary>
600         /// <param name="packagePath">Absolute path for the package to be installed.</param>
601         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed.</param>
602         /// <param name="eventCallback">The event callback will be invoked only for the current request.</param>
603         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
604         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
605         /// <remarks>
606         /// The 'true' means that the request for installation is successful.
607         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event or eventCallback.
608         /// </remarks>
609         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
610         /// <privlevel>platform</privlevel>
611         /// <since_tizen> 3 </since_tizen>
612         public static bool Install(string packagePath, string expansionPackagePath, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
613         {
614             return Install(packagePath, expansionPackagePath, PackageType.UNKNOWN, eventCallback, installMode);
615         }
616
617         /// <summary>
618         /// Installs the package located at the given path.
619         /// </summary>
620         /// <param name="packagePath">Absolute path for the package to be installed.</param>
621         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed.</param>
622         /// <param name="type">Package type for the package to be installed.</param>
623         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
624         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
625         /// <remarks>
626         /// The 'true' means that the request for installation is successful.
627         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event.
628         /// </remarks>
629         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
630         /// <privlevel>platform</privlevel>
631         /// <since_tizen> 3 </since_tizen>
632         public static bool Install(string packagePath, string expansionPackagePath, PackageType type, InstallationMode installMode = InstallationMode.Normal)
633         {
634             return Install(packagePath, expansionPackagePath, type, null, installMode);
635         }
636
637         /// <summary>
638         /// Installs the package located at the given path.
639         /// </summary>
640         /// <param name="packagePath">Absolute path for the package to be installed.</param>
641         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed.</param>
642         /// <param name="type">Package type for the package to be installed.</param>
643         /// <param name="eventCallback">The event callback will be invoked only for the current request.</param>
644         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
645         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
646         /// <remarks>
647         /// The 'true' means that the request for installation is successful.
648         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event or eventCallback.
649         /// </remarks>
650         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
651         /// <privlevel>platform</privlevel>
652         /// <since_tizen> 3 </since_tizen>
653         public static bool Install(string packagePath, string expansionPackagePath, PackageType type, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
654         {
655             return InstallInternal(new List<string>{ packagePath }, expansionPackagePath, type, eventCallback, installMode);
656         }
657
658         /// <summary>
659         /// Installs the packages located at the given path.
660         /// </summary>
661         /// <param name="packagePaths">Absolute paths for the package to be installed.</param>
662         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
663         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
664         /// <remarks>
665         /// The 'true' means that the request for installation is successful.
666         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event or eventCallback.
667         /// </remarks>
668         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
669         /// <privlevel>platform</privlevel>
670         /// <since_tizen> 8 </since_tizen>
671         public static bool Install(List<string> packagePaths, InstallationMode installMode = InstallationMode.Normal)
672         {
673             return InstallInternal(packagePaths, null, PackageType.UNKNOWN, null, installMode);
674         }
675
676         /// <summary>
677         /// Installs the packages located at the given path.
678         /// </summary>
679         /// <param name="packagePaths">Absolute paths for the package to be installed.</param>
680         /// <param name="eventCallback">The event callback will be invoked only for the current request.</param>
681         /// <param name="installMode">Optional parameter to indicate special installation mode.</param>
682         /// <returns>Returns true if installation request is successful, false otherwise.</returns>
683         /// <remarks>
684         /// The 'true' means that the request for installation is successful.
685         /// To check the result of installation, the caller should check the progress using the InstallProgressChanged event or eventCallback.
686         /// </remarks>
687         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
688         /// <privlevel>platform</privlevel>
689         /// <since_tizen> 8 </since_tizen>
690         public static bool Install(List<string> packagePaths, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
691         {
692             return InstallInternal(packagePaths, null, PackageType.UNKNOWN, eventCallback, installMode);
693         }
694
695         private static bool InstallInternal(List<string> packagePaths, string expansionPackagePath, PackageType type, RequestEventCallback eventCallback, InstallationMode installMode)
696         {
697             if (packagePaths == null || !packagePaths.Any())
698             {
699                 Log.Warn(LogTag, string.Format("Invalid argument"));
700                 return false;
701             }
702
703             SafePackageManagerRequestHandle RequestHandle;
704             var err = Interop.PackageManager.PackageManagerRequestCreate(out RequestHandle);
705             if (err != Interop.PackageManager.ErrorCode.None)
706             {
707                 Log.Warn(LogTag, string.Format("Failed to install packages. Error in creating package manager request handle. err = {0}", err));
708                 return false;
709             }
710
711             try
712             {
713                 if (type != PackageType.UNKNOWN)
714                 {
715                     err = Interop.PackageManager.PackageManagerRequestSetType(RequestHandle, type.ToString().ToLowerInvariant());
716                     if (err != Interop.PackageManager.ErrorCode.None)
717                     {
718                         Log.Warn(LogTag, string.Format("Failed to install packages. Error in setting request package type. err = {0}", err));
719                         RequestHandle.Dispose();
720                         return false;
721                     }
722                 }
723
724                 if (!string.IsNullOrEmpty(expansionPackagePath))
725                 {
726                     err = Interop.PackageManager.PackageManagerRequestSetTepPath(RequestHandle, expansionPackagePath);
727                     if (err != Interop.PackageManager.ErrorCode.None)
728                     {
729                         Log.Warn(LogTag, string.Format("Failed to install package. Error in setting request package mode. err = {0}", err));
730                         RequestHandle.Dispose();
731                         return false;
732                     }
733                 }
734
735                 int requestId;
736                 if (eventCallback != null)
737                 {
738                     if (packagePaths.Count > 1)
739                     {
740                         InstallPackagesMethodWithCallback installPackages;
741                         if (installMode == InstallationMode.Mount)
742                         {
743                             installPackages = Interop.PackageManager.PackageManagerRequestMountInstallPackagesWithCb;
744                         }
745                         else
746                         {
747                             installPackages = Interop.PackageManager.PackageManagerRequestInstallPackagesWithCb;
748                         }
749                         err = installPackages(RequestHandle, packagePaths.ToArray(), packagePaths.Count, internalRequestEventCallback, IntPtr.Zero, out requestId);
750                         if (err == Interop.PackageManager.ErrorCode.None)
751                         {
752                             RequestCallbacks.Add(requestId, eventCallback);
753                             RequestHandles.Add(requestId, RequestHandle);
754                             RequestPackageCount.Add(requestId, packagePaths.Count);
755                         }
756                         else
757                         {
758                             Log.Warn(LogTag, string.Format("Failed to install packages. err = {0}",  err));
759                             RequestHandle.Dispose();
760                             return false;
761                         }
762                     }
763                     else
764                     {
765                         InstallMethodWithCallback install;
766                         if (installMode == InstallationMode.Mount)
767                         {
768                             install = Interop.PackageManager.PackageManagerRequestMountInstallWithCB;
769                         }
770                         else
771                         {
772                             install = Interop.PackageManager.PackageManagerRequestInstallWithCB;
773                         }
774                         err = install(RequestHandle, packagePaths[0], internalRequestEventCallback, IntPtr.Zero, out requestId);
775                         if (err == Interop.PackageManager.ErrorCode.None)
776                         {
777                             RequestCallbacks.Add(requestId, eventCallback);
778                             RequestHandles.Add(requestId, RequestHandle);
779                             RequestPackageCount.Add(requestId, packagePaths.Count);
780
781                         }
782                         else
783                         {
784                             Log.Warn(LogTag, string.Format("Failed to install package {0}. err = {1}", packagePaths, err));
785                             RequestHandle.Dispose();
786                             return false;
787                         }
788
789                     }
790
791                 }
792                 else
793                 {
794                     if (packagePaths.Count > 1)
795                     {
796                         InstallPackagesMethod installPackages;
797                         if (installMode == InstallationMode.Mount)
798                         {
799                             installPackages = Interop.PackageManager.PackageManagerRequestMountInstallPackages;
800                         }
801                         else
802                         {
803                             installPackages = Interop.PackageManager.PackageManagerRequestInstallPackages;
804                         }
805                         err = installPackages(RequestHandle, packagePaths.ToArray(), packagePaths.Count, out requestId);
806                         if (err != Interop.PackageManager.ErrorCode.None)
807                         {
808                             Log.Warn(LogTag, string.Format("Failed to install package {0}. err = {1}", packagePaths, err));
809                             RequestHandle.Dispose();
810                             return false;
811                         }
812                     }
813                     else
814                     {
815                         InstallMethod install;
816                         if (installMode == InstallationMode.Mount)
817                         {
818                             install = Interop.PackageManager.PackageManagerRequestMountInstall;
819                         }
820                         else
821                         {
822                             install = Interop.PackageManager.PackageManagerRequestInstall;
823                         }
824                         err = install(RequestHandle, packagePaths[0], out requestId);
825                         if (err != Interop.PackageManager.ErrorCode.None)
826                         {
827                             Log.Warn(LogTag, string.Format("Failed to install package {0}. err = {1}", packagePaths, err));
828                             RequestHandle.Dispose();
829                             return false;
830                         }
831                     }
832
833                     // RequestHandle isn't necessary when this method is called without 'eventCallback' parameter.
834                     RequestHandle.Dispose();
835                 }
836                 return true;
837             }
838             catch (Exception e)
839             {
840                 Log.Warn(LogTag, e.Message);
841                 RequestHandle.Dispose();
842                 return false;
843             }
844         }
845
846         /// <summary>
847         /// Uninstalls the package with the given name.
848         /// </summary>
849         /// <param name="packageId">ID of the package to be uninstalled.</param>
850         /// <returns>Returns true if the uninstallation request is successful, false otherwise.</returns>
851         /// <remarks>
852         /// The 'true' means that the request for uninstallation is successful.
853         /// To check the result of uninstallation, the caller should check the progress using the UninstallProgressChanged event.
854         /// </remarks>
855         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
856         /// <privlevel>platform</privlevel>
857         /// <since_tizen> 3 </since_tizen>
858         public static bool Uninstall(string packageId)
859         {
860             return Uninstall(packageId, PackageType.UNKNOWN, null);
861         }
862
863         /// <summary>
864         /// Uninstalls package with the given names.
865         /// </summary>
866         /// <param name="packageId">ID of the package to be uninstalled.</param>
867         /// <param name="type">Optional - Package type for the package to be uninstalled.</param>
868         /// <returns>Returns true if the uninstallation request is successful, false otherwise.</returns>
869         /// <remarks>
870         /// The 'true' means that the request for uninstallation is successful.
871         /// To check the result of uninstallation, the caller should check the progress using the UninstallProgressChanged event.
872         /// </remarks>
873         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
874         /// <privlevel>platform</privlevel>
875         /// <since_tizen> 3 </since_tizen>
876         public static bool Uninstall(string packageId, PackageType type)
877         {
878             return Uninstall(packageId, type, null);
879         }
880
881         /// <summary>
882         /// Uninstalls the package with the given name.
883         /// </summary>
884         /// <param name="packageId">ID of the package to be uninstalled.</param>
885         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request.</param>
886         /// <returns>Returns true if the uninstallation request is successful, false otherwise.</returns>
887         /// <remarks>
888         /// The 'true' means that the request for uninstallation is successful.
889         /// To check the result of uninstallation, the caller should check the progress using the UninstallProgressChanged event or eventCallback.
890         /// </remarks>
891         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
892         /// <privlevel>platform</privlevel>
893         /// <since_tizen> 3 </since_tizen>
894         public static bool Uninstall(string packageId, RequestEventCallback eventCallback)
895         {
896             return Uninstall(packageId, PackageType.UNKNOWN, eventCallback);
897         }
898
899         /// <summary>
900         /// Uninstalls the package with the given name.
901         /// </summary>
902         /// <param name="packageId">ID of the package to be uninstalled</param>
903         /// <param name="type">Optional - Package type for the package to be uninstalled.</param>
904         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request.</param>
905         /// <returns>Returns true if the uninstallation request is successful, false otherwise.</returns>
906         /// <remarks>
907         /// The 'true' means that the request for uninstallation is successful.
908         /// To check the result of uninstallation, the caller should check the progress using the UninstallProgressChanged event or eventCallback.
909         /// </remarks>
910         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
911         /// <privlevel>platform</privlevel>
912         /// <since_tizen> 3 </since_tizen>
913         public static bool Uninstall(string packageId, PackageType type, RequestEventCallback eventCallback)
914         {
915             SafePackageManagerRequestHandle RequestHandle;
916             var err = Interop.PackageManager.PackageManagerRequestCreate(out RequestHandle);
917             if (err != Interop.PackageManager.ErrorCode.None)
918             {
919                 Log.Warn(LogTag, string.Format("Failed to uninstall package {0}. Error in creating package manager request handle. err = {1}", packageId, err));
920                 return false;
921             }
922
923             try
924             {
925                 err = Interop.PackageManager.PackageManagerRequestSetType(RequestHandle, type.ToString().ToLowerInvariant());
926                 if (err != Interop.PackageManager.ErrorCode.None)
927                 {
928                     Log.Warn(LogTag, string.Format("Failed to uninstall package {0}. Error in setting request package type. err = {1}", packageId, err));
929                     RequestHandle.Dispose();
930                     return false;
931                 }
932
933                 int requestId;
934                 if (eventCallback != null)
935                 {
936                     err = Interop.PackageManager.PackageManagerRequestUninstallWithCB(RequestHandle, packageId, internalRequestEventCallback, IntPtr.Zero, out requestId);
937                     if (err == Interop.PackageManager.ErrorCode.None)
938                     {
939                         RequestCallbacks.Add(requestId, eventCallback);
940                         RequestHandles.Add(requestId, RequestHandle);
941                         RequestPackageCount.Add(requestId, 1);
942                     }
943                     else
944                     {
945                         Log.Warn(LogTag, string.Format("Failed to uninstall package {0}. err = {1}", packageId, err));
946                         RequestHandle.Dispose();
947                         return false;
948                     }
949                 }
950                 else
951                 {
952                     err = Interop.PackageManager.PackageManagerRequestUninstall(RequestHandle, packageId, out requestId);
953                     if (err != Interop.PackageManager.ErrorCode.None)
954                     {
955                         Log.Warn(LogTag, string.Format("Failed to uninstall package. err = {0}", err));
956                         RequestHandle.Dispose();
957                         return false;
958                     }
959                     // RequestHandle isn't necessary when this method is called without 'eventCallback' parameter.
960                     RequestHandle.Dispose();
961                 }
962                 return true;
963             }
964             catch (Exception e)
965             {
966                 Log.Warn(LogTag, e.Message);
967                 RequestHandle.Dispose();
968                 return false;
969             }
970         }
971
972         /// <summary>
973         /// Moves the package to the given storage.
974         /// </summary>
975         /// <param name="packageId">ID of the package to be moved.</param>
976         /// <param name="newStorage">Storage package should be moved to.</param>
977         /// <returns>Returns true if the move request is successful, false otherwise.</returns>
978         /// <remarks>
979         /// The 'true' means that the request for move is successful.
980         /// To check the result of move, the caller should check the progress using the MoveProgressChanged event.
981         /// </remarks>
982         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
983         /// <privlevel>platform</privlevel>
984         /// <since_tizen> 3 </since_tizen>
985         public static bool Move(string packageId, StorageType newStorage)
986         {
987             return Move(packageId, PackageType.UNKNOWN, newStorage, null);
988         }
989
990         /// <summary>
991         /// Moves the package to the given storage.
992         /// </summary>
993         /// <param name="packageId">ID of the package to be moved.</param>
994         /// <param name="type">Optional - Package type for the package to be moved.</param>
995         /// <param name="newStorage">Storage package should be moved to.</param>
996         /// <returns>Returns true if the move request is successful, false otherwise.</returns>
997         /// <remarks>
998         /// The 'true' means that the request for move is successful.
999         /// To check the result of move, the caller should check the progress using the MoveProgressChanged event.
1000         /// </remarks>
1001         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1002         /// <privlevel>platform</privlevel>
1003         /// <since_tizen> 3 </since_tizen>
1004         public static bool Move(string packageId, PackageType type, StorageType newStorage)
1005         {
1006             return Move(packageId, type, newStorage, null);
1007         }
1008
1009         /// <summary>
1010         /// Moves the package to the given storage.
1011         /// </summary>
1012         /// <param name="packageId">ID of the package to be moved.</param>
1013         /// <param name="newStorage">Storage package should be moved to.</param>
1014         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request.</param>
1015         /// <returns>Returns true if move request is successful, false otherwise.</returns>
1016         /// <remarks>
1017         /// The 'true' means that the request for move is successful.
1018         /// To check the result of move, the caller should check the progress using the MoveProgressChanged event.
1019         /// </remarks>
1020         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1021         /// <privlevel>platform</privlevel>
1022         /// <since_tizen> 3 </since_tizen>
1023         public static bool Move(string packageId, StorageType newStorage, RequestEventCallback eventCallback)
1024         {
1025             return Move(packageId, PackageType.UNKNOWN, newStorage, eventCallback);
1026         }
1027
1028         /// <summary>
1029         /// Moves the package to the given storage.
1030         /// </summary>
1031         /// <param name="packageId">ID of the package to be moved.</param>
1032         /// <param name="type">Optional - Package type for the package to be moved.</param>
1033         /// <param name="newStorage">Storage, package should be moved to.</param>
1034         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request.</param>
1035         /// <returns>Returns true if move request is successful, false otherwise.</returns>
1036         /// <remarks>
1037         /// The 'true' means that the request for move is successful.
1038         /// To check the result of move, the caller should check the progress using the MoveProgressChanged event.
1039         /// </remarks>
1040         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1041         /// <privlevel>platform</privlevel>
1042         /// <since_tizen> 3 </since_tizen>
1043         public static bool Move(string packageId, PackageType type, StorageType newStorage, RequestEventCallback eventCallback)
1044         {
1045             SafePackageManagerRequestHandle RequestHandle;
1046             var err = Interop.PackageManager.PackageManagerRequestCreate(out RequestHandle);
1047             if (err != Interop.PackageManager.ErrorCode.None)
1048             {
1049                 Log.Warn(LogTag, string.Format("Failed to create package manager request handle. err = {0}", err));
1050                 return false;
1051             }
1052
1053             try
1054             {
1055                 bool result = true;
1056                 err = Interop.PackageManager.PackageManagerRequestSetType(RequestHandle, type.ToString().ToLowerInvariant());
1057                 if (err != Interop.PackageManager.ErrorCode.None)
1058                 {
1059                     Log.Warn(LogTag, string.Format("Failed to move package. Error in setting request package type. err = {0}", err));
1060                     RequestHandle.Dispose();
1061                     return false;
1062                 }
1063
1064                 if (eventCallback != null)
1065                 {
1066                     int requestId;
1067                     err = Interop.PackageManager.PackageManagerRequestMoveWithCB(RequestHandle, packageId, (Interop.PackageManager.StorageType)newStorage, internalRequestEventCallback, IntPtr.Zero, out requestId);
1068                     if (err == Interop.PackageManager.ErrorCode.None)
1069                     {
1070                         RequestCallbacks.Add(requestId, eventCallback);
1071                         RequestHandles.Add(requestId, RequestHandle);
1072                         RequestPackageCount.Add(requestId, 1);
1073                     }
1074                     else
1075                     {
1076                         Log.Warn(LogTag, string.Format("Failed to move package to requested location. err = {0}", err));
1077                         RequestHandle.Dispose();
1078                         result = false;
1079                     }
1080                 }
1081                 else
1082                 {
1083                     err = Interop.PackageManager.PackageManagerRequestMove(RequestHandle, packageId, (Interop.PackageManager.StorageType)newStorage);
1084                     if (err != Interop.PackageManager.ErrorCode.None)
1085                     {
1086                         Log.Warn(LogTag, string.Format("Failed to move package to requested location. err = {0}", err));
1087                         RequestHandle.Dispose();
1088                         result = false;
1089                     }
1090                     // RequestHandle isn't necessary when this method is called without 'eventCallback' parameter.
1091                     RequestHandle.Dispose();
1092                 }
1093                 return result;
1094             }
1095             catch (Exception e)
1096             {
1097                 Log.Warn(LogTag, e.Message);
1098                 RequestHandle.Dispose();
1099                 return false;
1100             }
1101         }
1102
1103         /// <summary>
1104         /// Gets the permission type of the package which has a given application ID.
1105         /// </summary>
1106         /// <param name="applicationId">ID of the application.</param>
1107         /// <returns>Returns the permission type.</returns>
1108         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
1109         /// <exception cref="ArgumentException">Thrown when the failed input package ID is invalid.</exception>
1110         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1111         /// <since_tizen> 3 </since_tizen>
1112         public static PermissionType GetPermissionTypeByApplicationId(string applicationId)
1113         {
1114             Interop.PackageManager.PackageManagerPermissionType permissionType;
1115             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerGetPermissionType(applicationId, out permissionType);
1116             if (err != Interop.PackageManager.ErrorCode.None)
1117             {
1118                 throw PackageManagerErrorFactory.GetException(err, "Failed to get permission type.");
1119             }
1120
1121             return (PermissionType)permissionType;
1122         }
1123
1124         /// <summary>
1125         /// Gets the package's preload attribute which contains a given application ID.
1126         /// </summary>
1127         /// <param name="applicationId">ID of the application.</param>
1128         /// <returns>Returns true if the package is preloaded, otherwise false.</returns>
1129         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
1130         /// <exception cref="ArgumentException">Thrown when the failed input package ID is invalid.</exception>
1131         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1132         /// <since_tizen> 3 </since_tizen>
1133         public static bool IsPreloadPackageByApplicationId(string applicationId)
1134         {
1135             bool isPreloadPackage;
1136             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerIsPreloadPackageByApplicationId(applicationId, out isPreloadPackage);
1137             if (err != Interop.PackageManager.ErrorCode.None)
1138             {
1139                 throw PackageManagerErrorFactory.GetException(err, "Failed to get preload info");
1140             }
1141
1142             return isPreloadPackage;
1143         }
1144
1145         /// <summary>
1146         /// Compares the certificate of the two packages.
1147         /// </summary>
1148         /// <param name="lhsPackageId">Package ID to compare.</param>
1149         /// <param name="rhsPackageId">Package ID to be compared.</param>
1150         /// <returns>Returns certificate comparison result.</returns>
1151         /// <exception cref="ArgumentException">Thrown when the failed input package ID is invalid.</exception>
1152         /// <exception cref="System.IO.IOException">Thrown when the method failed due to an internal I/O error.</exception>
1153         /// <since_tizen> 3 </since_tizen>
1154         public static CertCompareResultType CompareCertInfo(string lhsPackageId, string rhsPackageId)
1155         {
1156             Interop.PackageManager.CertCompareResultType compareResult;
1157             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerCompareCertInfo(lhsPackageId, rhsPackageId, out compareResult);
1158             if (err != Interop.PackageManager.ErrorCode.None)
1159             {
1160                 throw PackageManagerErrorFactory.GetException(err, "Failed to compare cert info");
1161             }
1162
1163             return (CertCompareResultType)compareResult;
1164         }
1165
1166         /// <summary>
1167         /// Compares the certificate of the two packages which contain each given application ID.
1168         /// </summary>
1169         /// <param name="lhsApplicationId">Application ID to compare.</param>
1170         /// <param name="rhsApplicationId">Application ID to be compared.</param>
1171         /// <returns>Returns certificate comparison result.</returns>
1172         /// <exception cref="ArgumentException">Thrown when the failed input package ID is invalid.</exception>
1173         /// <exception cref="System.IO.IOException">Thrown when the method failed due to an internal I/O error.</exception>
1174         /// <since_tizen> 3 </since_tizen>
1175         public static CertCompareResultType CompareCertInfoByApplicationId(string lhsApplicationId, string rhsApplicationId)
1176         {
1177             Interop.PackageManager.CertCompareResultType compareResult;
1178             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerCompareCertInfoByApplicationId(lhsApplicationId, rhsApplicationId, out compareResult);
1179             if (err != Interop.PackageManager.ErrorCode.None)
1180             {
1181                 throw PackageManagerErrorFactory.GetException(err, "Failed to compare cert info by application id");
1182             }
1183
1184             return (CertCompareResultType)compareResult;
1185         }
1186
1187         /// <summary>
1188         /// Gets the package archive's information for the given archive path.
1189         /// </summary>
1190         /// <param name="archivePath">The path of the package archive.</param>
1191         /// <remarks>
1192         /// Regular 3rd party apps do not need to use this API
1193         /// </remarks>
1194         /// <returns>Returns the package archive information for the given archive path.</returns>
1195         /// <exception cref="ArgumentException">Thrown when the failed input package ID is invalid.</exception>
1196         /// <exception cref="System.IO.IOException">Thrown when the method fails due to an internal I/O error.</exception>
1197         /// <since_tizen> 6 </since_tizen>
1198         public static PackageArchive GetPackageArchive(string archivePath)
1199         {
1200             return PackageArchive.GetPackageArchive(archivePath);
1201         }
1202
1203         /// <summary>
1204         /// Enable the given package.
1205         /// </summary>
1206         /// <param name="packageId">The ID of the package.</param>
1207         /// <remarks>
1208         /// This API is for inhouse app only.
1209         /// </remarks>
1210         /// <returns>Returns true if succeeds, otherwise false.</returns>
1211         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1212         /// <privlevel>platform</privlevel>
1213         /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid.</exception>
1214         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
1215         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1216         /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
1217         /// <since_tizen> 11 </since_tizen>
1218         [EditorBrowsable(EditorBrowsableState.Never)]
1219         public static void EnablePackage(string packageId)
1220         {
1221             // 0 is PC_REQUEST
1222             IntPtr clientHandle = Interop.PackageManagerInternal.PkgmgrClientNew(0);
1223             if (clientHandle == null)
1224             {
1225                 throw PackageManagerErrorFactory.GetException(Interop.PackageManager.ErrorCode.OutOfMemory, "Failed to create internal handle");
1226             }
1227
1228             Interop.PackageManager.ErrorCode err = Interop.PackageManagerInternal.PkgmgrClientActivate(clientHandle, null, packageId);
1229             if (err != Interop.PackageManager.ErrorCode.None)
1230             {
1231                 Interop.PackageManagerInternal.PkgmgrClientFree(clientHandle);
1232                 throw PackageManagerErrorFactory.GetException(err, "Failed to activate the package");
1233             }
1234
1235             Interop.PackageManagerInternal.PkgmgrClientFree(clientHandle);
1236         }
1237
1238         /// <summary>
1239         /// Disable the given package.
1240         /// </summary>
1241         /// <param name="packageId">The ID of the package.</param>
1242         /// <remarks>
1243         /// This API is for inhouse app only.
1244         /// </remarks>
1245         /// <returns>Returns true if succeeds, otherwise false.</returns>
1246         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1247         /// <privlevel>platform</privlevel>
1248         /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid.</exception>
1249         /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
1250         /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1251         /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
1252         /// <since_tizen> 11 </since_tizen>
1253         [EditorBrowsable(EditorBrowsableState.Never)]
1254         public static void DisablePackage(string packageId)
1255         {
1256             // 0 is PC_REQUEST
1257             IntPtr clientHandle = Interop.PackageManagerInternal.PkgmgrClientNew(0);
1258             if (clientHandle == null)
1259             {
1260                 throw PackageManagerErrorFactory.GetException(Interop.PackageManager.ErrorCode.OutOfMemory, "Failed to create internal handle");
1261             }
1262
1263             Interop.PackageManager.ErrorCode err = Interop.PackageManagerInternal.PkgmgrClientDeactivate(clientHandle, null, packageId);
1264             if (err != Interop.PackageManager.ErrorCode.None)
1265             {
1266                 Interop.PackageManagerInternal.PkgmgrClientFree(clientHandle);
1267                 throw PackageManagerErrorFactory.GetException(err, "Failed to activate the package");
1268             }
1269
1270             Interop.PackageManagerInternal.PkgmgrClientFree(clientHandle);
1271         }
1272
1273         /// <summary>
1274         /// Drm nested class. This class has the PackageManager's drm related methods.
1275         /// </summary>
1276         /// <since_tizen> 3 </since_tizen>
1277         public static class Drm
1278         {
1279             /// <summary>
1280             /// Generates a request for getting the license.
1281             /// </summary>
1282             /// <param name="responseData">Response data string of the purchase request.</param>
1283             /// <returns>Returns the package DRM information of a given response data which contains the required data and license URL.</returns>
1284             /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1285             /// <privlevel>platform</privlevel>
1286             /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid.</exception>
1287             /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
1288             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1289             /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
1290             /// <since_tizen> 3 </since_tizen>
1291             public static PackageDrm GenerateLicenseRequest(string responseData)
1292             {
1293                 return PackageDrm.GenerateLicenseRequest(responseData);
1294
1295             }
1296
1297             /// <summary>
1298             /// Registers the encrypted license.
1299             /// </summary>
1300             /// <param name="responseData">The response data string of the rights request.</param>
1301             /// <returns>Returns true if succeeds, otherwise false.</returns>
1302             /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1303             /// <privlevel>platform</privlevel>
1304             /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid.</exception>
1305             /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
1306             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1307             /// <exception cref="SystemException">Thrown when the method failed due to internal system error.</exception>
1308             /// <since_tizen> 3 </since_tizen>
1309             public static bool RegisterLicense(string responseData)
1310             {
1311                 Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerDrmRegisterLicense(responseData);
1312                 if (err != Interop.PackageManager.ErrorCode.None)
1313                 {
1314                     throw PackageManagerErrorFactory.GetException(err, "Failed to register drm license");
1315                 }
1316
1317                 return true;
1318             }
1319
1320             /// <summary>
1321             /// Decrypts the contents which are encrypted.
1322             /// </summary>
1323             /// <param name="drmFilePath">Drm file path.</param>
1324             /// <param name="decryptedFilePath">Decrypted file path.</param>
1325             /// <returns>Returns true if succeeds, otherwise false.</returns>
1326             /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
1327             /// <privlevel>platform</privlevel>
1328             /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid.</exception>
1329             /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method.</exception>
1330             /// <exception cref="UnauthorizedAccessException">Thrown when an application does not have the privilege to access this method.</exception>
1331             /// <exception cref="SystemException">Thrown when the method failed due to an internal system error.</exception>
1332             /// <since_tizen> 3 </since_tizen>
1333             public static bool DecryptPackage(string drmFilePath, string decryptedFilePath)
1334             {
1335                 Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerDrmDecryptPackage(drmFilePath, decryptedFilePath);
1336                 if (err != Interop.PackageManager.ErrorCode.None)
1337                 {
1338                     throw PackageManagerErrorFactory.GetException(err, "Failed to decrypt drm package");
1339                 }
1340
1341                 return true;
1342             }
1343         }
1344
1345         private static void SetPackageManagerEventStatus(Interop.PackageManager.EventStatus status)
1346         {
1347             if (Handle.IsInvalid) return;
1348
1349             Interop.PackageManager.EventStatus eventStatus = s_eventStatus;
1350             eventStatus |= status;
1351             if (eventStatus != Interop.PackageManager.EventStatus.All)
1352                 eventStatus |= Interop.PackageManager.EventStatus.Progress;
1353
1354             var err = Interop.PackageManager.ErrorCode.None;
1355             if (s_eventStatus != eventStatus)
1356             {
1357                 err = Interop.PackageManager.PackageManagerSetEventStatus(Handle, eventStatus);
1358                 if (err == Interop.PackageManager.ErrorCode.None)
1359                 {
1360                     s_eventStatus = eventStatus;
1361                     Log.Debug(LogTag, string.Format("New Event Status flag: {0}", s_eventStatus));
1362                     return;
1363                 }
1364                 Log.Debug(LogTag, string.Format("Failed to set flag for {0} event. err = {1}", eventStatus, err));
1365             }
1366         }
1367
1368         private static void UnsetPackageManagerEventStatus()
1369         {
1370             if (Handle.IsInvalid) return;
1371
1372             Interop.PackageManager.EventStatus eventStatus = Interop.PackageManager.EventStatus.All;
1373             if (s_installEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Install;
1374             if (s_uninstallEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Uninstall;
1375             if (s_updateEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Upgrade;
1376             if (s_moveEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Move;
1377             if (s_clearDataEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.ClearData;
1378             if (eventStatus != Interop.PackageManager.EventStatus.All)
1379                 eventStatus |= Interop.PackageManager.EventStatus.Progress;
1380
1381             var err = Interop.PackageManager.ErrorCode.None;
1382             if (s_eventStatus != eventStatus)
1383             {
1384                 err = Interop.PackageManager.PackageManagerSetEventStatus(Handle, eventStatus);
1385                 if (err == Interop.PackageManager.ErrorCode.None)
1386                 {
1387                     s_eventStatus = eventStatus;
1388                     Log.Debug(LogTag, string.Format("New Event Status flag: {0}", s_eventStatus));
1389                     return;
1390                 }
1391                 Log.Debug(LogTag, string.Format("Failed to set flag for {0} event. err = {1}", eventStatus, err));
1392             }
1393         }
1394
1395         private static void RegisterPackageManagerEventIfNeeded()
1396         {
1397             if (s_installEventHandler != null && s_uninstallEventHandler != null && s_updateEventHandler != null && s_moveEventHandler != null && s_clearDataEventHandler != null)
1398                 return;
1399
1400             if ((s_registered_eventStatus & s_eventStatus) == s_eventStatus)
1401                 return;
1402
1403             var err = Interop.PackageManager.ErrorCode.None;
1404
1405             if (!Handle.IsInvalid)
1406             {
1407                 lock (Handle)
1408                 {
1409                     err = Interop.PackageManager.PackageManagerSetEvent(Handle, s_packageManagerEventCallback, IntPtr.Zero);
1410                 }
1411             }
1412             if (err != Interop.PackageManager.ErrorCode.None)
1413             {
1414                 s_registered_eventStatus = Interop.PackageManager.EventStatus.All;
1415                 Log.Warn(LogTag, string.Format("Failed to register callback for package manager event. err = {0}", err));
1416                 throw PackageManagerErrorFactory.GetException(err, "Failed to register package manager event.");
1417             } else {
1418                 s_registered_eventStatus = s_eventStatus;
1419             }
1420         }
1421
1422         private static void InternalEventCallback(string packageType, string packageId, Interop.PackageManager.EventType eventType, Interop.PackageManager.PackageEventState eventState, int progress, Interop.PackageManager.ErrorCode error, IntPtr user_data)
1423         {
1424             PackageManagerEventArgs args;
1425             try
1426             {
1427                 args = new PackageManagerEventArgs(packageType, packageId, (PackageEventState)eventState, progress);
1428             }
1429             catch (Exception e)
1430             {
1431                 Log.Warn(LogTag, e.Message);
1432                 return;
1433             }
1434
1435             EventHandler<PackageManagerEventArgs> handlers = null;
1436             lock (s_pkgEventLock)
1437             {
1438                 if (eventType == Interop.PackageManager.EventType.Install)
1439                 {
1440                     handlers = s_installEventHandler;
1441                 }
1442                 else if (eventType == Interop.PackageManager.EventType.Uninstall)
1443                 {
1444                     handlers = s_uninstallEventHandler;
1445                 }
1446                 else if (eventType == Interop.PackageManager.EventType.Update)
1447                 {
1448                     handlers = s_updateEventHandler;
1449                 }
1450                 else if (eventType == Interop.PackageManager.EventType.Move)
1451                 {
1452                     handlers = s_moveEventHandler;
1453                 }
1454                 else if (eventType == Interop.PackageManager.EventType.ClearData)
1455                 {
1456                     handlers = s_clearDataEventHandler;
1457                 }
1458             }
1459
1460             handlers?.Invoke(null, args);
1461         }
1462
1463         private static void UnregisterPackageManagerEventIfNeeded()
1464         {
1465             if (s_packageManagerEventCallback == null || s_installEventHandler != null || s_uninstallEventHandler != null || s_updateEventHandler != null || s_moveEventHandler != null || s_clearDataEventHandler != null)
1466             {
1467                 return;
1468             }
1469
1470             lock (Handle)
1471             {
1472                 var err = Interop.PackageManager.PackageManagerUnsetEvent(Handle);
1473                 if (err != Interop.PackageManager.ErrorCode.None)
1474                 {
1475                     throw PackageManagerErrorFactory.GetException(err, "Failed to unregister package manager event event.");
1476                 }
1477                 s_registered_eventStatus = Interop.PackageManager.EventStatus.All;
1478             }
1479         }
1480     }
1481
1482     internal static class PackageManagerErrorFactory
1483     {
1484         internal static Exception GetException(Interop.PackageManager.ErrorCode err, string message)
1485         {
1486             string errMessage = string.Format("{0} err = {1}", message, err);
1487             switch (err)
1488             {
1489                 case Interop.PackageManager.ErrorCode.InvalidParameter:
1490                 case Interop.PackageManager.ErrorCode.NoSuchPackage:
1491                     return new ArgumentException(errMessage);
1492                 case Interop.PackageManager.ErrorCode.PermissionDenied:
1493                     return new UnauthorizedAccessException(errMessage);
1494                 case Interop.PackageManager.ErrorCode.IoError:
1495                     return new global::System.IO.IOException(errMessage);
1496                 default:
1497                     return new InvalidOperationException(errMessage);
1498             }
1499         }
1500     }
1501 }