diff -r f5050f1da672 -r 04becd199f91 javaextensions/wma/mms/src.s60/cmmsplatformservices60impl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaextensions/wma/mms/src.s60/cmmsplatformservices60impl.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,1322 @@ +/* +* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: ?Description + * +*/ + + +// INCLUDE FILES +#include +#include +#include + +#include "logger.h" +#include "fs_methodcall.h" +#include "s60commonutils.h" +#include "cmmsmessageattachment.h" +#include "cmmsplatformservices60impl.h" + +//constants +const TInt KMaxAppIDLength = 34; + +using namespace java::push; +using namespace java::util; + +namespace java +{ +namespace wma +{ +/* ================= MEMBER FUNCTIONS ======================= + * constructor + *------------------------------------------------------------------------------ + * private CMMSPlatformServiceS60Impl + * + *------------------------------------------------------------------------------ + */ +CMMSPlatformServiceS60Impl::CMMSPlatformServiceS60Impl( + const bool aServerConnection, + HBufC* aServerApplicationId, + ConnectionListener* aListener) + :CActive(EPriorityNormal), java::util::FunctionServer("CMMSPlatformService"), + mIsSending(false), mServerConnection(aServerConnection), mNewMessages(0), + mServerApplicationId(aServerApplicationId) +{ + JELOG2(EWMA); + //Creates a new thread and starts active scheduler + //This results in call to doServerSideInit() + createServerToNewThread(); + mSendMsgArray = NULL; + mMessageListener = aListener; +} +/** + * Gets the instance of OS Specific class which implements the interface + * CMMSPlatformService. + * @param aJni - jni interface pointer + * @param aPeer - java side peer reference. + * @param aServerConnection - boolean value to identify client/server + * connection. + * @param aUri - uri on which the connection to be opened. + * @param aListener - listener to be notified about incoming messages. + */ +MMSPlatformService* MMSPlatformService::getInstance(JNIEnv& aJni, + jobject aPeer,const bool aServerConnection,const std::wstring& aUri, + ConnectionListener* aListener) +{ + return CMMSPlatformServiceS60Impl::New(aJni,aPeer,aServerConnection,aUri, + aListener); +} + + +CMMSPlatformServiceS60Impl* CMMSPlatformServiceS60Impl::New(JNIEnv& aJni, + jobject aPeer,const bool aServerConnection,const std::wstring& aUri, + ConnectionListener* aListener) +{ + JELOG2(EWMA); + HBufC* serverApplicationId = NULL; + int error = KErrNone; + if (aServerConnection) + { + serverApplicationId = S60CommonUtils::wstringToDes( + (aUri.substr(7)).c_str()); + } + CMMSPlatformServiceS60Impl * self = new CMMSPlatformServiceS60Impl( + aServerConnection, serverApplicationId, aListener); + error = self->getError(); + if (KErrNone == error) + { + //Attaches the function server thread to VM, to make callbacks to java + //This results in call to vmAttached() + self->attachToVm(aJni, aPeer); + LOG(EWMA, EInfo, "CMMSPlatformServiceS60Impl Successfully attached to VM"); + TRAP(error, self->ConstructL()); + } + if (error != KErrNone) + { + ELOG1(EWMA, "CMMSPlatformServiceS60Impl : Error while opening %d", error); + // If there is any error while opening close the connection + self->closeConnection(aJni,aPeer); + delete self; + throw error; + } + return self; +} + +/**------------------------------------------------------------------------------ + * EPOC default constructor can leave. + * private ConstructL + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::ConstructL() +{ + JELOG2(EWMA); + User::LeaveIfError(mRFs.Connect()); + User::LeaveIfError(mRFs.ShareProtected()); + CreateSendMessageArrayL(); // create send array + mMessageDeliveryDate = TTime(0); + mMmsMessagePriority = EMmsPriorityHigh; + mMessageHandler = CJavaMMSMessageHandler::NewL(mRFs); + // If server connection then check for messages already available in MMS + // message store. + if (mServerConnection) + { + LOG(EWMA, EInfo , "CMMSPlatformServiceS60Impl::ConstructL() Check for" + "any messages availble in message store"); + CallMethodL(this, &CMMSPlatformServiceS60Impl::NotifyReceivedMessageL, + this); + } +} + + +void CMMSPlatformServiceS60Impl::vmAttached() +{ + JELOG2(EWMA); + jclass sessionClass = mJniEnv->FindClass( + "com/nokia/mj/impl/mms/MMSConnectionImpl"); + mSendCallBackMethodId = mJniEnv->GetMethodID(sessionClass, + "messageSentCallback", "(I)V"); + +} +/** + * Returns total number of messages that are arrived + * from opening the connection + */ +int CMMSPlatformServiceS60Impl::getNumberOfMessages() +{ + JELOG2(EWMA); + return mNewMessages; +} +/** + * Does the MMS Engine side initializations .Registers with MMS Engine + * for notification about incoming message in case of server connection. + */ +void CMMSPlatformServiceS60Impl::doServerSideInit() +{ + JELOG2(EWMA); + FunctionServer::doServerSideInit(); + CActiveScheduler::Add(this); + TRAPD(error, + { + mSession = CMsvSession::OpenSyncL(*this); + mClientMtmRegistry = CClientMtmRegistry::NewL(*mSession); + mMmsClient = (CMmsClientMtm *) mClientMtmRegistry->NewMtmL( + KUidMsgTypeMultimedia); + mSendTMsvIdArray = RArray(KArrayGranularity); + mMmsApplicationAdapter = CMmsApplicationAdapter::NewL(); + if (mServerConnection) + { + mServerMmsMtm = (CMmsClientMtm *) mClientMtmRegistry->NewMtmL( + KUidMsgTypeMultimedia); + mReceivedMsgArray = new(ELeave) CArrayPtrSeg + (KArrayGranularity); + TBool isRegister = EFalse; + // If launched by push the application would have already registered + // with mms engine . check before registering. + LOG(EWMA, EInfo , "Checking whether application is already" + "registered or not"); + isRegister = mMmsApplicationAdapter->RegisteredL + (*mServerApplicationId); + // If not registered , register now. + if (!isRegister) + { + TMsvId folderId; + LOG(EWMA, EInfo , "Registering the AppId with MMS engine"); + mMmsApplicationAdapter->RegisterL(*mServerApplicationId,folderId); + isRegister = true; + } + + TMsvId tmsvId = mMmsApplicationAdapter->FolderIdL( + *mServerApplicationId); + if (0 != tmsvId) + { + mRegisterCMsvEntry = mSession->GetEntryL(tmsvId); + // Add listener to the created entry for that application Id + mRegisterCMsvEntry->AddObserverL(*this); + } + + } + }); + mError = error; +} + +/* ----------------------------------------------------------------------------- + * CMMSPlatformServiceS60Impl::Send + * Sends a multimedia message to its recipients. + * ----------------------------------------------------------------------------- + */ +int CMMSPlatformServiceS60Impl::send(JNIEnv& aJniEnv, + jbyteArray aBytes, int aOffset, int aLength, jstring /*aDestination*/) +{ + JELOG2(EWMA); + // put the jbyteArray into the mSendBuffer + delete mSendBuf; // avoid the memory leak + mSendBuf = NULL; + TRAPD(error, + { + mSendBuf = CBufFlat::NewL(aLength); + + // Extends the size of the buffer by the required size + mSendBuf->ExpandL(aOffset, aLength); + + // Transfer the data from java + TPtr8 sendBufPtr = mSendBuf->Ptr(0); + S60CommonUtils::CopyToNative(aJniEnv, aBytes, aOffset, aLength,sendBufPtr); + // If the object is active then it is currently sending a message + // it will also send the newly added message. + iStatus = KRequestPending; + SetActive(); + CallMethodL(this, &CMMSPlatformServiceS60Impl::mmsRequestComplete, + KErrNone,this); + }); + ELOG1(EWMA, "CMMSPlatformServiceS60Impl : status of send %d",error); + return error; +} + +/*------------------------------------------------------------------------------ + * protected SetObjectActive locally + * . + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::mmsRequestComplete(int result) +{ + JELOG2(EWMA); + TRequestStatus *status = &iStatus; + User::RequestComplete(status, result); +} + +/*------------------------------------------------------------------------------ + * Notifies java side about success or failure of sending MMS message + * . + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::NotifySend(JNIEnv& aJni,jobject aPeer, + int aError) +{ + JELOG2(EWMA); + aJni.CallVoidMethod(aPeer, mSendCallBackMethodId, aError); + mIsSending = false; +} + +/*------------------------------------------------------------------------------ + * RunL from CActive + * . + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::RunL() +{ + JELOG2(EWMA); + if (iStatus.Int() ==KErrNone) + { + mIsSending = true; + SendMultiPartMessageL(); + } +} + +/*------------------------------------------------------------------------------ + * protected DoCancel + * Cancel the sending of the message. If the message is in the creation phase + * we can cancel the sending of the message. If the deviec is actually sending + * the message we cannot cancel it. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::DoCancel() +{ + // clean up the entry + JELOG2(EWMA); +} +/*------------------------------------------------------------------------------ + * protected RunError + * . + *------------------------------------------------------------------------------ + */ +TInt CMMSPlatformServiceS60Impl::RunError(TInt aError) +{ + JELOG2(EWMA); + ELOG1(EWMA, "+ In runerror %d this %d", aError); + NotifySend(*mJniEnv, mJavaPeerObject, aError); + return KErrNone; +} +/* ----------------------------------------------------------------------------- + * CMMSPlatformServiceS60Impl::RetrieveMessageL + * Retrieves the first received message from the queue. After delivering the + * message to the caller, the message is removed from the queue. + * ----------------------------------------------------------------------------- + */ +jbyteArray CMMSPlatformServiceS60Impl::retrieveMessage(JNIEnv& aJni) +{ + JELOG2(EWMA); + // check if there is something in the queue + if (mReceivedMMSIDs.Count() <= 0) + { + return NULL; + } + // retrieve the first message whose ID is in the queue + TMsvId id = mReceivedMMSIDs[0]; + mReceivedMMSIDs.Remove(0); + + CMMSMessageInformation* mms = ReceivedMessage(id); + if (!mms) + { + return NULL; + } + CleanupStack::PushL(mms); + + // serialize the received MMS + LOG(EWMA, EInfo , "Serializing the message before giving to java"); + CBufFlat& receiveBuffer = mMessageHandler->SerializeLC(*mms); + // receiveBuffer is on the cleanup stack + TPtr8 receiveBufferPtr = receiveBuffer.Ptr(0); + //get the jbyteArray + TInt dataLength = receiveBuffer.Capacity(); + jbyteArray array = aJni.NewByteArray(dataLength); + S60CommonUtils::CopyToJava(aJni, receiveBufferPtr, array, 0,dataLength); + CleanupStack::PopAndDestroy(&receiveBuffer); // receiveBuffer + CleanupStack::PopAndDestroy(mms); + return array; +} + +/*------------------------------------------------------------------------------ + * public CreateMessageL + * create an empty messsage in draft folder. Later we will add the information + * (attachments addresses, subject etc) + *------------------------------------------------------------------------------ + */ +TMsvId CMMSPlatformServiceS60Impl::CreateMessageL() +{ + JELOG2(EWMA); + TMsvId serviceId = mMmsClient->DefaultServiceL(); + // Context must be set to parent folder for CreateMessageL + mMmsClient->SwitchCurrentEntryL(KMsvDraftEntryId); + mMmsClient->CreateMessageL(serviceId); + CMsvEntry& cmsvEntry = mMmsClient->Entry(); + TMsvId msvId = cmsvEntry.EntryId(); + return msvId; +} + +/*------------------------------------------------------------------------------ + * private DeleteSentMessage + * When the message is gone from the device. Delete the message from + * the sent folder. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::DeleteSentMessageL(TMsvId aMsvId) +{ + JELOG2(EWMA); + TInt index = mSendTMsvIdArray.Find(aMsvId); + if (KErrNotFound == index) + { + return; + } + mSendTMsvIdArray.Remove(index); + DeleteMmsMessageL(aMsvId); +} + +/*------------------------------------------------------------------------------ + * public DeleteMessage + * Delete the message from message store. We are deleting two type of + * multimedia messages.Messages that we send from Java side. When they + * are gone from the device. We delete the message from the sent folder. + * Second is when we receive the message we delete it after + * reading it from Java side. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::DeleteMmsMessageL(TMsvId aMsvId) +{ + JELOG2(EWMA); + LoadMessageL(aMsvId); + CMsvEntry& cmsvEntry = mMmsClient->Entry(); + TMsvEntry tmsvEntry(cmsvEntry.Entry()); + + if ((tmsvEntry.iMtm != KUidMsgTypeMultimedia)||(tmsvEntry.InPreparation())) + { + // It is not MMS or the entry is not ready + return; + } + //Taking a handle to the Sent folder... + TMsvSelectionOrdering sort = cmsvEntry.SortType(); + sort.SetShowInvisibleEntries(ETrue); + // we want to handle also the invisible entries + // Take a handle to the parent entry + CMsvEntry* parentEntry = CMsvEntry::NewL(mMmsClient->Session(), + tmsvEntry.Parent(), sort); + CleanupStack::PushL(parentEntry); // + TRAPD(err, parentEntry->DeleteL(aMsvId)); + if (err != KErrNone) + { + mSession->RemoveEntry(aMsvId); + } + CleanupStack::PopAndDestroy(parentEntry); +} +/*------------------------------------------------------------------------------ + * public LoadMessage + * laod the message from the given TMsvId, + * After this call message will be current message + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::LoadMessageL(TMsvId aMessageEntry) +{ + JELOG2(EWMA); + mMmsClient->SwitchCurrentEntryL(aMessageEntry); + mMmsClient->LoadMessageL(); +} +/*------------------------------------------------------------------------------ + * AddAttachments + * add attachment, location, contentId, and set the message root here + * + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::AddAttachmentsL( + CMMSMessageInformation* aMidMessageInformation) +{ + JELOG2(EWMA); + // Add attachments also set the started ID + CMsvStore* store = mMmsClient->Entry().EditStoreL(); + CleanupStack::PushL(store); + TInt count = aMidMessageInformation->AttachmentCount(); + for (int i = 0; i < count; i++) + { + CMMSMessageAttachment& messageAttachment = + aMidMessageInformation->Attachment(i); + TDesC& fileName = messageAttachment.AttachmentName(); + TDesC8& mimeType8 = messageAttachment.AttachmentType(); + TDesC8& contentLocation8 = messageAttachment.ContentLocationL(); + TDesC8& contentId8 = messageAttachment.ContentIdL(); + TInt charEncoding = messageAttachment.Encoding(); + TDesC* contentLocation = NULL; + S60CommonUtils::ConvertNarrowToWiderLC(contentLocation8,contentLocation); + + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewLC(); + // set the attachment mime type in the CMsvMimeHeaders + if (&mimeType8) + { + TInt position = mimeType8.Find(KSlash); + if (position > 0 && position < mimeType8.Length() - 1) + { + mimeHeaders->SetContentTypeL(mimeType8.Left(position)); + mimeHeaders->SetContentSubTypeL(mimeType8.Mid(position + 1)); + } + else + { + mimeHeaders->SetContentTypeL(mimeType8); + } + } + CMsvAttachment* attachment = CMsvAttachment::NewL( + CMsvAttachment::EMsvFile); + if (contentLocation) + { + mimeHeaders->SetContentLocationL(*contentLocation); + } + // contentId8 can be NULL + if (&contentId8) + { + mimeHeaders->SetContentIdL(contentId8); + } + // set Charset in attachment + if (charEncoding >= 0) + { + mimeHeaders->SetMimeCharset(charEncoding); + } + RFile attaFile; + User::LeaveIfError(attaFile.Open(mRFs, fileName, + EFileShareReadersOnly | EFileRead)); + CleanupClosePushL(attaFile); + TMsvAttachmentId attaId = 0; + // attachment ownerhip will be transferred to Attachment Manager + // It must not be pushed onto the cleanupStack before calling + // CreateAttachment2L + HBufC8* emptyMime = NULL; + if (&mimeType8) + { + mMmsClient->CreateAttachment2L(*store, // edit store + attaFile, // open file handle + mimeType8, + // combination type like image/jpeg + *mimeHeaders, attachment, attaId); + } + else + { + emptyMime = HBufC8::NewLC(0); + mMmsClient->CreateAttachment2L(*store, // edit store + attaFile, // open file handle + *emptyMime, + // combination type like image/jpeg + *mimeHeaders, attachment, attaId); + } + // Now Attachment Manager owns the attachment object, so assign it NULL. + attachment = NULL; + // check also isStarted Id + if (messageAttachment.IsStarterContentId()) + { + mMmsClient->SetMessageRootL(attaId); + } + if (emptyMime) + { + CleanupStack::PopAndDestroy(emptyMime); + } + CleanupStack::PopAndDestroy(&attaFile); // attaFile.Close() + CleanupStack::PopAndDestroy(mimeHeaders); // mimeHeaders + CleanupStack::PopAndDestroy(contentLocation); // contentLocation + } // end of add attachment for loop + + store->CommitL(); + CleanupStack::PopAndDestroy(store); // store +} +/*------------------------------------------------------------------------------ + * public SetSubject + * LoadMessage is called before this method call other wise subject can be set + * to wrong TMsvId + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::SetSubjectL(const TDesC& aSubject) +{ + JELOG2(EWMA); + mMmsClient->SetSubjectL(aSubject); +} +/*------------------------------------------------------------------------------ + * public AddRecipient + * LoadMessage is called before this method call other wise address can be set + * to wrong TMsvId + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::AddRecipientL(const TDesC& aAddress, + TMmsRecipients aAddressType) +{ + JELOG2(EWMA); + mMmsClient->AddAddresseeL(aAddressType, aAddress); +} +/*------------------------------------------------------------------------------ + * public SetApplicationId + * LoadMessage is called before this method call, other wise applicationId can + * be set to wrong TMsvId. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::SetApplicationIdL(const TDesC& aApplicationId) +{ + JELOG2(EWMA); + if (aApplicationId.Length() > 0) + { + TMsvId mvsEntry = mMmsClient->Entry().EntryId(); + mMmsApplicationAdapter->SetApplicationIdL(mvsEntry,aApplicationId); + } +} +/*------------------------------------------------------------------------------ + * SetReplyToApplicationId + * LoadMessage is called before this method call, other wise + * ReplyToApplicationId can be set to wrong TMsvId. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::SetReplyToApplicationIdL( + const TDesC& aReplyToApplicationId) +{ + JELOG2(EWMA); + if (aReplyToApplicationId.Length() > 0) + { + TMsvId mvsEntry = mMmsClient->Entry().EntryId(); + mMmsApplicationAdapter->SetReplyToApplicationIdL(mvsEntry, + aReplyToApplicationId); + } +} +/*------------------------------------------------------------------------------ + * public SendMultiPartMessageL + * ASyn method call to send the message. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::SendMultiPartMessageL() +{ + JELOG2(EWMA); + // convert the byte array into a native multimedia message representation + LOG(EWMA, EInfo , "Converting the byte array into a native multimedia" + "message representation"); + CMMSMessageInformation& mms = mMessageHandler->DeSerializeL(*mSendBuf); + // send it towards the MMS engine + mSendMsgArray->AppendL(&mms); + while (mSendMsgArray->Count() > 0) + { + CMMSMessageInformation* midMessageInformation = + mSendMsgArray->At(0); + CleanupStack::PushL(midMessageInformation); + SendMmsMessageL(midMessageInformation); + mSendMsgArray->Delete(0); + CleanupStack::Pop(midMessageInformation); // midMessageInformation + delete midMessageInformation; + midMessageInformation = NULL; + } +} +/*------------------------------------------------------------------------------ + * public SendMultiMediaMessageL + * Message is send in the following steps + * 1) Create an empty message in the draft folder + * 2) Get the multimeida messsage information from the CMMSMessageInformation + * object and set that information to the newly created multimedia message + * in the following order + * i) Set the subject of the message (Optional) + * ii)Add the destination addresses (to, cc, bcc) + * iii)Add attachments to the message. Attachments are saved in the + * message store. + * vi)Set message setting (Date, time, expiry time, priority, visibility + * of the sender) + * 3) Save the formed message in the message store + * 4) Send the message by using mmsMTMClient. + * 5) When the message is gone from the device delete the message from the sent + * folder. + *----------------------------------------------------------------------------- + */ +void CMMSPlatformServiceS60Impl::SendMmsMessageL( + CMMSMessageInformation* aMidMessageInformation) +{ + JELOG2(EWMA); + TMsvId msvId = CreateMessageL(); + // Add subject + TDesC8& str8 = aMidMessageInformation->MessageSubjectL(); + TDesC* str = NULL; + if (NULL != &str8) + { + S60CommonUtils::ConvertNarrowToWiderL(str8, str); + SetSubjectL(*str); + delete str; + str = NULL; + } + // Add EMsvRecipientTo addresses + TInt i = 0; + TInt count = aMidMessageInformation->AddressesCount(EMsvRecipientTo); + for (i = 0; i < count; i++) + { + AddRecipientL(aMidMessageInformation->MessageAddressL( + EMsvRecipientTo, i), EMsvRecipientTo); + } + // Add EMsvRecipientCc addresses + count = aMidMessageInformation->AddressesCount(EMsvRecipientCc); + for (i = 0; i < count; i++) + { + AddRecipientL(aMidMessageInformation->MessageAddressL( + EMsvRecipientCc, i), EMsvRecipientCc); + } + // Add EMsvRecipientBcc addresses + count = aMidMessageInformation->AddressesCount(EMsvRecipientBcc); + for (i = 0; i < count; i++) + { + AddRecipientL(aMidMessageInformation->MessageAddressL( + EMsvRecipientBcc, i), EMsvRecipientBcc); + } + // Add attachments also set the started ID + AddAttachmentsL(aMidMessageInformation); + // set date and time + TInt64 time = aMidMessageInformation->MessageTime(); + SetMessageSendDate(time); + mMmsMessagePriority = aMidMessageInformation->MessagePriority(); + // set priorty, delivery time, message class, ExpiryInterval, + // sender visibility and delivery report + SetMessageSettingL(); + + // set application-id and reply-to-application-id + TDesC8& id8 = aMidMessageInformation->ApplicationIdL(); + TDesC* id = NULL; + if (NULL != &id8) + { + S60CommonUtils::ConvertNarrowToWiderL(id8, id); + SetApplicationIdL(*id); + delete id; + id = NULL; + } + // Set reply-to-application-Id + TDesC8& rId8 = aMidMessageInformation->ReplyToApplicationIdL(); + if (NULL != &rId8) + { // add reply-to-application-id to currently loaded message + S60CommonUtils::ConvertNarrowToWiderL(rId8, id); + SetReplyToApplicationIdL(*id); + delete id; + id = NULL; + } + SendMmsMessageL(msvId); // send it now + LOG(EWMA, EInfo, "CMMSPlatformServiceS60Impl::SendMmsMessageL Notifying" + "java about the message send status"); + NotifySend(*mJniEnv, mJavaPeerObject, KErrNone); +} +/*----------------------------------------------------------------------------- + * private SendMmsMessageL + * Send the message from the device. This method is called when the + * message is ready to send. All the necessary fields are filled. + * message is send by using mmsClient mtm. + *----------------------------------------------------------------------------- + */ +void CMMSPlatformServiceS60Impl::SendMmsMessageL(TMsvId aSendMmsMsgId) +{ + JELOG2(EWMA); + TMsvEntry tmvsEntry = mMmsClient->Entry().Entry(); + tmvsEntry.SetInPreparation(EFalse); + tmvsEntry.SetVisible(ETrue); + mMmsClient->Entry().ChangeL(tmvsEntry); + // Save the message here to save the last changes made above. + mMmsClient->SaveMessageL(); + // left on CleanupStack + CMsvOperationWait* wait = CMsvOperationWait::NewLC(); + wait->iStatus = KRequestPending; + CMsvOperation* op = NULL; + op = mMmsClient->SendL(wait->iStatus); + wait->Start(); + CleanupStack::PushL(op); + CActiveScheduler::Start(); + mSendTMsvIdArray.AppendL(aSendMmsMsgId); + // The following is to ignore the completion of other active objects. + // It is not needed if the app has a command absorbing control. + while (wait->iStatus.Int() == KRequestPending) + { + CActiveScheduler::Start(); + } + CleanupStack::PopAndDestroy(op); + CleanupStack::PopAndDestroy(wait); +} +/*------------------------------------------------------------------------------ + * protected Set Message Setting + * Set the class, ExpiryInterval, delivery time interval, priority and + * visibility of the sender. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::SetMessageSettingL() +{ + JELOG2(EWMA); + mMmsClient->RestoreSettingsL(); + + mMmsClient->SetMessageClass(EMmsClassPersonal); + // X-Mms-Delivery-Time + mMmsClient->SetDeliveryDate(mMessageDeliveryDate); + + // X-Mms-Priority + mMmsClient->SetMessagePriority(mMmsMessagePriority); + mMmsClient->SetSenderVisibility(EMmsSenderVisibilityShow); + mMmsClient->SetDeliveryReport(EMmsDeliveryReportYes); +} +/*------------------------------------------------------------------------------ + * public SetMessageSendDate + * Set message time in Java format + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::SetMessageSendDate(TInt64& aLong) +{ + JELOG2(EWMA); + if (aLong != 0) + { + mMessageDeliveryDate = S60CommonUtils::JavaTimeToTTime(aLong); + } + else + { + mMessageDeliveryDate = TTime(0); + } +} +/*------------------------------------------------------------------------------ + * public HandleSessionEventL + * EMsvEntriesMoved, + * + * One or more entries have been moved. + * + * aArg1 is a CMsvEntrySelection containing the IDs of the moved entries. + * aArg2 is the TMsvId of the new parent. + * aArg3 is the TMsvId of the old parent entry. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::HandleSessionEventL( + TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* /*aArg3*/) +{ + JELOG2(EWMA); + switch (aEvent) + { + case EMsvEntriesMoved: + { + TMsvId parentId = KMsvNullIndexEntryId; + parentId = *(TMsvId*) aArg2; + + if (parentId == KMsvSentEntryId) + { + // We take the created entries into a selection + CMsvEntrySelection* entries = + static_cast(aArg1); + TInt count = entries->Count(); + LOG1(EWMA, EInfo, "CMMSPlatformServiceS60Impl::HandleSessionEventL" + "Count = %d ", count); + for (TInt i = 0; i < count; i++) + { + LOG1(EWMA, EInfo, "CMMSPlatformServiceS60Impl::" + "HandleSessionEventL number = %d ", i); + TRAP_IGNORE(DeleteSentMessageL(entries->At(i))); + }// end of for loop + } // end of parentid if + break; + } + default: + break; + } +} +/*------------------------------------------------------------------------------ + * private CreateSendMessageArray + * Create the send message TMsvId array. It will be later used to delete the + * messages. We should NOT be deleting the messages send by other application. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::CreateSendMessageArrayL() +{ + JELOG2(EWMA); + ClearAndDestroySendMessageArray(); + mSendMsgArray = new(ELeave) CArrayPtrSeg + (KArrayGranularity); +} +/*------------------------------------------------------------------------------ + * private ClearAndDestroySendMessageArray + * + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::ClearAndDestroySendMessageArray() +{ + JELOG2(EWMA); + if (mSendMsgArray) + { + mSendMsgArray->ResetAndDestroy(); + } + delete mSendMsgArray; + mSendMsgArray = NULL; +} + +/*------------------------------------------------------------------------------ + * public ClearSendMessageArray + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::ClearSendMessageArray() +{ + JELOG2(EWMA); + if (mSendMsgArray) + { + mSendMsgArray->Reset(); + } +} + +/*------------------------------------------------------------------------------ + * public NotifyReceivedMessage + * Message arrive in the device. User was prompted for the MMS message. + * But user do not want to start the midlet. Later (after some time) + * user start the midlet. + * MIDlet will receive all the messages. Following method will notify + * the listener for the received messages. + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::NotifyReceivedMessageL() +{ + JELOG2(EWMA); + TMsvId folderId = KMsvNullIndexEntryId; + folderId = mMmsApplicationAdapter->FolderIdL(*mServerApplicationId); + + if (KMsvNullIndexEntryId != folderId) + { + CMsvEntry* cEntry = mSession->GetEntryL(folderId); + // Show invisible entries + // Sort the entries according to date; + cEntry->SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping, + EMsvSortByDate, ETrue)); + //get the selection array of the messages in sorted order by date + CMsvEntrySelection* msvEntrySelection = + cEntry->ChildrenWithTypeL(KUidMsvMessageEntry); + + //Process each entry, one at a time. + TInt count = msvEntrySelection->Count(); + for (TInt i = 0; i < count; i++) + { + // this checks the entry and handles it if it is targeted + // to midp app we are in startup we do not want to leave here + TRAP_IGNORE(DoReceiveMessageL(msvEntrySelection->At(i))); + }// end of for loop + delete msvEntrySelection; + msvEntrySelection = NULL; + delete cEntry; + cEntry = NULL; + } +} // end of the method NotifyReceivedMessageL + +/*------------------------------------------------------------------------------ + * public HandleEntryEventL + * observer the entry for the specific application Id. + * if a new message is arrived in this folder notify the listener + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::HandleEntryEventL( + TMsvEntryEvent aEvent, TAny* aArg1, TAny*, TAny*) +{ + JELOG2(EWMA); + switch (aEvent) + { + case MMsvSessionObserver::EMsvEntriesChanged: + { + // We take the created entries into a selection + CMsvEntrySelection* entries = + static_cast(aArg1); + //Process each created entry, one at a time. + for (TInt i = 0; i < entries->Count(); i++) + { // this checks the entry and handles it if it is targeted + // to midp app + TRAP_IGNORE(DoReceiveMessageL(entries->At(i))); + } // end of for loop + } + break; + } +} + +/*------------------------------------------------------------------------------ + * private DoReceiveMessageL + * ReceiveMessageL MUST be call from DoReceiveMessageL + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::DoReceiveMessageL(TMsvId aMsvId) +{ + JELOG2(EWMA); + ReceiveMessageL(aMsvId); +} +/*------------------------------------------------------------------------------ + * protected ReceiveMessageL + * + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::ReceiveMessageL(TMsvId aMsvId) +{ + JELOG2(EWMA); + CMsvEntry* csvEntry = mSession->GetEntryL(aMsvId); + TMsvEntry msvEntry = csvEntry->Entry(); + + if (msvEntry.iMtm != KUidMsgTypeMultimedia) + { // It is not MMS, free up the memory of the CMsvEntry + delete csvEntry; + csvEntry = NULL; + return; + } + + if (msvEntry.InPreparation() > 0) + { // message is not ready free up the memory of the CMsvEntry + delete csvEntry; + csvEntry = NULL; + return; // entry is not ready to read + } + + mServerMmsMtm->SwitchCurrentEntryL(aMsvId); + mServerMmsMtm->LoadMessageL(); + + // Check application ID + TPtrC applicationId = mMmsApplicationAdapter->ApplicationIdL(aMsvId); + // Local Copy of the Application ID + TDesC *localCopy_AppId = NULL; + S60CommonUtils::CopyWiderL(applicationId, (TDesC16*&) localCopy_AppId); + // AppId and replyToAppId is not working yet so cannot be tested. + if (mServerApplicationId->Compare(*localCopy_AppId) != 0) + { // received message is not for this connector + delete csvEntry; + csvEntry = NULL; // free the memory + return; + } + TPtrC replyToappId = mMmsApplicationAdapter->ReplyToApplicationIdL(aMsvId); + // Local Copy of reply-to-Application-Id //TDesC16*& + TDesC *localCopy_Reply_To_AppId = NULL; + S60CommonUtils::CopyWiderL(replyToappId,(TDesC16*&)localCopy_Reply_To_AppId); + + // receive message date + TInt64 dateTime; + if (mServerMmsMtm->SendingDate() != TTime(0)) + { + dateTime = S60CommonUtils::TTimeToJavaTime( + mServerMmsMtm->SendingDate()); + } + else + { + dateTime = S60CommonUtils::TTimeToJavaTime(msvEntry.iDate); + } + TDesC *localCopySender = NULL; + // only for emulator in local mode to pass the test on the emulator +#if(defined (__WINS__) || defined(__WINSCW__)) + { + const CMsvRecipientList& recipientList =mServerMmsMtm->AddresseeList(); + TInt recipientCount = recipientList.Count(); + for (TInt j=0; j < recipientCount; j++) + { + const TDesC& address = recipientList[j]; + TMsvRecipientType addressType = recipientList.Type(j); + if (EMsvRecipientTo == addressType) + { + TInt len = S60CommonUtils::CopyWiderL(address,(TDesC16*&) + localCopySender); + break; + } + } + } +#else + { + const TPtrC sender = mServerMmsMtm->Sender(); + S60CommonUtils::CopyWiderL(sender, (TDesC16*&) localCopySender); + } +#endif + + TInt size = mServerMmsMtm->MessageSize(); + TDesC8* applicationId8 = NULL; + CMMSMessageInformation* receiveMsgInformation = + CMMSMessageInformation::NewL(*localCopySender, dateTime, + *applicationId8, aMsvId); + CleanupStack::PushL(receiveMsgInformation); + + const CMsvRecipientList& recipientList = mServerMmsMtm->AddresseeList(); + TInt recipientCount = recipientList.Count(); + TDesC16* messageAddress; + for (TInt j = 0; j < recipientCount; j++) + { + messageAddress = NULL; + const TDesC& address = recipientList[j]; + TMsvRecipientType addressType = recipientList.Type(j); + S60CommonUtils::CopyWiderL(address, messageAddress); + receiveMsgInformation->AddAddressL((TMsvRecipientTypeValues)addressType, + messageAddress); + } + + receiveMsgInformation->SetApplicationIdL(*localCopy_AppId); + receiveMsgInformation->SetReplyToApplicationIdL(*localCopy_Reply_To_AppId); + receiveMsgInformation->SetMessageSize(size); + TPtrC subject = mServerMmsMtm->SubjectL(); + receiveMsgInformation->SetMessageSubjectL(subject); + TMmsMessagePriority priority = + (TMmsMessagePriority) mServerMmsMtm->MessagePriority(); + receiveMsgInformation->SetMessagePriority(priority); + ReadAttachmentsL(*receiveMsgInformation); + + mReceivedMsgArray->AppendL(receiveMsgInformation); + CleanupStack::Pop(receiveMsgInformation); + + delete csvEntry; + csvEntry = NULL; + delete localCopy_Reply_To_AppId; + localCopy_Reply_To_AppId = NULL; + delete localCopy_AppId; + localCopy_AppId = NULL; + delete localCopySender; + localCopySender = NULL; + + HBufC* buf = HBufC::NewLC(KMaxAppIDLength); + TPtr ptr = buf->Des(); + ptr.SetLength(0); // make sure that there is no garbage + ptr.AppendNum(aMsvId); + NotifyJava(*buf, 1); + CleanupStack::PopAndDestroy(buf); //buf + TRAP_IGNORE(DeleteMmsMessageL(aMsvId)); +} + +/*------------------------------------------------------------------------------ + * Notifies the message listener about the incoming message + * . + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::NotifyJava(const TDesC& aDescription, + int aMessages) +{ + JELOG2(EWMA); + TLex lex(aDescription); + TMsvId ID; + lex.Val(ID); + TRAP_IGNORE(mReceivedMMSIDs.AppendL(ID)); + mNewMessages += aMessages; + mMessageListener->msgArrived(); +} +/*------------------------------------------------------------------------------- + * void ReadAttachmentsL(CMMSMessageInformation& aMidMessageInformation) + * + *------------------------------------------------------------------------------- + */ +void CMMSPlatformServiceS60Impl::ReadAttachmentsL( + CMMSMessageInformation& aMidMessageInformation) +{ + JELOG2(EWMA); + // Find root attachment + TMsvAttachmentId rootId = mServerMmsMtm->MessageRootAttachment(); + CMsvStore* store = mServerMmsMtm->Entry().ReadStoreL(); + CleanupStack::PushL(store); + MMsvAttachmentManager& attaMan = store->AttachmentManagerL(); + CMsvAttachment* msvAttachment = NULL; + TInt attaCount = attaMan.AttachmentCount(); + + for (TInt i = 0; i < attaCount; i++) + { + msvAttachment = attaMan.GetAttachmentInfoL(i); + CleanupStack::PushL(msvAttachment); + // open other message part + // get mime header + CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewLC(); + mimeHeaders->RestoreL(*msvAttachment); + + TMsvAttachmentId attachmentId = msvAttachment->Id(); + RFile attaFile = attaMan.GetAttachmentFileL(attachmentId); + TDesC8* dataArray8 = NULL; + ReadDataFromAttachFileL(attaFile, dataArray8); + CleanupStack::PushL(dataArray8); + attaFile.Close(); + // mimetype and encoding from mime header + const TDesC8& attachmentType8 = mimeHeaders->ContentType(); + const TDesC8& attachmentSubType8 = mimeHeaders->ContentSubType(); + HBufC8* attachmentTypeBuf8 = HBufC8::NewLC(attachmentType8.Length() + + attachmentSubType8.Length() + + KSlashLength + + KSlashLength); + TPtr8 ptr = attachmentTypeBuf8->Des(); + ptr.SetLength(0); + ptr.Append(attachmentType8); + ptr.Append(KSlash); + ptr.Append(attachmentSubType8); + // Get the values of content-id, content-location + const TDesC8& contentId8 = mimeHeaders->ContentId(); + const TDesC& location = mimeHeaders->ContentLocation(); + TDesC8* location8 = NULL; + // Check for the content location if we have the same string that + // we use for sending remove the content location. + if ((&location) && location.Find(KTempMmsAttachmentName)== KErrNotFound) + { + S60CommonUtils::ConvertWiderToNarrowL(location, location8); + } + TInt size = msvAttachment->Size(); + + CMMSMessageAttachment* midAttachment = + CMMSMessageAttachment::NewL(mRFs, *dataArray8, + *attachmentTypeBuf8, contentId8, *location8, + false); + + CleanupStack::PushL(midAttachment); + + TUint charEncoding = mimeHeaders->MimeCharset(); + midAttachment->SetEncoding(charEncoding); + + if (attachmentId == rootId) + { + midAttachment->SetStarterContentId(true); + } + aMidMessageInformation.InsertAttachmentL(midAttachment); + CleanupStack::Pop(midAttachment); // midAttachment + + delete location8; + location8 = NULL; // location8 + // attachmentTypeBuf8 + CleanupStack::PopAndDestroy(attachmentTypeBuf8); + CleanupStack::Pop(dataArray8); // dataArray8 + // mimeHeaders, attaInfo + CleanupStack::PopAndDestroy(mimeHeaders); + // mimeHeaders, attaInfo + CleanupStack::PopAndDestroy(msvAttachment); + } + CleanupStack::PopAndDestroy(store); // store +} +/*------------------------------------------------------------------------------- + * + *------------------------------------------------------------------------------- + */ +void CMMSPlatformServiceS60Impl::ReadDataFromAttachFileL(RFile& aRFile, + TDesC8*& aDataArray) +{ + JELOG2(EWMA); + TInt size = 0; + TInt error = KErrNotFound; + error = aRFile.Size(size); + if (error == KErrNone) + { + HBufC8* buffer = HBufC8::NewL(size); + if (buffer) + { + TPtr8 ptr = buffer->Des(); + error = aRFile.Read(ptr, size); //read the data in the file + } + aDataArray = buffer; + } +} + +/*------------------------------------------------------------------------------ + * public ReceivedMessage(TMsvId aMessageId) + * + *------------------------------------------------------------------------------ + */ +CMMSMessageInformation* CMMSPlatformServiceS60Impl::ReceivedMessage( + TMsvId aMessageId) +{ + JELOG2(EWMA); + CMMSMessageInformation* msgInfo = NULL; + TInt count = mReceivedMsgArray->Count(); + for (TInt i = 0; i < count; i++) + { + CMMSMessageInformation* mi =(CMMSMessageInformation*) + mReceivedMsgArray->At(i); + if (aMessageId == mi->MessageMsvId()) //check for the message Id + { + msgInfo = mi; // that is the message we are looking for. + mReceivedMsgArray->Delete(i); + break; + } + } + return msgInfo; +} + +/*------------------------------------------------------------------------------ + * public destructor + * + *------------------------------------------------------------------------------ + */ +CMMSPlatformServiceS60Impl::~CMMSPlatformServiceS60Impl() +{ + JELOG2(EWMA); + detachFromVm(); + stopServer(); +} +void CMMSPlatformServiceS60Impl::closeConnection(JNIEnv& aJni, jobject aPeer) +{ + JELOG2(EWMA); + // If sending of a message is being carried out unblock the java side with + // KErrCancel. + if (mIsSending) + { + NotifySend(aJni, aPeer, KErrCancel); + } + // Close() Needs to be called in function server thread + TRAP_IGNORE(CallMethodL(this, &CMMSPlatformServiceS60Impl::Close, this)); +} +/*------------------------------------------------------------------------------ + * private close + * + *------------------------------------------------------------------------------ + */ +void CMMSPlatformServiceS60Impl::Close() +{ + JELOG2(EWMA); + if (mServerConnection) + { + mReceivedMMSIDs.Close(); + if (mRegisterCMsvEntry) + { + mRegisterCMsvEntry->RemoveObserver(*this); + delete mRegisterCMsvEntry; + mRegisterCMsvEntry = NULL; + } + if (mServerMmsMtm) + { + delete mServerMmsMtm; + mServerMmsMtm = NULL; + } + if (mReceivedMsgArray) + { + mReceivedMsgArray->ResetAndDestroy(); + delete mReceivedMsgArray; + mReceivedMsgArray = NULL; + } + // Unregistering from MMS Engine. + LOG(EWMA, EInfo , "CMMSPlatformServiceS60Impl::Close() Unregistering" + "from MMS Engine"); + mMmsApplicationAdapter->UnregisterL(*mServerApplicationId); + if (mServerApplicationId) + { + delete mServerApplicationId; + mServerApplicationId = NULL; + } + } + if (mMmsClient) + { + delete mMmsClient; + mMmsClient = NULL; + } + + if (mClientMtmRegistry) + { + delete mClientMtmRegistry; + mClientMtmRegistry = NULL; + } + + if (mSession) + { + delete mSession; + mSession = NULL; + } + + if (mMmsApplicationAdapter) + { + delete mMmsApplicationAdapter; + mMmsApplicationAdapter = NULL; + } + mSendTMsvIdArray.Close(); + + if (mSendMsgArray) + { + mSendMsgArray->ResetAndDestroy(); + delete mSendMsgArray; + mSendMsgArray = NULL; + } + if (mMessageHandler) + { + delete mMessageHandler; + mMessageHandler = NULL; + } +} +// End of File +} //namespace wma +} //namespace java +