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