|
1 /* |
|
2 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: The JNI code for Java Installer component |
|
15 * ApplicationRegistrator. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 #include <apaid.h> |
|
21 #include <f32file.h> |
|
22 #include <apgcli.h> |
|
23 #include <utf.h> |
|
24 #include <s32mem.h> |
|
25 #include <bautils.h> |
|
26 #include <w32std.h> |
|
27 #include <apgtask.h> |
|
28 #include <apacmdln.h> |
|
29 #include <centralrepository.h> |
|
30 #include <AknUtils.h> |
|
31 #include <hal.h> |
|
32 |
|
33 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
34 #include <apgicnfl.h> |
|
35 #else |
|
36 #include <apgicnflpartner.h> |
|
37 #endif |
|
38 |
|
39 |
|
40 |
|
41 // JNI header must be included before iconconverter.h. Latter includes some |
|
42 // other header file which defines WIN32 macro, causing incorrect definitions |
|
43 // to be taken from jniport.h when WINSCW compilation is made. |
|
44 // This error situation can be seen from linker warnings which complain |
|
45 // about not frozen exports for JNI methods. |
|
46 #include "com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator.h" |
|
47 #include "iconconverter.h" |
|
48 #include "javacommonutils.h" |
|
49 #include "logger.h" |
|
50 |
|
51 // NAMESPACE DECLARATION |
|
52 using namespace java; |
|
53 |
|
54 /** |
|
55 * MIDP Stub SIS file UID. The application type Uid for MIDlets in S60 |
|
56 */ |
|
57 const TUid KMidletApplicationTypeUid = { 0x10210E26 }; |
|
58 |
|
59 /** |
|
60 * Symbian file path separator |
|
61 */ |
|
62 _LIT(KPathSeperator, "\\"); |
|
63 |
|
64 /** |
|
65 * Postfix for the fake application name generated only to make AppArc happy |
|
66 */ |
|
67 _LIT(KAppPostfix, ".fakeapp"); |
|
68 |
|
69 // ------------------------ |
|
70 |
|
71 /** |
|
72 * Internal wrapper method that is used to make TRAPping the leaves in the |
|
73 * native Symbian code easier. |
|
74 * Used from JNI method ...1registerApplication() |
|
75 * @see Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1registerApplication |
|
76 */ |
|
77 jint registerApplicationL(JNIEnv *aEnv, jclass aClass, jint aSessionHandle, |
|
78 jint aUid, HBufC16 *aGroupName, HBufC16 *aMIDletName, HBufC16 *aTargetDrive, |
|
79 HBufC16 *aIconFileName, HBufC16 *aJarFileName, jboolean aHidden, |
|
80 jboolean aBackground); |
|
81 |
|
82 /** |
|
83 * Internal helper method for checking whether Application Shell is already running |
|
84 * Used JNI method ...1startAppShellUi |
|
85 * |
|
86 * @return ETrue if AppShell is running |
|
87 */ |
|
88 TBool isAppShellUiRunning(); |
|
89 |
|
90 /** |
|
91 * Internal helper method for checking whether this code is executing in |
|
92 * a device that has correctly working version of |
|
93 * RApaLsSession::ForceCommitNonNativeApplicationsUpdatesL() |
|
94 * |
|
95 * @return ETrue if force commit works well |
|
96 */ |
|
97 TBool isForceCommitSupported(); |
|
98 |
|
99 /** |
|
100 * Internal helper method for starting menu application |
|
101 * |
|
102 * @return KErrNone or Symbian error code |
|
103 */ |
|
104 TInt startAppShellApplicationL(); |
|
105 |
|
106 // -------------------------- |
|
107 |
|
108 /** |
|
109 * Starts native application registration session. |
|
110 * |
|
111 * @return native session handle or Symbian error code (negative number) |
|
112 */ |
|
113 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1startSession |
|
114 (JNIEnv *, jclass) |
|
115 { |
|
116 TInt err; |
|
117 RApaLsSession *pApaSession = new RApaLsSession; |
|
118 |
|
119 if (NULL == pApaSession) |
|
120 { |
|
121 // Could not create session |
|
122 return KErrGeneral; |
|
123 } |
|
124 |
|
125 err = pApaSession->Connect(); |
|
126 if (KErrNone != err) |
|
127 { |
|
128 // Cannot connect to AppArc server |
|
129 return err; |
|
130 } |
|
131 |
|
132 #if 1 |
|
133 //#ifndef RD_JAVA_USIF_APP_REG |
|
134 // Delete any pending (un)registrations (possible if |
|
135 // e.g. device rebooted before commit). |
|
136 // This call does nothing if there is no pending registrations. |
|
137 // Ignore errors. |
|
138 (void)pApaSession->RollbackNonNativeApplicationsUpdates(); |
|
139 |
|
140 // Prepare for Java application registrations / unregistrations |
|
141 TRAP(err, pApaSession->PrepareNonNativeApplicationsUpdatesL()); |
|
142 if (KErrNone != err) |
|
143 { |
|
144 // Close session and return error |
|
145 pApaSession->Close(); |
|
146 return err; |
|
147 } |
|
148 #endif // RD_JAVA_USIF_APP_REG |
|
149 |
|
150 // Return handle to session. Utilize the fact that in Symbian |
|
151 // all pointer addresses are MOD 4 so the last 2 bits are 0 |
|
152 // and can be shifted out. This way the returned handle is |
|
153 // always positive whereas Symbian error codes are always negative. |
|
154 return reinterpret_cast<TUint>(pApaSession)>>2; |
|
155 } |
|
156 |
|
157 |
|
158 /** |
|
159 * Registers Java Application to S60 AppArc |
|
160 * |
|
161 * @param[in] aSessionHandle |
|
162 * @param[in] aUid The Uid of the application. |
|
163 * @param[in] aGroupName Max group name len is 16 in AppArc |
|
164 * @param[in] aMIDletName |
|
165 * @param[in] aTargetDrive Must be "C:", "E:", ..., "J:" |
|
166 * @param[in] aIconFileName The name of the icon |
|
167 * @param[in] aJarFileName The full path name of the jar file |
|
168 * @param[in] aHidden |
|
169 * @param[in] aBackground |
|
170 * @return 0 if registration succeeded or Symbian error code |
|
171 */ |
|
172 #if 0 |
|
173 //#ifdef RD_JAVA_USIF_APP_REG |
|
174 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1registerApplication |
|
175 (JNIEnv */*aEnv*/, jclass /*aClass*/, jint /*aSessionHandle*/, jint /*aUid*/, jstring /*aGroupName*/, |
|
176 jstring /*aMIDletName*/, jstring /*aTargetDrive*/, jstring /*aIconFileName*/, |
|
177 jstring /*aJarFileName*/, jboolean /*aHidden*/, jboolean /*aBackground*/) |
|
178 { |
|
179 return KErrNone; |
|
180 } |
|
181 #else |
|
182 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1registerApplication |
|
183 (JNIEnv *aEnv, jclass aClass, jint aSessionHandle, jint aUid, jstring aGroupName, |
|
184 jstring aMIDletName, jstring aTargetDrive, jstring aIconFileName, |
|
185 jstring aJarFileName, jboolean aHidden, jboolean aBackground) |
|
186 { |
|
187 TInt err(KErrNone); |
|
188 TBool fStayInLoop(EFalse); |
|
189 |
|
190 HBufC16 *unicodeIconFileName(NULL); |
|
191 HBufC16 *unicodeGroupName(NULL); |
|
192 HBufC16 *unicodeMIDletName(NULL); |
|
193 HBufC16 *unicodeTargetDrive(NULL); |
|
194 HBufC16 *unicodeJarFileName(NULL); |
|
195 |
|
196 // create loop that is executed only once to make error handling easier |
|
197 do |
|
198 { |
|
199 // Copy the unicode characters in jstrings to Symbian buffers so that |
|
200 // they can be used in S60 code |
|
201 const jchar *iconFileName = aEnv->GetStringChars(aIconFileName, 0); |
|
202 if (NULL == iconFileName) |
|
203 { |
|
204 ELOG( |
|
205 EJavaInstaller, |
|
206 "Cannot register application, getting icon file name as unicode failed in JNI"); |
|
207 err = KErrArgument; |
|
208 break; |
|
209 } |
|
210 unicodeIconFileName = HBufC16::New(aEnv->GetStringLength(aIconFileName) + 1); |
|
211 if (NULL == unicodeIconFileName) |
|
212 { |
|
213 err = KErrNoMemory; |
|
214 break; |
|
215 } |
|
216 *unicodeIconFileName = iconFileName; |
|
217 aEnv->ReleaseStringChars(aIconFileName, iconFileName); |
|
218 |
|
219 const jchar *groupName = aEnv->GetStringChars(aGroupName, 0); |
|
220 if (NULL == groupName) |
|
221 { |
|
222 ELOG( |
|
223 EJavaInstaller, |
|
224 "Cannot register application, getting group name as unicode failed in JNI"); |
|
225 err = KErrArgument; |
|
226 break; |
|
227 } |
|
228 unicodeGroupName = HBufC16::New(aEnv->GetStringLength(aGroupName) + 1); |
|
229 if (NULL == unicodeGroupName) |
|
230 { |
|
231 err = KErrNoMemory; |
|
232 break; |
|
233 } |
|
234 *unicodeGroupName = groupName; |
|
235 aEnv->ReleaseStringChars(aGroupName, groupName); |
|
236 |
|
237 const jchar *midletName = aEnv->GetStringChars(aMIDletName, 0); |
|
238 if (NULL == midletName) |
|
239 { |
|
240 ELOG( |
|
241 EJavaInstaller, |
|
242 "Cannot register application, getting midlet name as unicode failed in JNI"); |
|
243 err = KErrArgument; |
|
244 break; |
|
245 } |
|
246 unicodeMIDletName = HBufC16::New(aEnv->GetStringLength(aMIDletName) + 1); |
|
247 if (NULL == unicodeMIDletName) |
|
248 { |
|
249 err = KErrNoMemory; |
|
250 break; |
|
251 } |
|
252 *unicodeMIDletName = midletName; |
|
253 aEnv->ReleaseStringChars(aMIDletName, midletName); |
|
254 |
|
255 const jchar *targetDrive = aEnv->GetStringChars(aTargetDrive, 0); |
|
256 if (NULL == targetDrive) |
|
257 { |
|
258 ELOG( |
|
259 EJavaInstaller, |
|
260 "Cannot register application, getting target drive as unicode failed in JNI"); |
|
261 err = KErrArgument; |
|
262 break; |
|
263 } |
|
264 unicodeTargetDrive = HBufC16::New(aEnv->GetStringLength(aTargetDrive) + 1); |
|
265 if (NULL == unicodeTargetDrive) |
|
266 { |
|
267 err = KErrNoMemory; |
|
268 break; |
|
269 } |
|
270 *unicodeTargetDrive = targetDrive; |
|
271 aEnv->ReleaseStringChars(aTargetDrive, targetDrive); |
|
272 |
|
273 const jchar *jarFileName = aEnv->GetStringChars(aJarFileName, 0); |
|
274 if (NULL == jarFileName) |
|
275 { |
|
276 ELOG( |
|
277 EJavaInstaller, |
|
278 "Cannot register application, getting jar file name as unicode failed in JNI"); |
|
279 err = KErrArgument; |
|
280 break; |
|
281 } |
|
282 unicodeJarFileName = HBufC16::New(aEnv->GetStringLength(aJarFileName) + 1); |
|
283 if (NULL == unicodeTargetDrive) |
|
284 { |
|
285 err = KErrNoMemory; |
|
286 break; |
|
287 } |
|
288 *unicodeJarFileName = jarFileName; |
|
289 aEnv->ReleaseStringChars(aJarFileName, jarFileName); |
|
290 } |
|
291 while (fStayInLoop); |
|
292 |
|
293 if (KErrNone != err) |
|
294 { |
|
295 delete unicodeIconFileName; |
|
296 delete unicodeGroupName; |
|
297 delete unicodeMIDletName; |
|
298 delete unicodeTargetDrive; |
|
299 delete unicodeJarFileName; |
|
300 |
|
301 return err; |
|
302 } |
|
303 |
|
304 // Call the actual register method inside TRAP harness |
|
305 TInt ret = KErrNone; |
|
306 TRAP(err, |
|
307 ret = registerApplicationL( |
|
308 aEnv, aClass, aSessionHandle, aUid, unicodeGroupName, |
|
309 unicodeMIDletName, unicodeTargetDrive, unicodeIconFileName, |
|
310 unicodeJarFileName, aHidden, aBackground)); |
|
311 |
|
312 LOG1WSTR( |
|
313 EJavaInstaller, |
|
314 EInfo, |
|
315 "Registering application, midlet name (%s)", |
|
316 (wchar_t *)(unicodeMIDletName->Des().PtrZ())); |
|
317 LOG1WSTR( |
|
318 EJavaInstaller, |
|
319 EInfo, |
|
320 "Registering application, icon file name (%s)", |
|
321 (wchar_t *)(unicodeIconFileName->Des().PtrZ())); |
|
322 |
|
323 if (KErrNone != err) |
|
324 { |
|
325 ELOG1(EJavaInstaller, |
|
326 "Cannot register application, err code is %d ", |
|
327 err); |
|
328 } |
|
329 if (KErrNone != ret) |
|
330 { |
|
331 // error even though the code did not leave |
|
332 err = ret; |
|
333 |
|
334 ELOG1(EJavaInstaller, |
|
335 "Cannot register application, non-leaving error %d", |
|
336 ret); |
|
337 } |
|
338 |
|
339 // Free all Symbian buffers containing copies of jstring data |
|
340 delete unicodeIconFileName; |
|
341 delete unicodeGroupName; |
|
342 delete unicodeMIDletName; |
|
343 delete unicodeTargetDrive; |
|
344 delete unicodeJarFileName; |
|
345 |
|
346 return err; |
|
347 } |
|
348 #endif // RD_JAVA_USIF_APP_REG |
|
349 |
|
350 |
|
351 /** |
|
352 * See JNI method __1registerApplication. |
|
353 * This method makes all calls that may leave (the actual registering) |
|
354 */ |
|
355 jint registerApplicationL( |
|
356 JNIEnv *, jclass, jint aSessionHandle, jint aUid, HBufC16 *aGroupName, |
|
357 HBufC16 *aMIDletName, HBufC16 *aTargetDrive, HBufC16 *aIconFileName, |
|
358 HBufC16 * /*aJarFileName*/, jboolean aHidden, jboolean aBackground) |
|
359 { |
|
360 RFs fileServ; |
|
361 RFile appArcIcon; |
|
362 TUid midletUid; |
|
363 TInt err; |
|
364 TInt numberOfIcons = 1; // Conversion results always one icon in mbm. |
|
365 // Also default mbm has one icon. |
|
366 |
|
367 midletUid.iUid = aUid; |
|
368 |
|
369 // AppArc requires open RFile handle |
|
370 err = fileServ.Connect(); |
|
371 if (KErrNone != err) |
|
372 { |
|
373 // Will not register application without icon |
|
374 ELOG1(EJavaInstaller, |
|
375 "Cannot open RFs connection, err code is %d ", err); |
|
376 return err; |
|
377 } |
|
378 CleanupClosePushL(fileServ); |
|
379 |
|
380 // The session must be shared so that AppArc can |
|
381 // use the same icon file handle |
|
382 err = fileServ.ShareProtected(); |
|
383 if (KErrNone != err) |
|
384 { |
|
385 ELOG1(EJavaInstaller, |
|
386 "Cannot share file server session, err code is %d ", err); |
|
387 User::Leave(err); |
|
388 } |
|
389 |
|
390 // Default icon has been copied from ROM, so the icon may have ReadOnly |
|
391 // flag on. Must remove that flag. |
|
392 fileServ.SetAtt(*aIconFileName, 0, KEntryAttReadOnly); |
|
393 |
|
394 // open the icon |
|
395 err = appArcIcon.Open( |
|
396 fileServ, |
|
397 *aIconFileName, |
|
398 (EFileShareReadersOrWriters | EFileWrite)); |
|
399 if (KErrNone != err) |
|
400 { |
|
401 ELOG1(EJavaInstaller, |
|
402 "registerApplicationL: Cannot open icon, err code is %d ", err); |
|
403 User::Leave(err); |
|
404 } |
|
405 |
|
406 // Now icon is open |
|
407 CleanupClosePushL(appArcIcon); |
|
408 |
|
409 // Generate the executable name name using the same |
|
410 // algorithm as used earlier in S60 platform |
|
411 // in case some external S60 application |
|
412 // needs to parse the Uid from the executable name. |
|
413 TFileName appName; |
|
414 appName.Copy(KPathSeperator); |
|
415 appName.AppendNum(midletUid.iUid); |
|
416 appName.Append(KAppPostfix); |
|
417 |
|
418 // Create writer needed for actual registration |
|
419 CApaRegistrationResourceFileWriter *writer = NULL; |
|
420 writer = CApaRegistrationResourceFileWriter::NewL( |
|
421 midletUid, |
|
422 appName, |
|
423 TApaAppCapability::ENonNative); |
|
424 CleanupStack::PushL(writer); |
|
425 |
|
426 writer->SetGroupNameL(*aGroupName); |
|
427 if (aBackground) |
|
428 { |
|
429 // By default this is false, so the value needs to be set |
|
430 // only if it is true |
|
431 writer->SetLaunchInBackgroundL(ETrue); |
|
432 } |
|
433 if (aHidden) |
|
434 { |
|
435 // By default this is false, so the value needs to be set |
|
436 // only if it is true |
|
437 writer->SetAppIsHiddenL(ETrue); |
|
438 } |
|
439 |
|
440 // write application Uid to opaque data (needed by MIDlet launcher) |
|
441 TBuf8<4> opaqueData; // opaque data will contain one signed 32-bit int |
|
442 RDesWriteStream writeStream(opaqueData); |
|
443 writeStream.WriteInt32L(midletUid.iUid); |
|
444 writeStream.CommitL(); |
|
445 writer->SetOpaqueDataL(opaqueData); |
|
446 |
|
447 CApaLocalisableResourceFileWriter* lWriter = NULL; |
|
448 lWriter = |
|
449 CApaLocalisableResourceFileWriter::NewL( |
|
450 KNullDesC, // short caption |
|
451 *aMIDletName, // caption |
|
452 numberOfIcons, |
|
453 KNullDesC); |
|
454 CleanupStack::PushL(lWriter); |
|
455 |
|
456 TDriveUnit targetDrive(*aTargetDrive); |
|
457 |
|
458 // Convert session handle to pointer. |
|
459 RApaLsSession *pApaSession = |
|
460 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
461 |
|
462 // Register application to AppArc |
|
463 pApaSession->RegisterNonNativeApplicationL( |
|
464 KMidletApplicationTypeUid, |
|
465 targetDrive, |
|
466 *writer, |
|
467 lWriter, |
|
468 &appArcIcon); |
|
469 |
|
470 CleanupStack::PopAndDestroy(lWriter); |
|
471 CleanupStack::PopAndDestroy(writer); |
|
472 // close icon file handle |
|
473 CleanupStack::PopAndDestroy(&appArcIcon); |
|
474 |
|
475 // close file server connection |
|
476 CleanupStack::PopAndDestroy(&fileServ); |
|
477 |
|
478 return err; |
|
479 } |
|
480 |
|
481 |
|
482 /** |
|
483 * Unregisters Java Application from S60 AppArc |
|
484 * |
|
485 * @param[in] aSessionHandle |
|
486 * @param[in] aUid The Uid of the application to be unregistered.. |
|
487 * @return 0 if unregistration succeeded or Symbian error code |
|
488 */ |
|
489 #if 0 |
|
490 //#ifdef RD_JAVA_USIF_APP_REG |
|
491 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1unregisterApplication |
|
492 (JNIEnv *, jclass, jint /*aSessionHandle*/, jint /*aUid*/) |
|
493 { |
|
494 return KErrNone; |
|
495 } |
|
496 #else |
|
497 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1unregisterApplication |
|
498 (JNIEnv *, jclass, jint aSessionHandle, jint aUid) |
|
499 { |
|
500 // Convert session handle to pointer. |
|
501 RApaLsSession *pApaSession = |
|
502 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
503 |
|
504 TUid appUid; |
|
505 appUid.iUid = aUid; |
|
506 TRAPD(err, pApaSession->DeregisterNonNativeApplicationL(appUid)); |
|
507 return err; |
|
508 } |
|
509 #endif // RD_JAVA_USIF_APP_REG |
|
510 |
|
511 |
|
512 /** |
|
513 * Commits native application registration session. |
|
514 * If commit succeeds the native session is closed. |
|
515 * |
|
516 * @param[in] aSessionHandle |
|
517 * @param[in] aSynchronous if true, makes synchronous commit |
|
518 * @return 0 or Symbian error code (negative number) |
|
519 */ |
|
520 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1commitSession |
|
521 (JNIEnv *, jclass, jint aSessionHandle, jboolean aSynchronous) |
|
522 { |
|
523 // Convert session handle to pointer. |
|
524 RApaLsSession *pApaSession = |
|
525 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
526 |
|
527 TInt err = KErrNone; |
|
528 |
|
529 #if 1 |
|
530 //#ifndef RD_JAVA_USIF_APP_REG |
|
531 if (aSynchronous) |
|
532 { |
|
533 // Make synchronous commit |
|
534 TRAP(err, pApaSession->CommitNonNativeApplicationsUpdatesL()); |
|
535 if (KErrNone == err) |
|
536 { |
|
537 pApaSession->Close(); |
|
538 delete pApaSession; |
|
539 } |
|
540 return err; |
|
541 } |
|
542 |
|
543 // Otherwise check whether the device supports asynchronous commit |
|
544 // (has a working version of new AppArc method ForceCommitNonNativeApplicationsUpdatesL) |
|
545 // Latest S60 5.0 builds contain fix for Symbian |
|
546 // defect PDEF129466 (PDEF129467 for Symbian OS 9.5). |
|
547 if (!isForceCommitSupported()) |
|
548 { |
|
549 // Use old API |
|
550 TRAP(err, pApaSession->CommitNonNativeApplicationsUpdatesL()); |
|
551 } |
|
552 else |
|
553 { |
|
554 #ifdef __WINS__ |
|
555 // Use always this synchronous commit when running in emulator |
|
556 // to make writing autotest cases easier. |
|
557 TRAP(err, pApaSession->CommitNonNativeApplicationsUpdatesL()); |
|
558 #else |
|
559 // asynchronous commit |
|
560 TRAP(err, pApaSession->ForceCommitNonNativeApplicationsUpdatesL()); |
|
561 #endif // __WINS__ |
|
562 } |
|
563 #endif // RD_JAVA_USIF_APP_REG |
|
564 |
|
565 if (KErrNone == err) |
|
566 { |
|
567 pApaSession->Close(); |
|
568 delete pApaSession; |
|
569 } |
|
570 return err; |
|
571 } |
|
572 |
|
573 |
|
574 /** |
|
575 * Rolls back and closes native application registration session. |
|
576 * |
|
577 * @param[in] aSessionHandle |
|
578 * @return 0 or Symbian error code (negative number) |
|
579 */ |
|
580 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1rollbackSession |
|
581 (JNIEnv *, jclass, jint aSessionHandle) |
|
582 { |
|
583 // Convert session handle to pointer. |
|
584 RApaLsSession *pApaSession = |
|
585 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
586 |
|
587 TInt err = KErrNone; |
|
588 #if 1 |
|
589 //#ifndef RD_JAVA_USIF_APP_REG |
|
590 err = pApaSession->RollbackNonNativeApplicationsUpdates(); |
|
591 #endif // RD_JAVA_USIF_APP_REG |
|
592 pApaSession->Close(); |
|
593 delete pApaSession; |
|
594 |
|
595 return err; |
|
596 } |
|
597 |
|
598 |
|
599 /** |
|
600 * Tells whether the uid is in use in AppArc. |
|
601 * Calls AppArc RApaLsSession::GetAppType |
|
602 * |
|
603 * @param[in] aSessionHandle |
|
604 * @param[in] aUid |
|
605 * @return 0 if the uid is not in use, |
|
606 * 1 if the uid is in use |
|
607 */ |
|
608 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1uidInUse |
|
609 (JNIEnv *, jclass, jint aSessionHandle, jint aUid) |
|
610 { |
|
611 // Convert session handle to pointer. |
|
612 RApaLsSession *pApaSession = |
|
613 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
614 |
|
615 TUid typeUid; |
|
616 TUid appUid; |
|
617 appUid.iUid = aUid; |
|
618 TInt err = pApaSession->GetAppType(typeUid, appUid); |
|
619 if (KErrNone == err) |
|
620 { |
|
621 // AppArc knows the app type -> the uid is in use |
|
622 return 1; |
|
623 } |
|
624 else |
|
625 { |
|
626 return 0; |
|
627 } |
|
628 } |
|
629 |
|
630 |
|
631 /** |
|
632 * Returns the logical group name of the application. |
|
633 * Calls AppArc RApaLsSession::GetAppCapability |
|
634 * |
|
635 * @param[in] aSessionHandle |
|
636 * @param[in] aUid |
|
637 * @param[out] aGroupName should be "" when called, will contain group name |
|
638 * when function returns if call was successfull. |
|
639 * Note that max group name len is 16. |
|
640 * @return Symbian error code (negative number) if fails, otherwise 0 |
|
641 */ |
|
642 JNIEXPORT jint JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1getGroupName |
|
643 (JNIEnv *aEnv, jclass aClass, jint aSessionHandle, jint aUid, jobject aGroupName) |
|
644 { |
|
645 if (0 == aGroupName) |
|
646 { |
|
647 // Cannot return logical group name because StringBuffer param is null |
|
648 return KErrArgument; |
|
649 } |
|
650 |
|
651 // Convert session handle to pointer. |
|
652 RApaLsSession *pApaSession = |
|
653 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
654 |
|
655 TInt err; |
|
656 TUid midletUid; |
|
657 TApaAppCapabilityBuf cap; |
|
658 |
|
659 midletUid.iUid = aUid; |
|
660 |
|
661 err = pApaSession->GetAppCapability(cap, midletUid); |
|
662 if (KErrNone != err) |
|
663 { |
|
664 return err; |
|
665 } |
|
666 |
|
667 // The name is available in Unicode format from cap, convert it to UTF8 |
|
668 // Then lenght of the buffer has '+1' to reserve space for zero terminator |
|
669 // needed to convert string to Java string |
|
670 TBuf8<KApaMaxAppGroupName+1> nameBuf; // max group name len is 16 |
|
671 err = CnvUtfConverter::ConvertFromUnicodeToUtf8(nameBuf, cap().iGroupName); |
|
672 if (KErrNone != err) |
|
673 { |
|
674 return err; |
|
675 } |
|
676 |
|
677 // Get class handle to StringBuffer |
|
678 aClass = aEnv->GetObjectClass(aGroupName); |
|
679 |
|
680 // Get method ID to StringBuffer StringBuffer.append(String) |
|
681 jmethodID methodID = aEnv->GetMethodID( |
|
682 aClass, |
|
683 "append", |
|
684 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); |
|
685 if (0 == methodID) |
|
686 { |
|
687 return KErrGeneral; |
|
688 } |
|
689 |
|
690 // Create new Java String |
|
691 jstring logicalName = aEnv->NewStringUTF((const char*)(nameBuf.PtrZ())); |
|
692 |
|
693 // Append it to aGroupName parameter |
|
694 aEnv->CallObjectMethod(aGroupName, methodID, logicalName); |
|
695 |
|
696 return 0; |
|
697 } |
|
698 |
|
699 |
|
700 /** |
|
701 * Closes native application registration session. |
|
702 * |
|
703 * @param[in] aSessionHandle the session to be closed |
|
704 */ |
|
705 JNIEXPORT void JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1closeSession |
|
706 (JNIEnv *, jclass, jint aSessionHandle) |
|
707 { |
|
708 // Convert session handle to pointer. |
|
709 RApaLsSession *pApaSession = |
|
710 reinterpret_cast<RApaLsSession*>(aSessionHandle<<2); |
|
711 |
|
712 pApaSession->Close(); |
|
713 delete pApaSession; |
|
714 } |
|
715 |
|
716 |
|
717 /** |
|
718 * Converts icon to S60 specific format. SVG icons are converted to MIF, |
|
719 * other icons to MBM. |
|
720 * |
|
721 * @param[in] aInputIconFilename file name of the original icon inside .jar |
|
722 * @param[in] aOutputIconFilename file name for converted (output) icon |
|
723 * @param[in] aJarFilename jar file name. In S60 the icon is always |
|
724 * inside the .jar file |
|
725 * @param[out] aIconSuffix the correct suffix of the icon is returned through |
|
726 * this parameter, will contain '.mbm' or '.mif' when function returns |
|
727 * @return true if the conversion succeeds |
|
728 */ |
|
729 JNIEXPORT jboolean JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1convertIcon |
|
730 (JNIEnv *aEnv, jclass aClass, jstring aInputIconFilename, |
|
731 jstring aOutputIconFilename, jstring aJarFilename, jobject aIconSuffix) |
|
732 { |
|
733 jboolean conversionSucceeded = JNI_TRUE; |
|
734 RFs fileServ; |
|
735 |
|
736 // IconConverter requires open RFile handle |
|
737 TInt err = fileServ.Connect(); |
|
738 if (KErrNone != err) |
|
739 { |
|
740 // Cannot convert icons without file server connection |
|
741 ELOG1(EJavaInstaller, |
|
742 "_1convertIcon: Cannot open RFs connection, err code is %d ", err); |
|
743 return err; |
|
744 } |
|
745 |
|
746 // Copy the unicode characters in jstrings to Symbian buffers so that |
|
747 // they can be used in S60 code |
|
748 const jchar *iconFileName = aEnv->GetStringChars(aInputIconFilename, 0); |
|
749 if (NULL == iconFileName) |
|
750 { |
|
751 ELOG( |
|
752 EJavaInstaller, |
|
753 "Cannot convert icon, getting icon file name as unicode failed in JNI"); |
|
754 fileServ.Close(); |
|
755 return JNI_FALSE; |
|
756 } |
|
757 HBufC16 *unicodeIconFileName = HBufC16::New(aEnv->GetStringLength(aInputIconFilename) + 1); |
|
758 if (NULL == unicodeIconFileName) |
|
759 { |
|
760 fileServ.Close(); |
|
761 return JNI_FALSE; |
|
762 } |
|
763 *unicodeIconFileName = iconFileName; |
|
764 aEnv->ReleaseStringChars(aInputIconFilename, iconFileName); |
|
765 |
|
766 const jchar *jarFileName = aEnv->GetStringChars(aJarFilename, 0); |
|
767 if (NULL == jarFileName) |
|
768 { |
|
769 ELOG( |
|
770 EJavaInstaller, |
|
771 "Cannot convert icon, getting jar file name as unicode failed in JNI"); |
|
772 delete unicodeIconFileName; |
|
773 fileServ.Close(); |
|
774 return JNI_FALSE; |
|
775 } |
|
776 HBufC16 *unicodeJarFileName = HBufC16::New(aEnv->GetStringLength(aJarFilename) + 1); |
|
777 if (NULL == unicodeJarFileName) |
|
778 { |
|
779 delete unicodeIconFileName; |
|
780 fileServ.Close(); |
|
781 return JNI_FALSE; |
|
782 } |
|
783 *unicodeJarFileName = jarFileName; |
|
784 aEnv->ReleaseStringChars(aJarFilename, jarFileName); |
|
785 |
|
786 const jchar *outputFileName = aEnv->GetStringChars(aOutputIconFilename, 0); |
|
787 if (NULL == outputFileName) |
|
788 { |
|
789 ELOG( |
|
790 EJavaInstaller, |
|
791 "Cannot convert icon, getting output file name as unicode failed in JNI"); |
|
792 delete unicodeIconFileName; |
|
793 delete unicodeJarFileName; |
|
794 fileServ.Close(); |
|
795 return JNI_FALSE; |
|
796 } |
|
797 HBufC16 *unicodeOutputFileName = HBufC16::New(aEnv->GetStringLength(aOutputIconFilename) + 1); |
|
798 if (NULL == unicodeOutputFileName) |
|
799 { |
|
800 delete unicodeIconFileName; |
|
801 delete unicodeJarFileName; |
|
802 fileServ.Close(); |
|
803 return JNI_FALSE; |
|
804 } |
|
805 *unicodeOutputFileName = outputFileName; |
|
806 aEnv->ReleaseStringChars(aOutputIconFilename, outputFileName); |
|
807 |
|
808 CIconConverter *pConv = NULL; |
|
809 TRAP(err, pConv= CIconConverter::NewL(fileServ)); |
|
810 if (KErrNone != err) |
|
811 { |
|
812 ELOG1(EJavaInstaller, "Cannot create icon converter, error %d ", err); |
|
813 delete unicodeIconFileName; |
|
814 delete unicodeJarFileName; |
|
815 delete unicodeOutputFileName; |
|
816 fileServ.Close(); |
|
817 return JNI_FALSE; |
|
818 } |
|
819 |
|
820 // read icon from .jar file, convert it to MIF/MBM and store to file |
|
821 TBool isMbmIcon = EFalse; |
|
822 err = pConv->Convert(*unicodeJarFileName, *unicodeIconFileName, |
|
823 *unicodeOutputFileName, &isMbmIcon); |
|
824 delete pConv; |
|
825 if (KErrNone != err) |
|
826 { |
|
827 WLOG1(EJavaInstaller, |
|
828 "Cannot convert icon, err code is %d.", |
|
829 err); |
|
830 conversionSucceeded = JNI_FALSE; |
|
831 } |
|
832 |
|
833 // Free all Symbian buffers containing copies of jstring data |
|
834 delete unicodeIconFileName; |
|
835 delete unicodeJarFileName; |
|
836 delete unicodeOutputFileName; |
|
837 fileServ.Close(); |
|
838 |
|
839 // set the value of aIconSuffix to '.mbm' or '.mif' |
|
840 if (0 == aIconSuffix) |
|
841 { |
|
842 // Cannot return icon suffix name because StringBuffer param is null |
|
843 WLOG(EJavaInstaller, |
|
844 "_1convertIcon cannot return the correct icon suffix because param is null"); |
|
845 return JNI_FALSE; |
|
846 } |
|
847 |
|
848 // Get class handle to StringBuffer |
|
849 aClass = aEnv->GetObjectClass(aIconSuffix); |
|
850 |
|
851 // Get method ID to StringBuffer StringBuffer.append(String) |
|
852 jmethodID methodID = aEnv->GetMethodID( |
|
853 aClass, |
|
854 "append", |
|
855 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); |
|
856 if (0 == methodID) |
|
857 { |
|
858 WLOG(EJavaInstaller, "_1convertIcon: JNI: getting append method failed."); |
|
859 return JNI_FALSE; |
|
860 } |
|
861 |
|
862 // Create new Java String, Multibitmap file name suffix is '.mbm', |
|
863 // suffix for mif wrapped svg is '.mif' |
|
864 jstring suffix; |
|
865 if (isMbmIcon) |
|
866 { |
|
867 suffix = aEnv->NewStringUTF(".mbm"); |
|
868 } |
|
869 else |
|
870 { |
|
871 suffix = aEnv->NewStringUTF(".mif"); |
|
872 } |
|
873 |
|
874 // Append it to aIconSuffix parameter |
|
875 aEnv->CallObjectMethod(aIconSuffix, methodID, suffix); |
|
876 |
|
877 return conversionSucceeded; |
|
878 } |
|
879 |
|
880 |
|
881 /** |
|
882 * Returns true if the current device is touch screen |
|
883 * device without physical LSK and RSK |
|
884 * |
|
885 * @return true if virtual on screen keypad is needed |
|
886 */ |
|
887 JNIEXPORT jboolean JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1isOnDeviceKeypadNeeded |
|
888 (JNIEnv *, jclass) |
|
889 { |
|
890 // Return TRUE -> OnScreenKeypad attribute will be given |
|
891 // default value if the attribute has not been defined in |
|
892 // .jad file or manifest. |
|
893 // The runtime code will check whether the device has touch |
|
894 // screen using AknLayoutUtils::PenEnabled() and show the |
|
895 // keypad only if needed. |
|
896 return JNI_TRUE; |
|
897 } |
|
898 |
|
899 |
|
900 /** |
|
901 * Sends a process to process notification to the parent process |
|
902 * of Java Installer telling that Installer is about to start |
|
903 * displaying UI dialogs. |
|
904 */ |
|
905 JNIEXPORT void JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1notifyLauncherThatUiIsReady |
|
906 (JNIEnv *, jclass) |
|
907 { |
|
908 RProcess currentProcess; |
|
909 currentProcess.Rendezvous(EJavaInstaller); |
|
910 |
|
911 return; |
|
912 } |
|
913 |
|
914 |
|
915 /** |
|
916 * Returns true if the code is executed in Symbian 9.2 |
|
917 * emulator environment. |
|
918 * |
|
919 * @return if Symbian 9.2 emulator environment |
|
920 */ |
|
921 JNIEXPORT jboolean JNICALL Java_com_nokia_mj_impl_installer_applicationregistrator_ApplicationRegistrator__1runningIn92Emulator |
|
922 (JNIEnv *, jclass) |
|
923 { |
|
924 #if !defined(RD_JAVA_S60_RELEASE_5_0_IAD) && defined(__WINS__) |
|
925 return JNI_TRUE; |
|
926 #else |
|
927 return JNI_FALSE; |
|
928 #endif |
|
929 } |
|
930 |
|
931 |
|
932 /** |
|
933 * Internal helper method for checking whether this code is executing in |
|
934 * a device that has correctly working version of |
|
935 * RApaLsSession::ForceCommitNonNativeApplicationsUpdatesL() |
|
936 * |
|
937 * The device family based on Nokia XpressMusic5800 did not have |
|
938 * working version of force commit |
|
939 * |
|
940 * @return ETrue if current device does not belong to Nokia XpressMusic5800 |
|
941 * device family |
|
942 */ |
|
943 TBool isForceCommitSupported() |
|
944 { |
|
945 TInt err; |
|
946 TInt value; |
|
947 |
|
948 err = HAL::Get(HAL::EModel, value); |
|
949 if (KErrNone == err) |
|
950 { |
|
951 LOG1(EJavaInstaller, EInfo, "Device model is %d", value); |
|
952 } |
|
953 else |
|
954 { |
|
955 WLOG1(EJavaInstaller, "Cannot get device model id, error %d", err); |
|
956 // It is safest to assume that force commit is not supported |
|
957 return EFalse; |
|
958 } |
|
959 |
|
960 // Check against all current (28. Aug 2009) members of the device family. |
|
961 // Note that several closely related devices share the same model id. |
|
962 if ((0x2000DA56 != value) && |
|
963 (0x2001DE9D != value) && |
|
964 (0x2000DA60 != value) && |
|
965 (0x20023765 != value)) |
|
966 { |
|
967 // The device does not belong to Nokia 5800 XpressMusic device family, |
|
968 // so it supports foce commit |
|
969 return ETrue; |
|
970 } |
|
971 else |
|
972 { |
|
973 return EFalse; |
|
974 } |
|
975 } |