|
1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // This file provides the implementation of the class for |
|
15 // the SUPL MT-LR procedure state handler |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalTechnology |
|
22 @deprecated |
|
23 */ |
|
24 |
|
25 #include "suplmtlrfsmsession.h" |
|
26 #include "suplmtlrstatehandler.h" |
|
27 #include "suplgatewayinterface.h" |
|
28 #include "suplmessagebase.h" |
|
29 #include "suplstart.h" |
|
30 #include "suplpos.h" |
|
31 #include "suplposinit.h" |
|
32 #include "suplresponse.h" |
|
33 #include "suplend.h" |
|
34 #include <etelmm.h> |
|
35 #include "supldevloggermacros.h" |
|
36 |
|
37 |
|
38 /** Static constructor. |
|
39 @param aMachine A reference to the parent state machine. |
|
40 @return A new instance of the CSuplMtLrStateHandler class |
|
41 */ |
|
42 CSuplMtLrStateHandler* CSuplMtLrStateHandler::NewL(CSuplFsmSessionBase& aMachine) |
|
43 { |
|
44 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::NewL() \n"); |
|
45 CSuplMtLrStateHandler* self = new (ELeave) CSuplMtLrStateHandler(aMachine); |
|
46 return self; |
|
47 } |
|
48 |
|
49 /** Standard constructor. |
|
50 @param aMachine A reference to the parent state machine. |
|
51 */ |
|
52 CSuplMtLrStateHandler::CSuplMtLrStateHandler(CSuplFsmSessionBase& aMachine) |
|
53 : CSuplStateHandlerBase(aMachine) |
|
54 { |
|
55 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::CSuplMtLrStateHandler() Begin\n"); |
|
56 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::CSuplMtLrStateHandler() End\n"); |
|
57 } |
|
58 |
|
59 |
|
60 /** Standard destructor. |
|
61 */ |
|
62 CSuplMtLrStateHandler::~CSuplMtLrStateHandler() |
|
63 { |
|
64 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::~CSuplMtLrStateHandler() Begin\n"); |
|
65 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::~CSuplMtLrStateHandler() End\n"); |
|
66 } |
|
67 |
|
68 |
|
69 /** Perform entry actions. |
|
70 This is called from the state machine to perform any actions |
|
71 associated with entering the current state following an external |
|
72 event or an autonomous state transition. |
|
73 |
|
74 For some states, there is only one possible course of action. |
|
75 For other states, the event store has to be checked to see what |
|
76 events have occurred and what actions have to be taken to handle |
|
77 such events. |
|
78 |
|
79 If an event conductive to cancelling the state machine had occurred |
|
80 (e.g, an explicit client cancel, an error, or a timeout), then the |
|
81 state machine would have been set in an state that terminates the |
|
82 session before this method is called (either EStateSuplSessionEnded |
|
83 or EStatePosSessionEnded). |
|
84 |
|
85 @return TBool ETrue if any actions have been taken |
|
86 */ |
|
87 TBool CSuplMtLrStateHandler::EntryActionsL() |
|
88 { |
|
89 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsL() Begin\n"); |
|
90 TBool actionsTaken = ETrue; |
|
91 // Retrieve current state and act accordingly |
|
92 switch(iMachine.CurrentState()) |
|
93 { |
|
94 case CSuplFsmSessionBase::EStateProcedureNull: |
|
95 // No action required |
|
96 break; |
|
97 |
|
98 case CSuplFsmSessionBase::EStateSuplInitReceived: |
|
99 actionsTaken = EntryActionsFromSuplInitReceived(); |
|
100 break; |
|
101 |
|
102 case CSuplFsmSessionBase::EStateNetConnectionStarted: |
|
103 actionsTaken = EntryActionsFromNetConnectionStarted(); |
|
104 break; |
|
105 |
|
106 case CSuplFsmSessionBase::EStatePosInitSent: |
|
107 // Build and send a SUPL POS INIT |
|
108 actionsTaken = EntryActionsFromPosInitSentStateL(); |
|
109 break; |
|
110 |
|
111 case CSuplFsmSessionBase::EStatePositioningInProgress: |
|
112 actionsTaken = EntryActionsFromPositioningInProgressStateL(); |
|
113 break; |
|
114 |
|
115 case CSuplFsmSessionBase::EStatePositionReceived: |
|
116 actionsTaken = EntryActionsFromPositionReceivedStateL(); |
|
117 break; |
|
118 |
|
119 case CSuplFsmSessionBase::EStateSuplSessionEnded: |
|
120 // Send SUPL END |
|
121 actionsTaken = EntryActionsFromSuplSessionEndedStateL(); |
|
122 break; |
|
123 |
|
124 case CSuplFsmSessionBase::EStatePosSessionEnded: |
|
125 // Send to Positioning FSM an instruction to terminate silently |
|
126 // |
|
127 iMachine.PositioningFsm()->CancelMachine(CSuplPositioningProtocolFsm::ESuplFsmCancel, CSuplFsmSessionBase::EReasonNone); |
|
128 break; |
|
129 |
|
130 case CSuplFsmSessionBase::EStateLbsSessionEnded: |
|
131 // Send session complete indication to LBS |
|
132 actionsTaken = EntryActionsFromLbsSessionEndedStateL(); |
|
133 break; |
|
134 |
|
135 case CSuplFsmSessionBase::EStateNetConnectionClosed: |
|
136 // Close the network connection |
|
137 iMachine.CompleteProcedure(); |
|
138 break; |
|
139 |
|
140 default: |
|
141 ASSERT(EFalse); |
|
142 break; |
|
143 } |
|
144 |
|
145 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsL() End\n"); |
|
146 return actionsTaken; |
|
147 } |
|
148 //--------------------------------------------------------------------------------------------------------------------- |
|
149 // ----------------------- METHODS FOR ACTIONS AFTER ENTERING STATES --------------------------------------------- |
|
150 //--------------------------------------------------------------------------------------------------------------------- |
|
151 |
|
152 /** Actions on entering state EStateSuplInitReceived |
|
153 This method sends a LocationRequest and a PrivacyRequest |
|
154 to LBS. |
|
155 */ |
|
156 TBool CSuplMtLrStateHandler::EntryActionsFromSuplInitReceived() |
|
157 { |
|
158 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromSuplInitReceived() Begin\n"); |
|
159 TLbsNetPosRequestPrivacy privacyAdvice; |
|
160 TLbsExternalRequestInfo requestor; |
|
161 TLbsNetPosRequestMethod posMethods; |
|
162 TLbsNetPosMethod selectedMethod; // only one method is sent to LBS |
|
163 TLbsNetPosRequestQuality quality; |
|
164 |
|
165 // Send a PrivacyRequest followed by a Location Request to LBS |
|
166 iMachine.RetrievePrivacyAdvice(privacyAdvice); |
|
167 iMachine.RetrieveRequestorInfo(requestor); |
|
168 iMachine.Observer().PrivacyReq(iMachine.LbsSessionId(), privacyAdvice, requestor); |
|
169 |
|
170 |
|
171 // Get the pos methods received in a SUPL INIT |
|
172 // (kept in event store). |
|
173 iMachine.RetrieveInitPosMethod(posMethods); |
|
174 TLbsNetPosMethod netPrefMethod; |
|
175 posMethods.GetPosMethod(0, netPrefMethod); |
|
176 if (KLbsPositioningMeansNone != netPrefMethod.PosMeans()) // not a "noPosition" INIT |
|
177 { |
|
178 // Check that there are supported positioning methods different |
|
179 // from Cell Based (Cell-Based can't be requested from LBS). |
|
180 TLbsNetPosCapabilities capabilities; |
|
181 iMachine.Observer().Gateway().GetCapabilities(capabilities); |
|
182 if (iMachine.PosMethodSupported(posMethods, selectedMethod,capabilities) && |
|
183 KLbsPositioningMeansCell != selectedMethod.PosMeans()) |
|
184 { |
|
185 // Method to be presented to LBS |
|
186 posMethods.SetPosMethods(&selectedMethod, 1); |
|
187 } |
|
188 else |
|
189 { |
|
190 // No mutually supported positioning methods. |
|
191 // Send to LBS the positioning method that is preferred |
|
192 // by LBS (the first in the capabilities) |
|
193 capabilities.GetPosMethod(0, selectedMethod); |
|
194 posMethods.SetPosMethods(&selectedMethod, 1); |
|
195 } |
|
196 |
|
197 iMachine.RetrieveInitQuality(quality); |
|
198 iMachine.Observer().LocationReq(iMachine.LbsSessionId(), iMachine.LocReqType(), |
|
199 quality, posMethods); |
|
200 } |
|
201 |
|
202 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromSuplInitReceived() End\n"); |
|
203 return ETrue; |
|
204 } |
|
205 |
|
206 |
|
207 /** Actions on entering state EStateNetConnectionStarted |
|
208 |
|
209 This method obtains an SLP Id from the Host Settings store |
|
210 and asks the Connection Manager to provide a connection with it. |
|
211 */ |
|
212 TBool CSuplMtLrStateHandler::EntryActionsFromNetConnectionStarted() |
|
213 { |
|
214 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromNetConnectionStarted() Begin\n"); |
|
215 TBool ret = ETrue; |
|
216 TLbsHostSettingsId hostId = TUid::Uid(0); |
|
217 TLbsNetSessionId::TSessionNum sessIdNum = 0; |
|
218 // Request a connection if one has not been set up already |
|
219 if (!iMachine.IsSessionConnected()) |
|
220 { |
|
221 TInt err = iMachine.GetHostId(hostId); |
|
222 |
|
223 if (KErrNone == err) |
|
224 { |
|
225 // Request a connection from the Connection Manager |
|
226 // |
|
227 sessIdNum = iMachine.SessionId().SessionNum(); |
|
228 iMachine.Observer().ConnectionManager().Connect(sessIdNum, hostId, CSuplSessionRecord::EServiceMtlr, iMachine); |
|
229 // start the timer that oversees connection creation |
|
230 iMachine.StartConnectionTimer(); |
|
231 } |
|
232 else |
|
233 { |
|
234 // Cancel session as a SUPL server could not be determined |
|
235 iMachine.CancelMachine(CSuplFsmSessionBase::ECancelSuplProt, CSuplFsmSessionBase::EReasonSlpSettingsMissing); |
|
236 } |
|
237 } |
|
238 else |
|
239 { |
|
240 // This will happen if the connection has been created but the state |
|
241 // machine remains in EStateNetConnectionStarted due to being waiting |
|
242 // for an event from LBS (either a position notification or an assistance |
|
243 // data request). Nothing to be done. |
|
244 ret = EFalse; |
|
245 } |
|
246 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromNetConnectionStarted() End\n"); |
|
247 return ret; |
|
248 } |
|
249 |
|
250 |
|
251 |
|
252 /** Actions on entering state EStatePosInitSent |
|
253 This method builds a SUPL POS INIT message and hands it over to |
|
254 the Connection Manager for sending to the SUPL server. |
|
255 */ |
|
256 TBool CSuplMtLrStateHandler::EntryActionsFromPosInitSentStateL() |
|
257 { |
|
258 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromPosInitSentStateL() Begin\n"); |
|
259 TBool err = EFalse; |
|
260 TLbsNetPosRequestQuality quality; |
|
261 TLbsNetPosCapabilities capabilities; |
|
262 TBool actionsTaken = EFalse; |
|
263 |
|
264 // There should be either an assistance data request |
|
265 // or a position from LBS in the event store |
|
266 if (iMachine.IsAssistanceDataRequestStored() || iMachine.IsPositionStored()) |
|
267 { |
|
268 ASSERT(iMachine.IsSessionConnected()); // should not have transitioned into this state without a connection |
|
269 |
|
270 // Create the SUPL POS INIT Message |
|
271 CSuplPosInit* suplPosInit = CSuplPosInit::NewL(); |
|
272 CleanupStack::PushL(suplPosInit); |
|
273 |
|
274 // Set the Location Id in the message |
|
275 CSuplLocationId* locationId; |
|
276 if (BuildLocationIdL(locationId)) |
|
277 { |
|
278 CleanupStack::PushL(locationId); |
|
279 |
|
280 suplPosInit->SetLocationId(*locationId); |
|
281 CleanupStack::PopAndDestroy(locationId); |
|
282 |
|
283 // Set Capabilities in the message |
|
284 BuildCapabilitiesL(capabilities,quality); |
|
285 User::LeaveIfError(suplPosInit->SetCapabilities(capabilities)); |
|
286 |
|
287 // Set either a supplied position or assistance data request in the message |
|
288 if (iMachine.IsPositionStored()) |
|
289 { |
|
290 TPositionInfoBase* posPtr = iMachine.RetrievePositionL(); |
|
291 User::LeaveIfError(suplPosInit->SetPosition(*posPtr)); |
|
292 } |
|
293 else if (iMachine.IsAssistanceDataRequestStored()) |
|
294 { |
|
295 TLbsAsistanceDataGroup assitDataReqMask; |
|
296 TBool assitDataReqPresent = iMachine.RetrieveAssistanceDataRequest(assitDataReqMask); |
|
297 if (assitDataReqMask != 0) |
|
298 { |
|
299 User::LeaveIfError(suplPosInit->SetRequestedAssistanceData(assitDataReqMask)); |
|
300 } |
|
301 else |
|
302 { |
|
303 // This was an empty assistance data request. No need to set it |
|
304 // in the POS INIT message (intentionally no action take here) |
|
305 } |
|
306 } |
|
307 |
|
308 // Set in message header the stored session id |
|
309 // after adding to it the SET session ID |
|
310 CSuplSessionId* sessionId = iMachine.MessageSessionId(); |
|
311 TUint32 ipAddr = iMachine.RetrieveLocalIpAddress().Address(); |
|
312 sessionId->iSetSessionIdPresent = ETrue; |
|
313 sessionId->iSetSessionId->iSessionId = iMachine.SessionId().SessionNum(); |
|
314 sessionId->iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeMsisdn; // TSuplSetIdType |
|
315 |
|
316 const TUint8 KMaxMsisdnLength = 8; |
|
317 TDes8& des = sessionId->iSetSessionId->iSetId->iSetId; |
|
318 if(iMachine.Msisdn()) |
|
319 { |
|
320 ConvertToBcd(des); |
|
321 } |
|
322 else |
|
323 { |
|
324 //Fill the descriptor with all bits set to 0, then append a 0xFF to the end to indicate the end of the MSISDN |
|
325 des.SetLength(KMaxMsisdnLength); |
|
326 des.Fill(0x00, (KMaxMsisdnLength -1)); //7 0's |
|
327 des.Append(0xFF); //Final 1 FF |
|
328 } |
|
329 |
|
330 //sessionId->iSetSessionId->iSetId->iSetIdType = ESuplSetIdTypeIPAddress; |
|
331 //sessionId->iSetSessionId->iSetId->iIpAddress->iIpAddressType = ESuplIpAddressTypeV4; |
|
332 //sessionId->iSetSessionId->iSetId->iIpAddress->iIpAddress.Copy(reinterpret_cast<unsigned char*>(&ipAddr), 4); |
|
333 |
|
334 User::LeaveIfError(suplPosInit->SetSessionId(*sessionId)); |
|
335 |
|
336 // Set in message the Ver field |
|
337 TBuf8<8> ver; |
|
338 iMachine.RetrieveVer(ver); |
|
339 User::LeaveIfError(suplPosInit->SetVer(ver)); |
|
340 |
|
341 CleanupStack::Pop(suplPosInit); |
|
342 // Ask the Connection Manager to send the SUPL POS INIT message |
|
343 iMachine.Observer().ConnectionManager().SendMessage(suplPosInit, iMachine.SessionId().SessionNum()); |
|
344 |
|
345 // Start the timer that oversees the arrival of SUPL POS |
|
346 iMachine.StartSuplPosTimer(); |
|
347 |
|
348 actionsTaken = ETrue; |
|
349 } |
|
350 else |
|
351 { |
|
352 // Failed to build Location Id |
|
353 err = ETrue; |
|
354 CleanupStack::PopAndDestroy(suplPosInit); |
|
355 } |
|
356 } |
|
357 else |
|
358 { |
|
359 err = ETrue; |
|
360 } |
|
361 |
|
362 if (err) |
|
363 { |
|
364 iMachine.CancelMachine(CSuplFsmSessionBase::ECancelSuplProt, CSuplFsmSessionBase::EReasonNone); |
|
365 } |
|
366 |
|
367 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::EntryActionsFromPosInitSentStateL() End\n"); |
|
368 return actionsTaken; |
|
369 } |
|
370 |
|
371 /** |
|
372 Utility method that builds the capabilities to send in a SUPL POS INIT using LBS's supported |
|
373 capabilities and network preferred positioning method. |
|
374 */ |
|
375 TBool CSuplMtLrStateHandler::BuildCapabilitiesL(TLbsNetPosCapabilities& aCapabilities, TLbsNetPosRequestQuality& aQuality) |
|
376 { |
|
377 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::BuildCapabilitiesL() Begin\n"); |
|
378 TLbsNetPosRequestMethod locReqMethods; |
|
379 TLbsNetPosMethod prefMethod; |
|
380 TInt numMethods; |
|
381 TInt index; |
|
382 TBool ecidSupported = EFalse; |
|
383 TInt additionalMethods = 1; // preferred method |
|
384 |
|
385 iMachine.Observer().Gateway().GetCapabilities(aCapabilities); |
|
386 numMethods = aCapabilities.NumPosMethods(); |
|
387 // Check if E-CID is possible |
|
388 // (currently this mean Timing Advance only) |
|
389 if(iMachine.IsNetworkInfoAvailable()) |
|
390 { |
|
391 RMobilePhone::TMobilePhoneNetworkInfoV1 networkInfo; |
|
392 RMobilePhone::TMobilePhoneLocationAreaV1 locationArea; |
|
393 iMachine.RetrieveStoredNetworkInfo(networkInfo, locationArea); |
|
394 if (RMobilePhone::ENetworkModeGsm == networkInfo.iMode) |
|
395 { |
|
396 RMobilePhone::TMobilePhoneCellInfoV9 cellInfo; |
|
397 if(iMachine.RetrieveStoredCellInfo(cellInfo)) |
|
398 { |
|
399 // Timing Advance not supported if negative |
|
400 ecidSupported = (cellInfo.iTimingAdvance >= 0); |
|
401 additionalMethods++; |
|
402 } |
|
403 } |
|
404 } |
|
405 |
|
406 // Determine what method has been used for this session (prefMethod). |
|
407 // The positioning method preferred by the SLP had been received in the |
|
408 // SUPL INIT message and is kept in the event store. |
|
409 iMachine.RetrieveInitPosMethod(locReqMethods); |
|
410 TLbsNetPosCapabilities capabilities; |
|
411 iMachine.Observer().Gateway().GetCapabilities(capabilities); |
|
412 if (!iMachine.PosMethodSupported(locReqMethods, prefMethod, capabilities) && |
|
413 KLbsPositioningMeansCell != prefMethod.PosMeans()) |
|
414 { |
|
415 // No pos method received from the SLP was used for the session as |
|
416 // no supported method was found. The first method in |
|
417 // the array of capabilities (LBS's preferred) was used instead. Get it. |
|
418 aCapabilities.GetPosMethod(0, prefMethod); |
|
419 } |
|
420 |
|
421 // The prefMethod has to be added at the end of the array of methods in aCapabilities |
|
422 // because that is where the ASN1 encoder expects it to be. |
|
423 // If E-CID is supported and there is room for it in the array, it will also be added to the |
|
424 // array. |
|
425 TLbsNetPosMethod* methods = NULL; |
|
426 if (numMethods + additionalMethods < KLbsMaxNetPosMethods) |
|
427 { |
|
428 TLbsNetPosMethod ecidMethod; |
|
429 ecidMethod.SetPosMethod(KLbsPositioningMeansCell, TPositionModuleInfo::ETechnologyNetwork); |
|
430 methods = new (ELeave) TLbsNetPosMethod[numMethods + additionalMethods]; |
|
431 |
|
432 for (index =0; index < numMethods; index++) |
|
433 { |
|
434 aCapabilities.GetPosMethod(index, methods[index]); |
|
435 } |
|
436 |
|
437 if (ecidSupported) |
|
438 { |
|
439 methods[numMethods] = ecidMethod; |
|
440 } |
|
441 |
|
442 // Add preferred method at the end |
|
443 methods[numMethods + additionalMethods - 1] = prefMethod; |
|
444 aCapabilities.SetPosMethods(methods, numMethods + additionalMethods); |
|
445 } |
|
446 else |
|
447 { |
|
448 // There is only additional room for 1 or 0 methods. |
|
449 methods = new (ELeave) TLbsNetPosMethod[KLbsMaxNetPosMethods]; |
|
450 for (index =0; index < KLbsMaxNetPosMethods; index++) |
|
451 { |
|
452 aCapabilities.GetPosMethod(index, methods[index]); |
|
453 } |
|
454 |
|
455 // Set the preferred method at the end (even if it |
|
456 // overwrites current entry) |
|
457 methods[KLbsMaxNetPosMethods-1] = prefMethod; |
|
458 aCapabilities.SetPosMethods(methods, KLbsMaxNetPosMethods); |
|
459 } |
|
460 |
|
461 delete[] methods; |
|
462 |
|
463 iMachine.RetrieveInitQuality(aQuality); |
|
464 SUPLLOG(ELogP1, "CSuplMtLrStateHandler::BuildCapabilitiesL() End\n"); |
|
465 return ETrue; |
|
466 } |
|
467 |