16 */ |
16 */ |
17 |
17 |
18 |
18 |
19 package com.nokia.mj.impl.installer.applicationregistrator; |
19 package com.nokia.mj.impl.installer.applicationregistrator; |
20 |
20 |
21 import com.nokia.mj.impl.installer.ui.InstallerUi; |
|
22 import com.nokia.mj.impl.installer.utils.InstallerException; |
21 import com.nokia.mj.impl.installer.utils.InstallerException; |
23 import com.nokia.mj.impl.installer.utils.Log; |
22 import com.nokia.mj.impl.installer.utils.Log; |
24 import com.nokia.mj.impl.installer.utils.PropertyListener; |
|
25 import com.nokia.mj.impl.installer.utils.PropertyProvider; |
|
26 |
23 |
27 /** |
24 /** |
28 * Sends installation and uninstallation progress notifications |
25 * Sends installation and uninstallation progress notifications |
29 * to platform's software installation framework. |
26 * to platform's software installation framework. |
30 */ |
27 */ |
31 public final class SifNotifier |
28 public final class SifNotifier |
32 { |
29 { |
33 /** Install operation. */ |
30 /** Install operation. */ |
34 public static final int OP_INSTALL = 1; // TSifOperationPhase::EInstalling |
31 public static final int OP_INSTALL = 1; |
35 /** Uninstall operation. */ |
32 /** Uninstall operation. */ |
36 public static final int OP_UNINSTALL = 2; // TSifOperationPhase::EUninstalling |
33 public static final int OP_UNINSTALL = 2; |
37 /** Update operation. */ |
34 /** Update operation. */ |
38 public static final int OP_UPDATE = 3; // TSifOperationPhase::EUpgrading |
35 public static final int OP_UPDATE = 3; |
39 |
36 |
40 /** Indicates installation or uninstallation without |
37 /** Indicates installaion or uninstallation without |
41 specific suboperation. */ |
38 specific suboperation. */ |
42 public static final int SUB_OP_NO = 1; // TSifOperationSubPhase::ENoSubPhase |
39 public static final int SUB_OP_NO = 1; |
43 /** OCSP phase during installation. */ |
40 /** OCSP phase during installation. */ |
44 public static final int SUB_OP_OCSP = 2; // TSifOperationSubPhase::EOCSPCheck |
41 public static final int SUB_OP_OCSP = 2; |
45 /** Download phase during installation. */ |
42 /** Download phase during installation. */ |
46 public static final int SUB_OP_DOWNLOAD = 3; // TSifOperationSubPhase::EDownload |
43 public static final int SUB_OP_DOWNLOAD = 3; |
47 /** Maximum progress notification value. */ |
|
48 private static final int MAX_PROGRESS = 100; |
|
49 |
44 |
50 /** Operation being notified. */ |
45 /** Operation being notified. */ |
51 private int iOperation = 0; |
46 private int iOperation = 0; |
52 /** Suboperation during installation. */ |
|
53 private int iSubOperation = 0; |
|
54 /** Global component id for the application. */ |
47 /** Global component id for the application. */ |
55 private String iGlobalComponentId = null; |
48 private String iGlobalComponentId = null; |
56 /** Component name (i.e. suite name). */ |
49 /** Component name (i.e. suite name). */ |
57 private String iComponentName = null; |
50 private String iComponentName = null; |
58 /** Application names. */ |
51 /** Application names. */ |
67 private String iComponentIcon = null; |
60 private String iComponentIcon = null; |
68 |
61 |
69 /** Sending progress notifications is only allowed between start |
62 /** Sending progress notifications is only allowed between start |
70 * and end notifications. */ |
63 * and end notifications. */ |
71 private boolean iNotifyProgressAllowed = false; |
64 private boolean iNotifyProgressAllowed = false; |
72 /** |
65 |
73 * Value of the last progress notification that has been sent with |
66 /** Native object handle. */ |
74 * SUB_OP_NO suboperation. |
|
75 */ |
|
76 private int iLastProgressSent = 0; |
|
77 /** Current value of the last progress notification that has been sent. */ |
|
78 private int iCurrentValue = 0; |
|
79 /** total value of the last progress notification that has been sent. */ |
|
80 private int iTotalValue = 0; |
|
81 |
|
82 /** Native notifier object handle. */ |
|
83 private int iHandle = 0; |
67 private int iHandle = 0; |
84 /** Native indicator object handle. */ |
|
85 private int iIndicatorHandle = 0; |
|
86 /** InstallerUi handle. */ |
|
87 private InstallerUi iInstallerUi = null; |
|
88 /** Provider for indicator status events. */ |
|
89 private PropertyProvider iIndicatorStatusProvider = null; |
|
90 /** Indicator state. */ |
|
91 private int iIndicatorState = -1; |
|
92 |
68 |
93 /*** ----------------------------- PUBLIC ------------------------------ */ |
69 /*** ----------------------------- PUBLIC ------------------------------ */ |
94 |
70 |
95 /** |
71 /** |
96 * Constructor. |
72 * Constructor. |
97 */ |
73 */ |
98 public SifNotifier() |
74 public SifNotifier() |
99 { |
75 { |
100 init(); |
76 init(); |
101 } |
|
102 |
|
103 /** |
|
104 * Set InstallerUi used when handling indicator. |
|
105 */ |
|
106 public void setInstallerUi(InstallerUi aInstallerUi) |
|
107 { |
|
108 iInstallerUi = aInstallerUi; |
|
109 } |
|
110 |
|
111 /** |
|
112 * Activates and updates indicator which displays installation |
|
113 * progress to user while installer UI is hidden. The notifyStart |
|
114 * and notifyProgress methods must be called at least once before |
|
115 * calling this method. |
|
116 */ |
|
117 public void activateIndicator() |
|
118 { |
|
119 if (iInstallerUi == null) |
|
120 { |
|
121 return; |
|
122 } |
|
123 |
|
124 if (iIndicatorHandle == 0) |
|
125 { |
|
126 int ret = _initIndicator(); |
|
127 if (ret < 0) |
|
128 { |
|
129 Log.logError( |
|
130 "Initializing SifNotifier indicator failed with code " + |
|
131 ret); |
|
132 } |
|
133 else |
|
134 { |
|
135 Log.log("SifNotifier indicator created"); |
|
136 } |
|
137 iIndicatorHandle = ret; |
|
138 } |
|
139 |
|
140 if (iIndicatorHandle == 0) |
|
141 { |
|
142 return; |
|
143 } |
|
144 |
|
145 int phase = 0; |
|
146 switch (iSubOperation) |
|
147 { |
|
148 case SUB_OP_OCSP: phase = 2; break; // TInstallingPhase::ECheckingCerts |
|
149 case SUB_OP_DOWNLOAD: phase = 1; break; // TInstallingPhase::EDownloading |
|
150 default: phase = 0; // TInstallingPhase::EInstalling |
|
151 } |
|
152 int progress = (iTotalValue == 0? 0: iCurrentValue*100/iTotalValue); |
|
153 updateIndicator(iComponentName, phase, progress); |
|
154 |
|
155 if (iIndicatorStatusProvider == null) |
|
156 { |
|
157 // Create PropertyListener which listens indicator status events |
|
158 // and unhides UI when necessary. |
|
159 final int indicatorCategory = 0x20022FC5; // sifuiinstallindicatorplugin |
|
160 final int indicatorKey = 0x2002E690; // /SifUiInstallIndicator/Status |
|
161 iIndicatorStatusProvider = new PropertyProvider(); |
|
162 iIndicatorStatusProvider.subscribe( |
|
163 indicatorCategory, indicatorKey, new PropertyListener() |
|
164 { |
|
165 public void valueChanged(int aCategory, int aKey, int aValue) |
|
166 { |
|
167 Log.log("SifNotifier indicator status " + aValue + |
|
168 " (category=" + aCategory + ", key=" + aKey + ")"); |
|
169 iIndicatorState = aValue; |
|
170 if (iIndicatorState == 0) |
|
171 { |
|
172 // Indicator has been closed, unhide the UI. |
|
173 iInstallerUi.hide(false); |
|
174 } |
|
175 } |
|
176 }); |
|
177 Log.log("SifNotifier indicator status provider subscribed"); |
|
178 } |
|
179 } |
|
180 |
|
181 /** |
|
182 * Updates indicator which displays installation progress to user |
|
183 * while installer UI is hidden. The activateindicator method must |
|
184 * be called before calling this method. |
|
185 */ |
|
186 public void updateIndicator(String aName, int aPhase, int aProgress) |
|
187 { |
|
188 if (iInstallerUi == null || iIndicatorHandle == 0) |
|
189 { |
|
190 return; |
|
191 } |
|
192 |
|
193 final String name = aName; |
|
194 final int phase = aPhase; |
|
195 final int progress = aProgress; |
|
196 iInstallerUi.syncExec(new Runnable() |
|
197 { |
|
198 // Indicator must be updated from UI thread. |
|
199 public void run() |
|
200 { |
|
201 int ret = _updateIndicator( |
|
202 iIndicatorHandle, name, phase, progress); |
|
203 if (ret < 0) |
|
204 { |
|
205 Log.logError( |
|
206 "Updating SifNotifier indicator failed with code " + |
|
207 ret); |
|
208 } |
|
209 else |
|
210 { |
|
211 Log.log("SifNotifier indicator updated: " + name + |
|
212 ", " + phase + ", " + progress + "%"); |
|
213 } |
|
214 } |
|
215 }); |
|
216 } |
|
217 |
|
218 /** |
|
219 * Deactivates indicator which displays installation |
|
220 * progress to user while installer UI is hidden. |
|
221 */ |
|
222 public void deactivateIndicator() |
|
223 { |
|
224 if (iIndicatorStatusProvider != null) |
|
225 { |
|
226 iIndicatorStatusProvider.unsubscribe(); |
|
227 iIndicatorStatusProvider = null; |
|
228 Log.log("SifNotifier indicator status provider unsubscribed"); |
|
229 } |
|
230 |
|
231 if (iInstallerUi == null) |
|
232 { |
|
233 return; |
|
234 } |
|
235 |
|
236 iInstallerUi.syncExec(new Runnable() |
|
237 { |
|
238 // Indicator must be deactivated from UI thread. |
|
239 public void run() |
|
240 { |
|
241 if (iIndicatorHandle == 0) |
|
242 { |
|
243 return; |
|
244 } |
|
245 int ret = _destroyIndicator(iIndicatorHandle, iIndicatorState); |
|
246 if (ret < 0) |
|
247 { |
|
248 Log.logError( |
|
249 "Destroying SifNotifier indicator failed with code " + |
|
250 ret); |
|
251 } |
|
252 else |
|
253 { |
|
254 Log.log("SifNotifier indicator destroyed"); |
|
255 } |
|
256 iIndicatorHandle = 0; |
|
257 } |
|
258 }); |
|
259 } |
77 } |
260 |
78 |
261 /** |
79 /** |
262 * Returns true if SIF progress notifications are enabled, false otherwise. |
80 * Returns true if SIF progress notifications are enabled, false otherwise. |
263 */ |
81 */ |
283 iApplicationIcons = aApplicationIcons; |
101 iApplicationIcons = aApplicationIcons; |
284 iComponentSize = aComponentSize; |
102 iComponentSize = aComponentSize; |
285 iIconDir = aIconDir; |
103 iIconDir = aIconDir; |
286 iComponentIcon = aComponentIcon; |
104 iComponentIcon = aComponentIcon; |
287 |
105 |
288 checkHandle(); |
106 if (iHandle == 0) |
|
107 { |
|
108 InstallerException.internalError( |
|
109 "SifNotifier.notifyStart: notifier has not been initialized"); |
|
110 } |
289 int ret = _notifyStart( |
111 int ret = _notifyStart( |
290 iHandle, aOperation, aGlobalComponentId, aComponentName, |
112 iHandle, aGlobalComponentId, aComponentName, |
291 aApplicationNames, aApplicationIcons, |
113 aApplicationNames, aApplicationIcons, |
292 aComponentSize, aIconDir, aComponentIcon); |
114 aComponentSize, aIconDir, aComponentIcon); |
293 if (ret < 0) |
115 if (ret < 0) |
294 { |
116 { |
295 Log.log("Notifying SIF start failed with code " + ret + |
117 Log.logError("Notifying SIF start failed with code " + ret + |
296 ", " + getInfoString()); |
118 ", " + getInfoString()); |
297 InstallerException.internalError( |
119 InstallerException.internalError( |
298 "Notifying SIF start failed with code " + ret); |
120 "Notifying SIF start failed with code " + ret); |
299 } |
|
300 else |
|
301 { |
|
302 Log.log("SifNotifier.notifyStart: " + getInfoString()); |
|
303 } |
121 } |
304 iNotifyProgressAllowed = true; |
122 iNotifyProgressAllowed = true; |
305 } |
123 } |
306 |
124 |
307 /** |
125 /** |
310 * @throws InstallerException in case an error occurs |
128 * @throws InstallerException in case an error occurs |
311 */ |
129 */ |
312 public void notifyEnd( |
130 public void notifyEnd( |
313 int aErrCategory, int aErrCode, String aErrMsg, String aErrMsgDetails) |
131 int aErrCategory, int aErrCode, String aErrMsg, String aErrMsgDetails) |
314 { |
132 { |
315 checkHandle(); |
133 if (iHandle == 0) |
316 if (aErrCategory == 0 && iLastProgressSent < MAX_PROGRESS) |
134 { |
317 { |
135 InstallerException.internalError( |
318 // Before sending end notification, update progress to max if |
136 "SifNotifier.notifyEnd: notifier has not been initialized"); |
319 // operation was successful and max progress notification has |
137 } |
320 // not yet been sent. |
|
321 notifyProgress(SUB_OP_NO, MAX_PROGRESS, MAX_PROGRESS); |
|
322 } |
|
323 // No more progress notifications allowed. |
|
324 iNotifyProgressAllowed = false; |
138 iNotifyProgressAllowed = false; |
325 int ret = _notifyEnd( |
139 int ret = _notifyEnd( |
326 iHandle, iGlobalComponentId, aErrCategory, aErrCode, |
140 iHandle, iGlobalComponentId, aErrCategory, aErrCode, |
327 aErrMsg, aErrMsgDetails); |
141 aErrMsg, aErrMsgDetails); |
328 String logMsg = |
142 if (ret < 0) |
329 "ErrCategory: " + aErrCategory + |
143 { |
330 ", ErrCode: " + aErrCode + |
144 Log.logError("Notifying SIF end failed with code " + ret + |
331 ", ErrMsg: " + aErrMsg + |
145 ", " + getInfoString() + |
332 ", ErrMsgDetails: " + aErrMsgDetails; |
146 ", ErrCategory: " + aErrCategory + |
333 if (ret < 0) |
147 ", ErrCode: " + aErrCode + |
334 { |
148 ", ErrMsg: " + aErrMsg + |
335 Log.log("Notifying SIF end failed with code " + ret + |
149 ", ErrMsgDetails: " + aErrMsgDetails); |
336 ", " + getInfoString() + ", " + logMsg); |
|
337 InstallerException.internalError( |
150 InstallerException.internalError( |
338 "Notifying SIF end failed with code " + ret); |
151 "Notifying SIF end failed with code " + ret); |
339 } |
152 } |
340 else |
|
341 { |
|
342 Log.log("SifNotifier.notifyEnd: " + logMsg); |
|
343 } |
|
344 } |
153 } |
345 |
154 |
346 /** |
155 /** |
347 * Notifies SIF about installation or uninstallation progress. |
156 * Notifies SIF about installation or uninstallation progress. |
348 * |
157 * |
352 { |
161 { |
353 if (!iNotifyProgressAllowed) |
162 if (!iNotifyProgressAllowed) |
354 { |
163 { |
355 return; |
164 return; |
356 } |
165 } |
357 |
166 if (iHandle == 0) |
358 iSubOperation = aSubOperation; |
167 { |
359 iCurrentValue = aCurrent; |
168 InstallerException.internalError( |
360 iTotalValue = aTotal; |
169 "SifNotifier.notifyProgress: notifier has not been initialized"); |
361 if (iIndicatorHandle != 0) |
|
362 { |
|
363 // Call activateIndicator so that indicator gets updated. |
|
364 activateIndicator(); |
|
365 } |
|
366 |
|
367 checkHandle(); |
|
368 if (aSubOperation == SUB_OP_NO) |
|
369 { |
|
370 iLastProgressSent = aCurrent; |
|
371 } |
170 } |
372 int ret = _notifyProgress( |
171 int ret = _notifyProgress( |
373 iHandle, iGlobalComponentId, iOperation, aSubOperation, |
172 iHandle, iGlobalComponentId, iOperation, aSubOperation, |
374 aCurrent, aTotal); |
173 aCurrent, aTotal); |
375 String logMsg = |
174 if (ret < 0) |
376 "SubOp: " + aSubOperation + |
175 { |
377 ", Current: " + aCurrent + |
176 Log.logError("Notifying SIF progress failed with code " + ret + |
378 ", Total: " + aTotal; |
177 ", " + getInfoString() + |
379 if (ret < 0) |
178 ", SubOp: " + aSubOperation + |
380 { |
179 ", Current: " + aCurrent + |
381 Log.log("Notifying SIF progress failed with code " + ret + |
180 ", Total: " + aTotal); |
382 ", " + getInfoString() + ", " + logMsg); |
|
383 InstallerException.internalError( |
181 InstallerException.internalError( |
384 "Notifying SIF progress failed with code " + ret); |
182 "Notifying SIF progress failed with code " + ret); |
385 } |
|
386 else |
|
387 { |
|
388 Log.log("SifNotifier.notifyProgress: " + logMsg); |
|
389 } |
183 } |
390 } |
184 } |
391 |
185 |
392 /** |
186 /** |
393 * Destroys SifNotifier. This method releawse native resources and |
187 * Destroys SifNotifier. This method releawse native resources and |
426 if (ret < 0) |
219 if (ret < 0) |
427 { |
220 { |
428 InstallerException.internalError( |
221 InstallerException.internalError( |
429 "Initializing SifNotifier failed with code " + ret); |
222 "Initializing SifNotifier failed with code " + ret); |
430 } |
223 } |
431 else |
|
432 { |
|
433 Log.log("SifNotifier created"); |
|
434 } |
|
435 iHandle = ret; |
224 iHandle = ret; |
436 } |
225 } |
437 |
226 |
438 /*** ----------------------------- PRIVATE ---------------------------- */ |
227 /*** ----------------------------- PRIVATE ---------------------------- */ |
439 |
|
440 /** |
|
441 * Checks if notifier instance has been initialized. |
|
442 * @throws InstallerException if notifier has not been initialized |
|
443 */ |
|
444 private void checkHandle() |
|
445 { |
|
446 if (iHandle == 0) |
|
447 { |
|
448 InstallerException.internalError( |
|
449 "SifNotifier.destroy: notifier has not been initialized"); |
|
450 } |
|
451 } |
|
452 |
228 |
453 /** |
229 /** |
454 * Returns notification info string used in logging. |
230 * Returns notification info string used in logging. |
455 */ |
231 */ |
456 private String getInfoString() |
232 private String getInfoString() |
457 { |
233 { |
458 StringBuffer buf = new StringBuffer(); |
234 StringBuffer buf = new StringBuffer(); |
459 buf.append("Operation: ").append(iOperation); |
235 buf.append("Operation: ").append(iOperation); |
460 buf.append(", GlobalComponentId: ").append(iGlobalComponentId); |
236 buf.append(", GlobalComponentId: ").append(iGlobalComponentId); |
461 buf.append(", ComponentName: ").append(iComponentName); |
237 buf.append(", ComponentName: ").append(iComponentName); |
462 if (iApplicationNames != null) |
238 for (int i = 0; i < iApplicationNames.length; i++) |
463 { |
239 { |
464 for (int i = 0; i < iApplicationNames.length; i++) |
240 buf.append(", ApplicationName: ").append(iApplicationNames[i]); |
465 { |
|
466 buf.append(", ApplicationName[").append(i).append("]: ") |
|
467 .append(iApplicationNames[i]); |
|
468 } |
|
469 } |
|
470 if (iApplicationIcons != null) |
|
471 { |
|
472 for (int i = 0; i < iApplicationIcons.length; i++) |
|
473 { |
|
474 buf.append(", ApplicationIcon[").append(i).append("]: ") |
|
475 .append(iApplicationIcons[i]); |
|
476 } |
|
477 } |
241 } |
478 buf.append(", ComponentSize: ").append(iComponentSize); |
242 buf.append(", ComponentSize: ").append(iComponentSize); |
479 if (iIconDir != null) |
|
480 { |
|
481 buf.append(", IconDir: ").append(iIconDir); |
|
482 } |
|
483 if (iComponentIcon != null) |
|
484 { |
|
485 buf.append(", ComponentIcon: ").append(iComponentIcon); |
|
486 } |
|
487 return buf.toString(); |
243 return buf.toString(); |
488 } |
244 } |
489 |
245 |
490 /*** ----------------------------- NATIVE ----------------------------- */ |
246 /*** ----------------------------- NATIVE ----------------------------- */ |
491 |
247 |
508 * @param aComponentIcon |
263 * @param aComponentIcon |
509 * @return Symbian error code (negative number) if operation fails, |
264 * @return Symbian error code (negative number) if operation fails, |
510 * otherwise 0 |
265 * otherwise 0 |
511 */ |
266 */ |
512 private static native int _notifyStart( |
267 private static native int _notifyStart( |
513 int aHandle, int aOperation, String aGlobalComponentId, |
268 int aHandle, String aGlobalComponentId, String aComponentName, |
514 String aComponentName, String[] aApplicationNames, |
269 String[] aApplicationNames, String[] aApplicationIcons, |
515 String[] aApplicationIcons, int aComponentSize, |
270 int aComponentSize, String aIconDir, String aComponentIcon); |
516 String aIconDir, String aComponentIcon); |
|
517 |
271 |
518 /** |
272 /** |
519 * Notifies SIF about installation/uinstallation completion. |
273 * Notifies SIF about installation/uinstallation completion. |
520 * |
274 * |
521 * @param aHandle |
275 * @param aHandle |
565 * @return Symbian error code (negative number) if operation fails, |
319 * @return Symbian error code (negative number) if operation fails, |
566 * otherwise 0 |
320 * otherwise 0 |
567 */ |
321 */ |
568 private static native int _destroy(int aHandle); |
322 private static native int _destroy(int aHandle); |
569 |
323 |
570 /** |
|
571 * Initializes SifNotifier indicator. |
|
572 * |
|
573 * @return Symbian error code (negative number) if operation fails, |
|
574 * otherwise handle to the native side object |
|
575 */ |
|
576 private static native int _initIndicator(); |
|
577 |
|
578 /** |
|
579 * Updates SifNotifier indicator. |
|
580 * |
|
581 * @param aHandle handle to indicator object |
|
582 * @param aName application name |
|
583 * @param aPhase operation phase |
|
584 * @param aProgress progress in percentage |
|
585 * @return Symbian error code (negative number) if operation fails, |
|
586 * otherwise handle to the native side object |
|
587 */ |
|
588 private static native int _updateIndicator( |
|
589 int aHandle, String aName, int aPhase, int aProgress); |
|
590 |
|
591 /** |
|
592 * Destroys SifNotifier indicator. |
|
593 * |
|
594 * @param aHandle handle to indicator object |
|
595 * @param aState indicator state |
|
596 * @return Symbian error code (negative number) if operation fails, |
|
597 * otherwise 0 |
|
598 */ |
|
599 private static native int _destroyIndicator(int aHandle, int aState); |
|
600 |
|
601 } |
324 } |