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