December 19, 2014
Hot Topics:

Inter-Application Communication in BREW

  • July 23, 2004
  • By Radu Braniste
  • Send Email »
  • More Articles »

Other things to have in mind:

  • Suspend/resume the caller or simply start/stop it? Take into account that launching any application (in the background or not) consumes memory; releasing the caller might free precious space.
  • Should the callee be a background application, become the active process, or simply be resurrected and put in the background for the duration of the call? All these behaviors are possible (see above for more details) and choosing one over the other is simply a matter of design and requirements.

A Short Example

The example consists of two applications (<cppapp> and <cppapp1>) and one extension (<extension>). <cppapp> contains the same code as [3] and is practically a client for <cppapp1>. <extension> is the component used by both application, hosting the pipe. The interface <extension> exposes is minimal:

QINTERFACE(IExtensionCls)
{
   DECLARE_IBASE(IExtensionCls)
   int  (*PipeWrite)(IExtensionCls * po, const char* data);
   int  (*PipeRead)(IExtensionCls * po, char* data);
};

and the implementation trivial:

static int ExtensionCls_PipeWrite(IExtensionCls * po, const char* v)
{
   IFileMgr* fmgr = 0;
   IShell* s = ((AEEApplet*)GETAPPINSTANCE())->m_pIShell;
   int err = ISHELL_CreateInstance(s, AEECLSID_FILEMGR, (void **)&fmgr);
   if(err != SUCCESS) return err;
   const char fn[]=AEE_SHARED_DIR"/pipe";
   IFILEMGR_Remove(fmgr, fn);
   IFile* fl( IFILEMGR_OpenFile(fmgr, fn , _OFM_CREATE));
   err = fl ? SUCCESS : EFAILED;
   if (fl)
   {
      IFILE_Write(fl, v, 32);
      IFILE_Release(fl);
   }
   IFILEMGR_Release(fmgr);
   return err;
}
static int ExtensionCls_PipeRead(IExtensionCls * po, char* v)
{
   IFileMgr* fmgr = 0;
   IShell* s = ((AEEApplet*)GETAPPINSTANCE())->m_pIShell;
   int err = ISHELL_CreateInstance(s, AEECLSID_FILEMGR, (void **)&fmgr);
   if(err != SUCCESS)  return err;
   const char fn[]=AEE_SHARED_DIR"/pipe";
   IFile* fl( IFILEMGR_OpenFile(fmgr, fn , _OFM_READ));
   err = fl ? SUCCESS : EFAILED;
   if (fl)
   {
      IFILE_Read(fl, v, 32);
      IFILE_Release(fl);
   }
   IFILEMGR_Release(fmgr);
   return err;
}

Obvious improvements would be the use of smart pointers to access BREW interfaces (see BrewIPtr in [4]) and refactoring the two methods, but this is beyond the scope of this article. This code is based on a fixed-size pipe, but the variable size can be easily implemented as discussed previously.

<cppapp1> has two methods to initiate communication:

static void placeCommand(AEECLSID cls, int command, uint32 params=0)
{
   IShell* s = ((AEEApplet*)GETAPPINSTANCE())->m_pIShell;
      ISHELL_StartApplet(s, cls);
      ISHELL_PostEvent(s, cls, EVT_USER, command , params);
}
   static void shareData()
   {
      IExtensionCls* e = 0;
      IShell* s = ((AEEApplet*)GETAPPINSTANCE())->m_pIShell;
      if(ISHELL_CreateInstance(s, AEECLSID_EXTENSION_CLS,
                               (void **)&e) != SUCCESS)
            return ;
      const char v[] = "TEST";
      IEXTCLS_PipeWrite(e, v);
      IEXTCLS_Release(e);
   }

Commands are decoded in the EVT_USER section of the HandleEvent method of <cppapp>. <cppapp> has only one relevant method:

static void readSharedData()
   {
      IExtensionCls* e = 0;
      IShell* s = ((AEEApplet*)GETAPPINSTANCE())->m_pIShell;
      if(ISHELL_CreateInstance(s, AEECLSID_EXTENSION_CLS,
                               (void **)&e) != SUCCESS)
            return ;
      char v[32];
      IEXTCLS_PipeRead(e, v);
      IEXTCLS_Release(e);
   }

How it works:

<cppapp1> asks <cppapp> to execute a command like:

placeCommand(AEECLSID_CPPAPP, 1, 700);

This is a very simple protocol using only one unsigned long paramter. <cppapp> will consequently execute:

test1(dwParam);
where dwParam = 700.

More complexes cases need more data being transferred:

placeCommand(AEECLSID_CPPAPP, 2, (uint32)address);
shareData();

<cppapp> simply reads the data passed to it and responds in a similar manner:

readSharedData();
   ISHELL_PostEvent(((AEEApplet*)GETAPPINSTANCE())->m_pIShell,
                      AEECLSID_CPPAPP_1, EVT_USER, 1 , 0);
   ISHELL_CloseApplet(((AEEApplet*)GETAPPINSTANCE())->
                        m_pIShell, false); 

Please note that <cppap1> is a minimal example and provides no support for suspend/resume.

Downloads

Download the example files here.

References

  1. Don Box, Keith Brown, Tim Ewald, Chris Sells: Effective COM: 50 Ways to Improve Your COM and MTS-based Applications, Addison-Wesley, 1998
  2. Background Applications: https://brewx.qualcomm.com/bws/.../docs/bg_apps.pdf
  3. C++ Idioms in BREW, Part 2: http://www.developer.com/ws/brew/article.php/3370971
  4. Small Memory Allocation, Part 3 http://www.developer.com/ws/brew/article.php/3340611




Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Sitemap | Contact Us

Rocket Fuel