Release 4.0.0-preview1-00051
[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 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 is occurred when a package is getting installed and the progress of the request to the package manager changes.
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 is occurred when a package is getting uninstalled and the progress of the request to the package manager changes.
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 is occurred when a package is getting updated and the progress of the request to the package manager changes.
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 is occurred when a package is getting moved and the progress of the request to the package manager changes.
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 is occurred 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 app ID.
199         /// </summary>
200         /// <param name="applicationId">The ID of the application</param>
201         /// <returns>Returns the ID of the package. Empty string if App 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 app does not have 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 failed when 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 method failed due to internal IO error</exception>
228         /// <exception cref="UnauthorizedAccessException">Thrown when app does not have 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 directory.
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 method failed due to internal IO error</exception>
241         /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
242         /// <exception cref="SystemException">Thrown when method failed due to 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 application's internal and external cache directory.
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 method failed due to internal IO error</exception>
259         /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
260         /// <exception cref="SystemException">Thrown when method failed due to 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 external storeage 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 method failed due to internal IO error</exception>
283         /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
284         /// <exception cref="SystemException">Thrown when method failed due to 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 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 package information of all installed packages satisfying 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 package located at the given path
387         /// </summary>
388         /// <param name="packagePath">Absolute path for the package to be installed</param>
389         /// <returns>Returns true if installtion request is successful, false otherwise.</returns>
390         /// <remarks>
391         /// The 'true' means that just the request of installation is seccessful.
392         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event.
393         /// </remarks>
394         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
395         /// <privlevel>platform</privlevel>
396         public static bool Install(string packagePath, InstallationMode installMode = InstallationMode.Normal)
397         {
398             return Install(packagePath, null, PackageType.UNKNOWN, null, installMode);
399         }
400
401         /// <summary>
402         /// Installs package located at the given path
403         /// </summary>
404         /// <param name="packagePath">Absolute path for the package to be installed</param>
405         /// <param name="eventCallback">The event callback will be invoked only for the current request</param>
406         /// <param name="installMode">Optional parameter to indicate special installation mode</param>
407         /// <returns>Returns true if installtion request is successful, false otherwise.</returns>
408         /// <remarks>
409         /// The 'true' means that just the request of installation is seccessful.
410         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event OR eventCallback.
411         /// </remarks>
412         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
413         /// <privlevel>platform</privlevel>
414         public static bool Install(string packagePath, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
415         {
416             return Install(packagePath, null, PackageType.UNKNOWN, eventCallback, installMode);
417         }
418
419         /// <summary>
420         /// Installs package located at the given path
421         /// </summary>
422         /// <param name="packagePath">Absolute path for the package to be installed</param>
423         /// <param name="type">Package type for the package to be installed</param>
424         /// <param name="installMode">Optional parameter to indicate special installation mode</param>
425         /// <returns>Returns true if installtion request is successful, false otherwise.</returns>
426         /// <remarks>
427         /// The 'true' means that just the request of installation is seccessful.
428         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event.
429         /// </remarks>
430         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
431         /// <privlevel>platform</privlevel>
432         public static bool Install(string packagePath, PackageType type, InstallationMode installMode = InstallationMode.Normal)
433         {
434             return Install(packagePath, null, type, null, installMode);
435         }
436
437         /// <summary>
438         /// Installs package located at the given path
439         /// </summary>
440         /// <param name="packagePath">Absolute path for the package to be installed</param>
441         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed</param>
442         /// <param name="installMode">Optional parameter to indicate special installation mode</param>
443         /// <returns>Returns true if installtion request is successful, false otherwise.</returns>
444         /// <remarks>
445         /// The 'true' means that just the request of installation is seccessful.
446         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event.
447         /// </remarks>
448         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
449         /// <privlevel>platform</privlevel>
450         public static bool Install(string packagePath, string expansionPackagePath, InstallationMode installMode = InstallationMode.Normal)
451         {
452             return Install(packagePath, expansionPackagePath, PackageType.UNKNOWN, null, installMode);
453         }
454
455         /// <summary>
456         /// Installs 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="eventCallback">The event callback will be invoked only for the current request</param>
461         /// <param name="installMode">Optional parameter to indicate special installation mode</param>
462         /// <returns>Returns true if installtion request is successful, false otherwise.</returns>
463         /// <remarks>
464         /// The 'true' means that just the request of installation is seccessful.
465         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event OR eventCallback.
466         /// </remarks>
467         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
468         /// <privlevel>platform</privlevel>
469         public static bool Install(string packagePath, PackageType type, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
470         {
471             return Install(packagePath, null, type, eventCallback, installMode);
472         }
473
474         /// <summary>
475         /// Installs 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="eventCallback">The event callback will be invoked only for the current request</param>
480         /// <param name="installMode">Optional parameter to indicate special installation mode</param>
481         /// <returns>Returns true if installtion request is successful, false otherwise.</returns>
482         /// <remarks>
483         /// The 'true' means that just the request of installation is seccessful.
484         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event OR eventCallback.
485         /// </remarks>
486         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
487         /// <privlevel>platform</privlevel>
488         public static bool Install(string packagePath, string expansionPackagePath, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
489         {
490             return Install(packagePath, expansionPackagePath, PackageType.UNKNOWN, eventCallback, installMode);
491         }
492
493         /// <summary>
494         /// Installs package located at the given path
495         /// </summary>
496         /// <param name="packagePath">Absolute path for the package to be installed</param>
497         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed</param>
498         /// <param name="type">Package type for the package to be installed</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 just the request of installation is seccessful.
503         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event.
504         /// </remarks>
505         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
506         /// <privlevel>platform</privlevel>
507         public static bool Install(string packagePath, string expansionPackagePath, PackageType type, InstallationMode installMode = InstallationMode.Normal)
508         {
509             return Install(packagePath, expansionPackagePath, type, null, installMode);
510         }
511
512         /// <summary>
513         /// Installs package located at the given path
514         /// </summary>
515         /// <param name="packagePath">Absolute path for the package to be installed</param>
516         /// <param name="expansionPackagePath">Absolute path for the expansion package to be installed</param>
517         /// <param name="type">Package type for the 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 just the request of installation is seccessful.
523         /// To check the result of installation, the caller should check the progress using InstallProgressChanged event OR eventCallback.
524         /// </remarks>
525         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
526         /// <privlevel>platform</privlevel>
527         public static bool Install(string packagePath, string expansionPackagePath, PackageType type, RequestEventCallback eventCallback, InstallationMode installMode = InstallationMode.Normal)
528         {
529             SafePackageManagerRequestHandle RequestHandle;
530             var err = Interop.PackageManager.PackageManagerRequestCreate(out RequestHandle);
531             if (err != Interop.PackageManager.ErrorCode.None)
532             {
533                 Log.Warn(LogTag, string.Format("Failed to install package {0}. Error in creating package manager request handle. err = {1}", packagePath, err));
534                 return false;
535             }
536
537             try
538             {
539                 if (type != PackageType.UNKNOWN)
540                 {
541                     err = Interop.PackageManager.PackageManagerRequestSetType(RequestHandle, type.ToString().ToLower());
542                     if (err != Interop.PackageManager.ErrorCode.None)
543                     {
544                         Log.Warn(LogTag, string.Format("Failed to install package {0}. Error in setting request package type. err = {1}", packagePath, err));
545                         RequestHandle.Dispose();
546                         return false;
547                     }
548                 }
549
550                 if (!string.IsNullOrEmpty(expansionPackagePath))
551                 {
552                     err = Interop.PackageManager.PackageManagerRequestSetTepPath(RequestHandle, expansionPackagePath);
553                     if (err != Interop.PackageManager.ErrorCode.None)
554                     {
555                         Log.Warn(LogTag, string.Format("Failed to install package {0}. Error in setting request package mode. err = {1}", packagePath, err));
556                         RequestHandle.Dispose();
557                         return false;
558                     }
559                 }
560
561                 int requestId;
562                 if (eventCallback != null)
563                 {
564                     InstallMethodWithCallback install;
565                     if (installMode == InstallationMode.Mount)
566                     {
567                         install = Interop.PackageManager.PackageManagerRequestMountInstallWithCB;
568                     }
569                     else
570                     {
571                         install = Interop.PackageManager.PackageManagerRequestInstallWithCB;
572                     }
573                     err = install(RequestHandle, packagePath, internalRequestEventCallback, IntPtr.Zero, out requestId);
574                     if (err == Interop.PackageManager.ErrorCode.None)
575                     {
576                         RequestCallbacks.Add(requestId, eventCallback);
577                         RequestHandles.Add(requestId, RequestHandle);
578                     }
579                     else
580                     {
581                         Log.Warn(LogTag, string.Format("Failed to install package {0}. err = {1}", packagePath, err));
582                         RequestHandle.Dispose();
583                         return false;
584                     }
585                 }
586                 else
587                 {
588                     InstallMethod install;
589                     if (installMode == InstallationMode.Mount)
590                     {
591                         install = Interop.PackageManager.PackageManagerRequestMountInstall;
592                     }
593                     else
594                     {
595                         install = Interop.PackageManager.PackageManagerRequestInstall;
596                     }
597                     err = install(RequestHandle, packagePath, out requestId);
598                     if (err != Interop.PackageManager.ErrorCode.None)
599                     {
600                         Log.Warn(LogTag, string.Format("Failed to install package {0}. err = {1}", packagePath, err));
601                         RequestHandle.Dispose();
602                         return false;
603                     }
604                     // RequestHandle isn't necessary when this method is called without 'eventCallback' parameter.
605                     RequestHandle.Dispose();
606                 }
607                 return true;
608             }
609             catch (Exception e)
610             {
611                 Log.Warn(LogTag, e.Message);
612                 RequestHandle.Dispose();
613                 return false;
614             }
615         }
616
617         /// <summary>
618         /// Uninstalls package with the given name.
619         /// </summary>
620         /// <param name="packageId">Id of the package to be uninstalled</param>
621         /// <returns>Returns true if uninstallation request is successful, false otherwise.</returns>
622         /// <remarks>
623         /// The 'true' means that just the request of uninstallation is seccessful.
624         /// To check the result of uninstallation, the caller should check the progress using UninstallProgressChanged event.
625         /// </remarks>
626         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
627         /// <privlevel>platform</privlevel>
628         public static bool Uninstall(string packageId)
629         {
630             return Uninstall(packageId, PackageType.UNKNOWN, null);
631         }
632
633         /// <summary>
634         /// Uninstalls package with the given name.
635         /// </summary>
636         /// <param name="packageId">Id of the package to be uninstalled</param>
637         /// <param name="type">Optional - Package type for the package to be uninstalled</param>
638         /// <returns>Returns true if uninstalltion request is successful, false otherwise.</returns>
639         /// <remarks>
640         /// The 'true' means that just the request of uninstallation is seccessful.
641         /// To check the result of uninstallation, the caller should check the progress using UninstallProgressChanged event.
642         /// </remarks>
643         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
644         /// <privlevel>platform</privlevel>
645         public static bool Uninstall(string packageId, PackageType type)
646         {
647             return Uninstall(packageId, type, null);
648         }
649
650         /// <summary>
651         /// Uninstalls package with the given name.
652         /// </summary>
653         /// <param name="packageId">Id of the package to be uninstalled</param>
654         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request</param>
655         /// <returns>Returns true if uninstalltion request is successful, false otherwise.</returns>
656         /// <remarks>
657         /// The 'true' means that just the request of uninstallation is seccessful.
658         /// To check the result of uninstallation, the caller should check the progress using UninstallProgressChanged event OR eventCallback.
659         /// </remarks>
660         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
661         /// <privlevel>platform</privlevel>
662         public static bool Uninstall(string packageId, RequestEventCallback eventCallback)
663         {
664             return Uninstall(packageId, PackageType.UNKNOWN, eventCallback);
665         }
666
667         /// <summary>
668         /// Uninstalls package with the given name.
669         /// </summary>
670         /// <param name="packageId">Id of the package to be uninstalled</param>
671         /// <param name="type">Optional - Package type for the package to be uninstalled</param>
672         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request</param>
673         /// <returns>Returns true if uninstalltion request is successful, false otherwise.</returns>
674         /// <remarks>
675         /// The 'true' means that just the request of uninstallation is seccessful.
676         /// To check the result of uninstallation, the caller should check the progress using UninstallProgressChanged event OR eventCallback.
677         /// </remarks>
678         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
679         /// <privlevel>platform</privlevel>
680         public static bool Uninstall(string packageId, PackageType type, RequestEventCallback eventCallback)
681         {
682             SafePackageManagerRequestHandle RequestHandle;
683             var err = Interop.PackageManager.PackageManagerRequestCreate(out RequestHandle);
684             if (err != Interop.PackageManager.ErrorCode.None)
685             {
686                 Log.Warn(LogTag, string.Format("Failed to uninstall package {0}. Error in creating package manager request handle. err = {1}", packageId, err));
687                 return false;
688             }
689
690             try
691             {
692                 err = Interop.PackageManager.PackageManagerRequestSetType(RequestHandle, type.ToString().ToLower());
693                 if (err != Interop.PackageManager.ErrorCode.None)
694                 {
695                     Log.Warn(LogTag, string.Format("Failed to uninstall package {0}. Error in setting request package type. err = {1}", packageId, err));
696                     RequestHandle.Dispose();
697                     return false;
698                 }
699
700                 int requestId;
701                 if (eventCallback != null)
702                 {
703                     err = Interop.PackageManager.PackageManagerRequestUninstallWithCB(RequestHandle, packageId, internalRequestEventCallback, IntPtr.Zero, out requestId);
704                     if (err == Interop.PackageManager.ErrorCode.None)
705                     {
706                         RequestCallbacks.Add(requestId, eventCallback);
707                         RequestHandles.Add(requestId, RequestHandle);
708                     }
709                     else
710                     {
711                         Log.Warn(LogTag, string.Format("Failed to uninstall package {0}. err = {1}", packageId, err));
712                         RequestHandle.Dispose();
713                         return false;
714                     }
715                 }
716                 else
717                 {
718                     err = Interop.PackageManager.PackageManagerRequestUninstall(RequestHandle, packageId, out requestId);
719                     if (err != Interop.PackageManager.ErrorCode.None)
720                     {
721                         Log.Warn(LogTag, string.Format("Failed to uninstall package. err = {0}", err));
722                         RequestHandle.Dispose();
723                         return false;
724                     }
725                     // RequestHandle isn't necessary when this method is called without 'eventCallback' parameter.
726                     RequestHandle.Dispose();
727                 }
728                 return true;
729             }
730             catch (Exception e)
731             {
732                 Log.Warn(LogTag, e.Message);
733                 RequestHandle.Dispose();
734                 return false;
735             }
736         }
737
738         /// <summary>
739         /// Move package to given storage.
740         /// </summary>
741         /// <param name="packageId">Id of the package to be moved</param>
742         /// <param name="newStorage">Storage, package should be moved to</param>
743         /// <returns>Returns true if move request is successful, false otherwise.</returns>
744         /// <remarks>
745         /// The 'true' means that just the request of move is seccessful.
746         /// To check the result of move, the caller should check the progress using MoveProgressChanged event.
747         /// </remarks>
748         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
749         /// <privlevel>platform</privlevel>
750         public static bool Move(string packageId, StorageType newStorage)
751         {
752             return Move(packageId, PackageType.UNKNOWN, newStorage, null);
753         }
754
755         /// <summary>
756         /// Move package to given storage.
757         /// </summary>
758         /// <param name="packageId">Id of the package to be moved</param>
759         /// <param name="type">Optional - Package type for the package to be moved</param>
760         /// <param name="newStorage">Storage, package should be moved to</param>
761         /// <returns>Returns true if move request is successful, false otherwise.</returns>
762         /// <remarks>
763         /// The 'true' means that just the request of move is seccessful.
764         /// To check the result of move, the caller should check the progress using MoveProgressChanged event.
765         /// </remarks>
766         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
767         /// <privlevel>platform</privlevel>
768         public static bool Move(string packageId, PackageType type, StorageType newStorage)
769         {
770             return Move(packageId, type, newStorage, null);
771         }
772
773         /// <summary>
774         /// Move package to given storage.
775         /// </summary>
776         /// <param name="packageId">Id of the package to be moved</param>
777         /// <param name="newStorage">Storage, package should be moved to</param>
778         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request</param>
779         /// <returns>Returns true if move request is successful, false otherwise.</returns>
780         /// <remarks>
781         /// The 'true' means that just the request of move is seccessful.
782         /// To check the result of move, the caller should check the progress using MoveProgressChanged event.
783         /// </remarks>
784         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
785         /// <privlevel>platform</privlevel>
786         public static bool Move(string packageId, StorageType newStorage, RequestEventCallback eventCallback)
787         {
788             return Move(packageId, PackageType.UNKNOWN, newStorage, eventCallback);
789         }
790
791         /// <summary>
792         /// Move package to given storage.
793         /// </summary>
794         /// <param name="packageId">Id of the package to be moved</param>
795         /// <param name="type">Optional - Package type for the package to be moved</param>
796         /// <param name="newStorage">Storage, package should be moved to</param>
797         /// <param name="eventCallback">Optional - The event callback will be invoked only for the current request</param>
798         /// <returns>Returns true if move request is successful, false otherwise.</returns>
799         /// <remarks>
800         /// The 'true' means that just the request of move is seccessful.
801         /// To check the result of move, the caller should check the progress using MoveProgressChanged event.
802         /// </remarks>
803         /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
804         /// <privlevel>platform</privlevel>
805         public static bool Move(string packageId, PackageType type, StorageType newStorage, RequestEventCallback eventCallback)
806         {
807             SafePackageManagerRequestHandle RequestHandle;
808             var err = Interop.PackageManager.PackageManagerRequestCreate(out RequestHandle);
809             if (err != Interop.PackageManager.ErrorCode.None)
810             {
811                 Log.Warn(LogTag, string.Format("Failed to create package manager request handle. err = {0}", err));
812                 return false;
813             }
814
815             try
816             {
817                 bool result = true;
818                 err = Interop.PackageManager.PackageManagerRequestSetType(RequestHandle, type.ToString().ToLower());
819                 if (err != Interop.PackageManager.ErrorCode.None)
820                 {
821                     Log.Warn(LogTag, string.Format("Failed to move package. Error in setting request package type. err = {0}", err));
822                     RequestHandle.Dispose();
823                     return false;
824                 }
825
826                 if (eventCallback != null)
827                 {
828                     int requestId;
829                     err = Interop.PackageManager.PackageManagerRequestMoveWithCB(RequestHandle, packageId, (Interop.PackageManager.StorageType)newStorage, internalRequestEventCallback, IntPtr.Zero, out requestId);
830                     if (err == Interop.PackageManager.ErrorCode.None)
831                     {
832                         RequestCallbacks.Add(requestId, eventCallback);
833                         RequestHandles.Add(requestId, RequestHandle);
834                     }
835                     else
836                     {
837                         Log.Warn(LogTag, string.Format("Failed to move package to requested location. err = {0}", err));
838                         RequestHandle.Dispose();
839                         result = false;
840                     }
841                 }
842                 else
843                 {
844                     err = Interop.PackageManager.PackageManagerRequestMove(RequestHandle, packageId, (Interop.PackageManager.StorageType)newStorage);
845                     if (err != Interop.PackageManager.ErrorCode.None)
846                     {
847                         Log.Warn(LogTag, string.Format("Failed to move package to requested location. err = {0}", err));
848                         RequestHandle.Dispose();
849                         result = false;
850                     }
851                     // RequestHandle isn't necessary when this method is called without 'eventCallback' parameter.
852                     RequestHandle.Dispose();
853                 }
854                 return result;
855             }
856             catch (Exception e)
857             {
858                 Log.Warn(LogTag, e.Message);
859                 RequestHandle.Dispose();
860                 return false;
861             }
862         }
863
864         /// <summary>
865         /// Gets permission type of package which has given application id
866         /// </summary>
867         /// <param name="applicationId">Id of the application</param>
868         /// <returns>Returns permission type.</returns>
869         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
870         /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
871         /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
872         public static PermissionType GetPermissionTypeByApplicationId(string applicationId)
873         {
874             Interop.PackageManager.PackageManagerPermissionType permissionType;
875             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerGetPermissionType(applicationId, out permissionType);
876             if (err != Interop.PackageManager.ErrorCode.None)
877             {
878                 throw PackageManagerErrorFactory.GetException(err, "Failed to get permission type.");
879             }
880
881             return (PermissionType)permissionType;
882         }
883
884         /// <summary>
885         /// Gets package's preload attribute which contain given applicion id
886         /// </summary>
887         /// <param name="applicationId">Id of the application</param>
888         /// <returns>Returns true if package is preloaded. Otherwise return false.</returns>
889         /// <privilege>http://tizen.org/privilege/packagemanager.info</privilege>
890         /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
891         /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
892         public static bool IsPreloadPackageByApplicationId(string applicationId)
893         {
894             bool isPreloadPackage;
895             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerIsPreloadPackageByApplicationId(applicationId, out isPreloadPackage);
896             if (err != Interop.PackageManager.ErrorCode.None)
897             {
898                 throw PackageManagerErrorFactory.GetException(err, "Failed to get preload info");
899             }
900
901             return isPreloadPackage;
902         }
903
904         /// <summary>
905         /// Compare certificate of two packages
906         /// </summary>
907         /// <param name="lhsPackageId">package id to compare</param>
908         /// <param name="rhsPackageId">package id to be compared</param>
909         /// <returns>Returns certificate comparison result.</returns>
910         /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
911         /// <exception cref="System.IO.IOException">Thrown when method failed due to internal IO error</exception>
912         public static CertCompareResultType CompareCertInfo(string lhsPackageId, string rhsPackageId)
913         {
914             Interop.PackageManager.CertCompareResultType compareResult;
915             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerCompareCertInfo(lhsPackageId, rhsPackageId, out compareResult);
916             if (err != Interop.PackageManager.ErrorCode.None)
917             {
918                 throw PackageManagerErrorFactory.GetException(err, "Failed to compare cert info");
919             }
920
921             return (CertCompareResultType)compareResult;
922         }
923
924         /// <summary>
925         /// Compare certificate of two packages which contain each given application id
926         /// </summary>
927         /// <param name="lhsApplicationId">application id to compare</param>
928         /// <param name="rhsApplicationId">application id to be compared</param>
929         /// <returns>Returns certificate comparison result.</returns>
930         /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
931         /// <exception cref="System.IO.IOException">Thrown when method failed due to internal IO error</exception>
932         public static CertCompareResultType CompareCertInfoByApplicationId(string lhsApplicationId, string rhsApplicationId)
933         {
934             Interop.PackageManager.CertCompareResultType compareResult;
935             Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerCompareCertInfoByApplicationId(lhsApplicationId, rhsApplicationId, out compareResult);
936             if (err != Interop.PackageManager.ErrorCode.None)
937             {
938                 throw PackageManagerErrorFactory.GetException(err, "Failed to compare cert info by application id");
939             }
940
941             return (CertCompareResultType)compareResult;
942         }
943
944         /// <summary>
945         /// Drm nested class. This class has the PackageManager's drm related methods.
946         /// </summary>
947         public static class Drm
948         {
949             /// <summary>
950             /// Generates request for getting license
951             /// </summary>
952             /// <param name="responseData">Response data string of the purchase request</param>
953             /// <returns>Returns package drm information of given response data which contains require data and license url</returns>
954             /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
955             /// <privlevel>platform</privlevel>
956             /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
957             /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method</exception>
958             /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
959             /// <exception cref="SystemException">Thrown when method failed due to internal system error</exception>
960             public static PackageDrm GenerateLicenseRequest(string responseData)
961             {
962                 return PackageDrm.GenerateLicenseRequest(responseData);
963
964             }
965
966             /// <summary>
967             /// Registers encrypted license
968             /// </summary>
969             /// <param name="responseData">The response data string of the rights request</param>
970             /// <returns>Returns true if succeed. Otherwise return false</returns>
971             /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
972             /// <privlevel>platform</privlevel>
973             /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
974             /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method</exception>
975             /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
976             /// <exception cref="SystemException">Thrown when method failed due to internal system error</exception>
977             public static bool RegisterLicense(string responseData)
978             {
979                 Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerDrmRegisterLicense(responseData);
980                 if (err != Interop.PackageManager.ErrorCode.None)
981                 {
982                     throw PackageManagerErrorFactory.GetException(err, "Failed to register drm license");
983                 }
984
985                 return true;
986             }
987
988             /// <summary>
989             /// Decrypts contents which is encrypted
990             /// </summary>
991             /// <param name="drmFilePath">Drm file path</param>
992             /// <param name="decryptedFilePath">Decrypted file path</param>
993             /// <returns>Returns true if succeed. Otherwise return false</returns>
994             /// <privilege>http://tizen.org/privilege/packagemanager.admin</privilege>
995             /// <privlevel>platform</privlevel>
996             /// <exception cref="ArgumentException">Thrown when failed when input package ID is invalid</exception>
997             /// <exception cref="OutOfMemoryException">Thrown when there is not enough memory to continue the execution of the method</exception>
998             /// <exception cref="UnauthorizedAccessException">Thrown when app does not have privilege to access this method</exception>
999             /// <exception cref="SystemException">Thrown when method failed due to internal system error</exception>
1000             public static bool DecryptPackage(string drmFilePath, string decryptedFilePath)
1001             {
1002                 Interop.PackageManager.ErrorCode err = Interop.PackageManager.PackageManagerDrmDecryptPackage(drmFilePath, decryptedFilePath);
1003                 if (err != Interop.PackageManager.ErrorCode.None)
1004                 {
1005                     throw PackageManagerErrorFactory.GetException(err, "Failed to decrypt drm package");
1006                 }
1007
1008                 return true;
1009             }
1010         }
1011
1012         private static void SetPackageManagerEventStatus(Interop.PackageManager.EventStatus status)
1013         {
1014             if (Handle.IsInvalid) return;
1015
1016             Interop.PackageManager.EventStatus eventStatus = s_eventStatus;
1017             eventStatus |= status;
1018             if (eventStatus != Interop.PackageManager.EventStatus.All)
1019                 eventStatus |= Interop.PackageManager.EventStatus.Progress;
1020
1021             var err = Interop.PackageManager.ErrorCode.None;
1022             if (s_eventStatus != eventStatus)
1023             {
1024                 err = Interop.PackageManager.PackageManagerSetEvenStatus(Handle, eventStatus);
1025                 if (err == Interop.PackageManager.ErrorCode.None)
1026                 {
1027                     s_eventStatus = eventStatus;
1028                     Log.Debug(LogTag, string.Format("New Event Status flag: {0}", s_eventStatus));
1029                     return;
1030                 }
1031                 Log.Debug(LogTag, string.Format("Failed to set flag for {0} event. err = {1}", eventStatus, err));
1032             }
1033         }
1034
1035         private static void UnsetPackageManagerEventStatus()
1036         {
1037             if (Handle.IsInvalid) return;
1038
1039             Interop.PackageManager.EventStatus eventStatus = Interop.PackageManager.EventStatus.All;
1040             if (s_installEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Install;
1041             if (s_uninstallEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Uninstall;
1042             if (s_updateEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Upgrade;
1043             if (s_moveEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.Move;
1044             if (s_clearDataEventHandler != null) eventStatus |= Interop.PackageManager.EventStatus.ClearData;
1045             if (eventStatus != Interop.PackageManager.EventStatus.All)
1046                 eventStatus |= Interop.PackageManager.EventStatus.Progress;
1047
1048             var err = Interop.PackageManager.ErrorCode.None;
1049             if (s_eventStatus != eventStatus)
1050             {
1051                 err = Interop.PackageManager.PackageManagerSetEvenStatus(Handle, eventStatus);
1052                 if (err == Interop.PackageManager.ErrorCode.None)
1053                 {
1054                     s_eventStatus = eventStatus;
1055                     Log.Debug(LogTag, string.Format("New Event Status flag: {0}", s_eventStatus));
1056                     return;
1057                 }
1058                 Log.Debug(LogTag, string.Format("Failed to set flag for {0} event. err = {1}", eventStatus, err));
1059             }
1060         }
1061
1062         private static void RegisterPackageManagerEventIfNeeded()
1063         {
1064             if (s_installEventHandler != null && s_uninstallEventHandler != null && s_updateEventHandler != null && s_moveEventHandler != null && s_clearDataEventHandler != null)
1065             {
1066                 return;
1067             }
1068
1069             var err = Interop.PackageManager.ErrorCode.None;
1070             s_packageManagerEventCallback = (packageType, packageId, eventType, eventState, progress, error, user_data) =>
1071             {
1072                 try
1073                 {
1074                     if (eventType == Interop.PackageManager.EventType.Install)
1075                     {
1076                         s_installEventHandler?.Invoke(null, new PackageManagerEventArgs(packageType, packageId, (PackageEventState)eventState, progress));
1077                     }
1078                     else if (eventType == Interop.PackageManager.EventType.Uninstall)
1079                     {
1080                         s_uninstallEventHandler?.Invoke(null, new PackageManagerEventArgs(packageType, packageId, (PackageEventState)eventState, progress));
1081                     }
1082                     else if (eventType == Interop.PackageManager.EventType.Update)
1083                     {
1084                         s_updateEventHandler?.Invoke(null, new PackageManagerEventArgs(packageType, packageId, (PackageEventState)eventState, progress));
1085                     }
1086                     else if (eventType == Interop.PackageManager.EventType.Move)
1087                     {
1088                         s_moveEventHandler?.Invoke(null, new PackageManagerEventArgs(packageType, packageId, (PackageEventState)eventState, progress));
1089                     }
1090                     else if (eventType == Interop.PackageManager.EventType.ClearData)
1091                     {
1092                         s_clearDataEventHandler?.Invoke(null, new PackageManagerEventArgs(packageType, packageId, (PackageEventState)eventState, progress));
1093                     }
1094                 }
1095                 catch (Exception e)
1096                 {
1097                     Log.Warn(LogTag, e.Message);
1098                 }
1099             };
1100
1101             if (!Handle.IsInvalid)
1102             {
1103                 Log.Debug(LogTag, "Reset Package Event");
1104                 err = Interop.PackageManager.PackageManagerUnsetEvent(Handle);
1105                 if (err != Interop.PackageManager.ErrorCode.None)
1106                 {
1107                     throw PackageManagerErrorFactory.GetException(err, "Failed to unregister package manager event event.");
1108                 }
1109
1110                 err = Interop.PackageManager.PackageManagerSetEvent(Handle, s_packageManagerEventCallback, IntPtr.Zero);
1111             }
1112             if (err != Interop.PackageManager.ErrorCode.None)
1113             {
1114                 Log.Warn(LogTag, string.Format("Failed to register callback for package manager event. err = {0}", err));
1115             }
1116         }
1117
1118         private static void UnregisterPackageManagerEventIfNeeded()
1119         {
1120             if (Handle.IsInvalid || s_installEventHandler != null || s_uninstallEventHandler != null || s_updateEventHandler != null || s_moveEventHandler != null || s_clearDataEventHandler != null)
1121             {
1122                 return;
1123             }
1124
1125             var err = Interop.PackageManager.PackageManagerUnsetEvent(Handle);
1126             if (err != Interop.PackageManager.ErrorCode.None)
1127             {
1128                 throw PackageManagerErrorFactory.GetException(err, "Failed to unregister package manager event event.");
1129             }
1130         }
1131     }
1132
1133     internal static class PackageManagerErrorFactory
1134     {
1135         internal static Exception GetException(Interop.PackageManager.ErrorCode err, string message)
1136         {
1137             string errMessage = string.Format("{0} err = {1}", message, err);
1138             switch (err)
1139             {
1140                 case Interop.PackageManager.ErrorCode.InvalidParameter:
1141                 case Interop.PackageManager.ErrorCode.NoSuchPackage:
1142                     return new ArgumentException(errMessage);
1143                 case Interop.PackageManager.ErrorCode.PermissionDenied:
1144                     return new UnauthorizedAccessException(errMessage);
1145                 case Interop.PackageManager.ErrorCode.IoError:
1146                     return new global::System.IO.IOException(errMessage);
1147                 default:
1148                     return new InvalidOperationException(errMessage);
1149             }
1150         }
1151     }
1152 }