|
1 /* |
|
2 * Copyright (c) 2009 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: Java platform 2.0 javaappbackconverter process |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <e32std.h> |
|
20 #include <e32base.h> |
|
21 #include <e32property.h> |
|
22 #include <f32file.h> |
|
23 #include <centralrepository.h> |
|
24 #include <swinstallerinternalpskeys.h> |
|
25 #include <AknGlobalMsgQuery.h> |
|
26 |
|
27 #include "javacommonutils.h" |
|
28 #include "javauids.h" |
|
29 #include "backconverter.h" |
|
30 #include "noarmlogs.h" |
|
31 |
|
32 _LIT_SECURE_ID(KAppInstUiSecureID, 0x101F875A); |
|
33 _LIT_SECURE_ID(KAppSisLauncherSecureID, 0x1020473F); |
|
34 |
|
35 |
|
36 /** |
|
37 * Create file server connection. |
|
38 * If no data storage file exists, exit. |
|
39 * Create active scheduler and start it to execute actual back converter. |
|
40 */ |
|
41 static void ExecuteBackConverterL(RFs &aFs) |
|
42 { |
|
43 LOG(EJavaConverters, EInfo, "javaappbackconverter: ExecuteBackConverterL called"); |
|
44 |
|
45 CActiveScheduler* as = new(ELeave) CActiveScheduler(); |
|
46 |
|
47 // Install active scheduler |
|
48 CActiveScheduler::Install(as); |
|
49 CleanupStack::PushL(as); |
|
50 |
|
51 // The file server session must be shared so that that AppArc can |
|
52 // use the icon file handle opened in back converter |
|
53 TInt err = aFs.ShareProtected(); |
|
54 if (KErrNone != err) |
|
55 { |
|
56 ELOG1(EJavaConverters, |
|
57 "javaappbackconverter: ExecuteBackConverterL: " |
|
58 "Cannot share file server session, err code is %d ", err); |
|
59 User::Leave(err); |
|
60 } |
|
61 |
|
62 // Setup and start the back conversion |
|
63 CBackConverter* back = CBackConverter::NewLC(aFs); |
|
64 |
|
65 LOG(EJavaConverters, |
|
66 EInfo, "javaappbackconverter: ExecuteBackConverterL: Call CBackConverter::Start()"); |
|
67 |
|
68 back->Start(); |
|
69 |
|
70 // Start active scheduler |
|
71 LOG(EJavaConverters, EInfo, "ExecuteBackConverterL: Starting CActiveScheduler"); |
|
72 CActiveScheduler::Start(); |
|
73 |
|
74 LOG(EJavaConverters, EInfo, "javaappbackconverter: ExecuteBackConverterL: Cleaning up"); |
|
75 |
|
76 CleanupStack::PopAndDestroy(back); |
|
77 CleanupStack::PopAndDestroy(as); |
|
78 } |
|
79 |
|
80 /** |
|
81 * Menu application has a central repository key that can be used in |
|
82 * devices belonging to Nokia 5800 XpressMusic device family to request |
|
83 * that the Menu application would rescan all applications it contains. |
|
84 */ |
|
85 static void UseCRKeyToUpdateAppShellDataL() |
|
86 { |
|
87 const TUid KCRUidMenu = { 0x101F8847 }; |
|
88 const TUint32 KMenuUpdateData = 0x00000001; |
|
89 |
|
90 // Update Central Rep |
|
91 CRepository *pCenRep = CRepository::NewL(KCRUidMenu); |
|
92 |
|
93 TInt value = 1; |
|
94 TInt err = pCenRep->Set(KMenuUpdateData, value); |
|
95 if (KErrNone != err) |
|
96 { |
|
97 ELOG1(EJavaConverters, |
|
98 "javaappbackconverter: UseCRKeyToUpdateAppShellDataL: " |
|
99 "setting cenrep value failed, error %d ", |
|
100 err); |
|
101 } |
|
102 |
|
103 delete pCenRep; |
|
104 } |
|
105 |
|
106 /** |
|
107 * After OMJ has been uninstalled the menu application of the device |
|
108 * does not display the icons of the old, restored java applications. |
|
109 * The icons are shown after the device is booted. |
|
110 * Tell menu application to scan again all applications so that the icons |
|
111 * will be shown. |
|
112 */ |
|
113 static void AddOldJavaAppIconsToMenuApp() |
|
114 { |
|
115 LOG(EJavaConverters, EInfo, "javaappbackconverter: AddOldJavaAppIconsToMenuApp called."); |
|
116 |
|
117 TRAPD(err, UseCRKeyToUpdateAppShellDataL()); |
|
118 if (KErrNotFound == err) |
|
119 { |
|
120 // Only Nokia XPressMusic 5800 device family supports this feature, |
|
121 // N97 and later devices no longer support it but they have new Menu |
|
122 // application that shows all Java application icons anyway. |
|
123 LOG(EJavaConverters, EInfo, |
|
124 "javaappbackconverter: AddOldJavaAppIconsToMenuApp: This device does not " |
|
125 "support refreshing Menu using CR keys."); |
|
126 } |
|
127 else if (KErrNone != err) |
|
128 { |
|
129 ELOG1(EJavaConverters, |
|
130 "javaappbackconverter: AddOldJavaAppIconsToMenuApp: Error: %d", err); |
|
131 } |
|
132 } |
|
133 |
|
134 /** |
|
135 * Kill the running OMJ javaregistry.exe. After killing next call to |
|
136 * Registry API restarts the old S60 server process. |
|
137 */ |
|
138 static void KillRegistry() |
|
139 { |
|
140 LOG(EJavaConverters, EInfo, "javaappbackconverter: KillRegistry called."); |
|
141 |
|
142 TFullName processName; |
|
143 _LIT(KJavaRegistryProcess, "javaregistry*"); |
|
144 TFindProcess finder(KJavaRegistryProcess); |
|
145 |
|
146 if (finder.Next(processName) != KErrNotFound) |
|
147 { |
|
148 RProcess processToKill; |
|
149 TInt err = processToKill.Open(finder); |
|
150 |
|
151 if (KErrNone != err) |
|
152 { |
|
153 WLOG1(EJavaConverters, "javaappbackconverter: Process open: %d", err); |
|
154 } |
|
155 else |
|
156 { |
|
157 processToKill.Kill(KErrNone); |
|
158 processToKill.Close(); |
|
159 } |
|
160 } |
|
161 else |
|
162 { |
|
163 WLOG(EJavaConverters, "javaappbackconverter: Registry process not found"); |
|
164 } |
|
165 } |
|
166 |
|
167 /** |
|
168 * Unregister OMJ MIDlet starter, reregister old S60 MIDlet starter |
|
169 */ |
|
170 static void ReregisterOldMidletStarter() |
|
171 { |
|
172 LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter called"); |
|
173 |
|
174 _LIT(KStubMIDP2RecogExe, "StubMIDP2RecogExe.exe"); |
|
175 |
|
176 RApaLsSession appLstSession; |
|
177 |
|
178 TInt error = appLstSession.Connect(); |
|
179 if (error != KErrNone) |
|
180 { |
|
181 ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " |
|
182 "RApaLsSession.Connect failed with error %d", error); |
|
183 return; |
|
184 } |
|
185 TRAP(error, appLstSession.RegisterNonNativeApplicationTypeL( |
|
186 TUid::Uid(KMidletApplicationTypeUid), KStubMIDP2RecogExe())); |
|
187 if (error == KErrNone) |
|
188 { |
|
189 LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter: " |
|
190 "Registered MIDlet application type for S60 Java."); |
|
191 } |
|
192 else if (error != KErrAlreadyExists) |
|
193 { |
|
194 ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " |
|
195 "RegisterNonNativeApplicationTypeL failed with error %d", error); |
|
196 } |
|
197 else |
|
198 { |
|
199 // OMJ Java has registered MIDlet application type so that it is handled by |
|
200 // OMJ binary 'javalauncher.exe', must change that registration |
|
201 WLOG(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " |
|
202 "MIDlet application type was registered (by OMJ Java)."); |
|
203 // Ignore possible error in deregistration |
|
204 TRAP(error, appLstSession.DeregisterNonNativeApplicationTypeL( |
|
205 TUid::Uid(KMidletApplicationTypeUid))); |
|
206 TRAP(error, appLstSession.RegisterNonNativeApplicationTypeL( |
|
207 TUid::Uid(KMidletApplicationTypeUid), KStubMIDP2RecogExe())); |
|
208 if (KErrNone != error) |
|
209 { |
|
210 ELOG1(EJavaConverters, "javaappbackconverter: ReregisterOldMidletStarter: " |
|
211 "RegisterNonNativeApplicationTypeL failed with error %d", error); |
|
212 } |
|
213 else |
|
214 { |
|
215 LOG(EJavaConverters, EInfo, "javaappbackconverter: ReregisterOldMidletStarter: " |
|
216 "Registered MIDlet application type again (for S60 Java)."); |
|
217 } |
|
218 } |
|
219 |
|
220 appLstSession.Close(); |
|
221 } |
|
222 |
|
223 |
|
224 /** |
|
225 * Show dialog telling that the device must be rebooted |
|
226 */ |
|
227 static void showMustRebootDialog() |
|
228 { |
|
229 LOG(EJavaConverters, EInfo, "javaappbackconverter: showMustRebootDialog() Called"); |
|
230 |
|
231 // Wait for 2 seconds before showing dialog |
|
232 User::After(2000000); |
|
233 |
|
234 TRAPD(err, |
|
235 TRequestStatus status; |
|
236 CAknGlobalMsgQuery* globalMsg = CAknGlobalMsgQuery::NewLC(); |
|
237 |
|
238 // In OMJ 2.x beta .sis uninstallation it is enough to |
|
239 // show the text always in english (non-localized) |
|
240 _LIT(KJavaPleaseReboot, "To complete the uninstallation process, \ |
|
241 the phone must be restarted. Until then some applications may not function properly."); |
|
242 |
|
243 // tell that device will be rebooted |
|
244 globalMsg->ShowMsgQueryL( |
|
245 status, |
|
246 KJavaPleaseReboot, |
|
247 R_AVKON_SOFTKEYS_OK_EMPTY__OK, |
|
248 KNullDesC(), |
|
249 KNullDesC(), |
|
250 0, |
|
251 -1, |
|
252 CAknQueryDialog::EWarningTone); |
|
253 |
|
254 User::WaitForRequest(status); |
|
255 |
|
256 CleanupStack::PopAndDestroy(globalMsg); |
|
257 ); |
|
258 if (KErrNone != err) |
|
259 { |
|
260 ELOG1(EJavaConverters, |
|
261 "javaappbackconverter: showMustRebootDialog() TRAP_IGNORE exited with err %d", err); |
|
262 } |
|
263 } |
|
264 |
|
265 |
|
266 /** |
|
267 * Create cleanup stack and run the javaappbackconverter code inside TRAP |
|
268 * harness to log unexpected leaves. |
|
269 */ |
|
270 TInt E32Main() |
|
271 { |
|
272 CTrapCleanup* pCleanupStack = CTrapCleanup::New(); |
|
273 if (NULL == pCleanupStack) |
|
274 { |
|
275 ELOG(EJavaConverters, "javaappbackconverter: Could not create cleanup stack!"); |
|
276 return KErrNoMemory; |
|
277 } |
|
278 |
|
279 LOG(EJavaConverters, EInfo, "javaappbackconverter: Starting backconverter"); |
|
280 |
|
281 // Create file server session |
|
282 RFs fs; |
|
283 TInt err = fs.Connect(); |
|
284 if (KErrNone != err) |
|
285 { |
|
286 ELOG1(EJavaConverters, |
|
287 "javaappbackconverter: Cannot open RFs connection. Error %d", err); |
|
288 return err; |
|
289 } |
|
290 |
|
291 // Determine whether backconversion should be done or not. |
|
292 // It should be done |
|
293 // - if this process has been started when java_2_0.sis is uninstalled |
|
294 // OR |
|
295 // - if this process has been started when s60_omj_restore_midlets.sis is installed |
|
296 |
|
297 // The path name of the loaded executable on which this process is based is |
|
298 // 'javaappbackconverter.exe' if this process has been started from java_2_0.sis and |
|
299 // 'javaapprestorer.exe' if this process has been started from s60_omj_restore_midlets.sis |
|
300 _LIT(KJavaRestorerFileName, "javaapprestorer.exe"); |
|
301 TBool fStartedFromOmjSis(ETrue); |
|
302 RProcess thisProcess; |
|
303 TFileName filename = thisProcess.FileName(); |
|
304 if (filename.Find(KJavaRestorerFileName) > 0) |
|
305 { |
|
306 LOG(EJavaConverters, EInfo, |
|
307 "javaappbackconverter: Started from s60_omj_restore_midlets.sis"); |
|
308 fStartedFromOmjSis = EFalse; |
|
309 } |
|
310 LOG1WSTR(EJavaConverters, EInfo, |
|
311 "javaappbackconverter: Process file name is %s", (wchar_t *)(filename.PtrZ())); |
|
312 |
|
313 // Check whether uninstalling or (installing/upgrading) |
|
314 TBool fUninstallingSisPackage(EFalse); |
|
315 TInt value(0); |
|
316 // Ignore errors, if the value cannot be read, assume 'installing .sis' |
|
317 RProperty::Get(KPSUidSWInstallerUiNotification, KSWInstallerUninstallation, value); |
|
318 if (0 == value) |
|
319 { |
|
320 // Native installer is installing (or upgrading) a .sis package |
|
321 LOG(EJavaConverters, EInfo, "javaappbackconverter: native installer is installing .sis"); |
|
322 } |
|
323 else |
|
324 { |
|
325 // Native installer is uninstalling a .sis package |
|
326 fUninstallingSisPackage = ETrue; |
|
327 LOG(EJavaConverters, EInfo, "javaappbackconverter: native installer is uninstalling .sis"); |
|
328 } |
|
329 |
|
330 if (fUninstallingSisPackage && fStartedFromOmjSis) |
|
331 { |
|
332 // backconversion must be done |
|
333 LOG(EJavaConverters, EInfo, "javaappbackconverter: Going to do backconversion."); |
|
334 } |
|
335 else if ((!fUninstallingSisPackage) && (!fStartedFromOmjSis)) |
|
336 { |
|
337 // backconversion must be done |
|
338 LOG(EJavaConverters, EInfo, "javaappbackconverter: Going to restore midlets."); |
|
339 } |
|
340 else |
|
341 { |
|
342 LOG(EJavaConverters, EInfo, |
|
343 "javaappbackconverter: Back conversion / restoration is not needed."); |
|
344 fs.Close(); |
|
345 return KErrNone; |
|
346 } |
|
347 |
|
348 // The only time that this application should be executed |
|
349 // is when native installer starts it |
|
350 if ((User::CreatorSecureId() != KAppInstUiSecureID) && |
|
351 (User::CreatorSecureId() != KAppSisLauncherSecureID)) |
|
352 { |
|
353 ELOG(EJavaConverters, |
|
354 "javaappbackconverter: Mismatch in secure ID, only AppInstUi " |
|
355 "or SisLauncher can launch this exe."); |
|
356 ELOG1(EJavaConverters, |
|
357 "javaappbackconverter: Starter has SID %x ", User::CreatorSecureId().iId); |
|
358 fs.Close(); |
|
359 return KErrPermissionDenied; |
|
360 } |
|
361 else |
|
362 { |
|
363 LOG(EJavaConverters, EInfo, "javaappbackconverter: Starter SID was OK."); |
|
364 } |
|
365 |
|
366 ReregisterOldMidletStarter(); |
|
367 |
|
368 TInt ret = KErrNone; |
|
369 TRAP(ret, ExecuteBackConverterL(fs)); |
|
370 if (ret != KErrNone) |
|
371 { |
|
372 ELOG1(EJavaConverters, "javaappbackconverter: ExecuteBackConverterL: Main error %d", ret); |
|
373 } |
|
374 |
|
375 // Kill OMJ Java Registry process. Next call to Java Registry API starts |
|
376 // old S60 Java Registry server |
|
377 KillRegistry(); |
|
378 |
|
379 // Start also old SystemAMS.exe to restore old S60 Java environment to functional state |
|
380 RProcess rSystemAms; |
|
381 _LIT(KSystemAmsProcess, "SystemAMS.exe"); |
|
382 _LIT(KEmptyCommandLine, ""); |
|
383 err = rSystemAms.Create(KSystemAmsProcess, KEmptyCommandLine); |
|
384 if (KErrNone == err) |
|
385 { |
|
386 rSystemAms.Resume(); |
|
387 } |
|
388 else |
|
389 { |
|
390 WLOG1(EJavaConverters, |
|
391 "javaappbackconverter: Starting SystemAMS.exe failed, err %d", err); |
|
392 } |
|
393 rSystemAms.Close(); |
|
394 |
|
395 AddOldJavaAppIconsToMenuApp(); |
|
396 |
|
397 fs.Close(); |
|
398 |
|
399 if (fUninstallingSisPackage) |
|
400 { |
|
401 showMustRebootDialog(); |
|
402 } |
|
403 |
|
404 delete pCleanupStack; |
|
405 return ret; |
|
406 } |