diff --git a/runtimes/cpp/base/Syscall.cpp b/runtimes/cpp/base/Syscall.cpp index c8b037e31..99be5c145 100644 --- a/runtimes/cpp/base/Syscall.cpp +++ b/runtimes/cpp/base/Syscall.cpp @@ -986,6 +986,7 @@ namespace Base { #if !defined(_android) int Syscall::maBtGetNewDevice(MABtDevice* dst) { MABtDeviceNative dn; + dn.nameBufSize = dst->nameBufSize; dn.name = (char*)GetValidatedMemRange(dst->name, dst->nameBufSize); int res = BLUETOOTH(maBtGetNewDevice)(&dn); dst->actualNameLength = dn.actualNameLength; @@ -999,6 +1000,7 @@ namespace Base { if(res <= 0) return res; MABtServiceNative sn; + sn.nameBufSize = dst->nameBufSize; sn.name = (char*)GetValidatedMemRange(dst->name, dst->nameBufSize); sn.uuids = (MAUUID*)GetValidatedMemRange(dst->uuids, ss.nUuids * sizeof(MAUUID)); res = BLUETOOTH(maBtGetNewService)(&sn); diff --git a/runtimes/cpp/base/networking.h b/runtimes/cpp/base/networking.h index 49a630316..278ae37f1 100644 --- a/runtimes/cpp/base/networking.h +++ b/runtimes/cpp/base/networking.h @@ -129,9 +129,13 @@ class ConnOp : public Runnable { ConnOp(MAConn& m) : mac(m) {} MAConn& mac; - void handleResult(int opcode, int result) { + void handleResult(int opcode, int result, bool lock = true) { LOGST("ConnOp::handleResult %i %i %i", mac.handle, opcode, result); - if(result < 0 && mac.cancel) { + if(lock) + { + gConnMutex.lock(); + } + if(result < 0 && mac.cancel) { result = CONNERR_CANCELED; } DEBUG_ASSERT(mac.state & opcode); @@ -145,6 +149,10 @@ class ConnOp : public Runnable { mac.state &= ~opcode; ConnPushEvent(ep); //send event to be processed + if(lock) + { + gConnMutex.unlock(); + } } }; @@ -160,11 +168,7 @@ class Connect : public ConnStreamOp { Connect(MAStreamConn& m) : ConnStreamOp(m) {} void run() { LOGST("Connect %i", mac.handle); - gConnMutex.lock(); - { - handleResult(CONNOP_CONNECT, masc.conn->connect()); - } - gConnMutex.unlock(); + handleResult(CONNOP_CONNECT, masc.conn->connect()); } }; @@ -173,11 +177,7 @@ class ConnRead : public ConnStreamOp { ConnRead(MAStreamConn& m, void* d, int s) : ConnStreamOp(m), dst(d), size(s) {} void run() { LOGST("ConnRead %i", mac.handle); - gConnMutex.lock(); - { - handleResult(CONNOP_READ, masc.conn->read(dst, size)); - } - gConnMutex.unlock(); + handleResult(CONNOP_READ, masc.conn->read(dst, size)); } private: void* dst; @@ -189,11 +189,7 @@ class ConnWrite : public ConnStreamOp { ConnWrite(MAStreamConn& m, const void* sr, int si) : ConnStreamOp(m), src(sr), size(si) {} void run() { LOGST("ConnWrite %i", mac.handle); - gConnMutex.lock(); - { - handleResult(CONNOP_WRITE, masc.conn->write(src, size)); - } - gConnMutex.unlock(); + handleResult(CONNOP_WRITE, masc.conn->write(src, size)); } private: const void* src; @@ -206,13 +202,12 @@ class ConnReadToData : public ConnStreamOp { : ConnStreamOp(m), dst(d), handle(h), offset(o), size(s) {} void run() { LOGST("ConnReadToData %i", mac.handle); + int result = masc.conn->read((byte*)dst.ptr() + offset, size); gConnMutex.lock(); { - int result = masc.conn->read((byte*)dst.ptr() + offset, size); - DefluxBinPushEvent(handle, dst); - handleResult(CONNOP_READ, result); + handleResult(CONNOP_READ, result, false); } gConnMutex.unlock(); @@ -230,24 +225,24 @@ class ConnWriteFromData : public ConnStreamOp { : ConnStreamOp(m), src(sr), handle(h), offset(o), size(si) {} void run() { LOGST("ConnWriteFromData %i", mac.handle); - gConnMutex.lock(); - { - int result; - if(src.ptrc() != NULL) { - result = masc.conn->write((byte*)src.ptrc() + offset, size); + + int result; + if(src.ptrc() != NULL) { + result = masc.conn->write((byte*)src.ptrc() + offset, size); + } else { + Smartie temp(new byte[size]); + if(!src.read(temp(), size)) { + LOG("Stream error in ConnWriteFromData!\n"); + result = CONNERR_GENERIC; } else { - Smartie temp(new byte[size]); - if(!src.read(temp(), size)) { - LOG("Stream error in ConnWriteFromData!\n"); - result = CONNERR_GENERIC; - } else { - result = masc.conn->write(temp(), size); - } + result = masc.conn->write(temp(), size); } - + } + gConnMutex.lock(); + { DefluxBinPushEvent(handle, src); - handleResult(CONNOP_WRITE, result); + handleResult(CONNOP_WRITE, result, false); } gConnMutex.unlock(); @@ -264,11 +259,7 @@ class HttpFinish : public ConnOp { HttpFinish(MAConn& m, HttpConnection& h) : ConnOp(m), http(h) {} void run() { LOGST("HttpFinish %i", mac.handle); - gConnMutex.lock(); - { - handleResult(CONNOP_FINISH, http.finish()); - } - gConnMutex.unlock(); + handleResult(CONNOP_FINISH, http.finish()); } private: HttpConnection& http; @@ -280,20 +271,16 @@ class Accept : public ConnOp { void run() { LOGST("Accept %i\n", mac.handle); BtSppConnection* conn; - gConnMutex.lock(); - { - int res = masc.serv->accept(conn); - if(res < 0) { - handleResult(CONNOP_ACCEPT, res); - return; - } + int res = masc.serv->accept(conn); + if(res < 0) { + handleResult(CONNOP_ACCEPT, res); + return; + } //success. let's store our new connection. - MAConn* newMac = new MAStreamConn(gConnNextHandle, conn); - gConnections.insert(ConnPair(gConnNextHandle, newMac)); - handleResult(CONNOP_ACCEPT, gConnNextHandle++); - } - gConnMutex.unlock(); + MAConn* newMac = new MAStreamConn(gConnNextHandle, conn); + gConnections.insert(ConnPair(gConnNextHandle, newMac)); + handleResult(CONNOP_ACCEPT, gConnNextHandle++); } private: MAServerConn& masc; diff --git a/testPrograms/ParallelDownloader/.cproject b/testPrograms/ParallelDownloader/.cproject new file mode 100644 index 000000000..741d7ef50 --- /dev/null +++ b/testPrograms/ParallelDownloader/.cproject @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/testPrograms/ParallelDownloader/.mosyncproject b/testPrograms/ParallelDownloader/.mosyncproject new file mode 100644 index 000000000..0577ca958 --- /dev/null +++ b/testPrograms/ParallelDownloader/.mosyncproject @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testPrograms/ParallelDownloader/.project b/testPrograms/ParallelDownloader/.project new file mode 100644 index 000000000..0171d9da6 --- /dev/null +++ b/testPrograms/ParallelDownloader/.project @@ -0,0 +1,30 @@ + + + ParallelDownloader + + + + + + com.mobilesorcery.sdk.core.builder + + + + + + com.mobilesorcery.sdk.core.nature + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + + + + 0 + + 6 + + org.eclipse.ui.ide.multiFilter + 1.0-name-matches-false-true-.*rebuild.build.cpp + + + + diff --git a/testPrograms/ParallelDownloader/.settings/org.eclipse.core.resources.prefs b/testPrograms/ParallelDownloader/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..15e561682 --- /dev/null +++ b/testPrograms/ParallelDownloader/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,3 @@ +#Wed Aug 15 15:13:56 CEST 2012 +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/testPrograms/ParallelDownloader/main.cpp b/testPrograms/ParallelDownloader/main.cpp new file mode 100644 index 000000000..5f617fb4a --- /dev/null +++ b/testPrograms/ParallelDownloader/main.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include + +using namespace MAUtil; + +#include "webImageDownloader.h" +/* + * 8 is the limit of consecutive downloads for Symbian, + * other platforms can do better. + * 32 is the limit on iOS. + */ +#define NUM_DOWNLOADS 8 +#define NUM_BATCHES 10 + +/** + * Moblet for the application. + */ +class myMoblet : public Moblet, public webImageDownloaderListener { +public: + myMoblet() + { + mBatchNumber = 0; + + printf("Number of parallel downloads:%d, number of batches:%d", NUM_DOWNLOADS, NUM_BATCHES); + startDownloads(); + + + } + + void startDownloads() + { + mFinishedDownloaders = 0; + MAUtil::String url = "http://www.mosync.com/miles/Web%20Scottish%20Loch.jpg"; + mBatchNumber++; + printf("STARTING DOWNLOAD BATCH %d", mBatchNumber); + for(int i = 0; i < NUM_DOWNLOADS; i++) + { + webImageDownloader * imagedownload = new webImageDownloader(url, "newdataname1", this); + } + } + + void downloadFinished(webImageDownloader *downloader) + { + delete downloader; + mFinishedDownloaders++; + + if(mFinishedDownloaders == NUM_DOWNLOADS) + { + if(mBatchNumber < NUM_BATCHES) + { + startDownloads(); + } + else + { + printf("TEST PASSED"); + } + } + } + + void myMoblet::init() {} + void myMoblet::draw() {} + + /** + * Destructor. + */ + virtual ~myMoblet(){} + +private: + int mFinishedDownloaders; + int mBatchNumber; +}; + +extern "C" int MAMain() +{ + InitConsole(); + gConsoleLogging = 1; + + // Run the moblet event loop. + //Moblet::run(moblet); + Moblet::run(new myMoblet()); + + // Deallocate objects. + //delete Moblet; + return 0; +} diff --git a/testPrograms/ParallelDownloader/webImageDownloader.cpp b/testPrograms/ParallelDownloader/webImageDownloader.cpp new file mode 100644 index 000000000..b87c224c5 --- /dev/null +++ b/testPrograms/ParallelDownloader/webImageDownloader.cpp @@ -0,0 +1,41 @@ +#include "webImageDownloader.h" + +webImageDownloader::webImageDownloader(MAUtil::String data, MAUtil::String dataId, webImageDownloaderListener *listener){ + imageDownloader = new Downloader(); + imageDownloader->addDownloadListener(this); + mWebListener = listener; + mImageResource = maCreatePlaceholder(); + printf("Placeholder:%d",mImageResource); + imageDownloader->beginDownloading(data.c_str(), mImageResource); +} + +webImageDownloader::~webImageDownloader(){} + +void webImageDownloader::finishedDownloading(Downloader *dl, MAHandle data){ + printf("finished downloading"); + + if(dl == imageDownloader) { + printf("beginning"); + + printf("datasize = %d", maGetDataSize(data)); + printf("MImage:%d data:%d", mImageResource, data); + MAHandle mystore = maOpenStore("teststore.jpg", MAS_CREATE_IF_NECESSARY); + if(mystore != STERR_NONEXISTENT) { + MAHandle myData = maCreatePlaceholder(); + //if(maCreateData(myData, maGetDataSize(data)) == RES_OK) { + // maWriteData(myData, text.c_str(), 0, maGetDataSize(data)); + //} + int result = maWriteStore(mystore, data); + maCloseStore(mystore, 0); + maDestroyPlaceholder(myData); + } + maDestroyPlaceholder(mImageResource); + mWebListener->downloadFinished(this); + printf("end of downloader"); + } +} + +void webImageDownloader::error(Downloader* dl, int code) { } +//maAlert("error", "", "ok", 0, 0);} +void webImageDownloader::downloadCancelled(Downloader* dl) {} +void webImageDownloader::notifyProgress(Downloader *dl, int downloadedBytes, int totalBytes){} diff --git a/testPrograms/ParallelDownloader/webImageDownloader.h b/testPrograms/ParallelDownloader/webImageDownloader.h new file mode 100644 index 000000000..c1ad9662a --- /dev/null +++ b/testPrograms/ParallelDownloader/webImageDownloader.h @@ -0,0 +1,43 @@ +#ifndef WEBIMAGEDOWNLOADER_H_ +#define WEBIMAGEDOWNLOADER_H_ + +#include +#include +#include +#include +#include +#include + +#include // Syscalls +#include // C++ String class +#include + +using namespace MAUtil; +class webImageDownloader; +class webImageDownloaderListener { +public: + virtual void downloadFinished(webImageDownloader *downloader) = 0; +}; + +class webImageDownloader : public DownloadListener { +public: + webImageDownloader(MAUtil::String data, MAUtil::String dataId, webImageDownloaderListener *listener); + virtual ~webImageDownloader(); + + void notifyProgress(Downloader *dl, int downloadedBytes, int totalBytes); + void error(Downloader* dl, int code); + void downloadCancelled(Downloader* dl); + + void finishedDownloading(Downloader *dl, MAHandle data); + + MAHandle newPlaceholder; + + MAHandle mImageResource; + Downloader * imageDownloader; + + DownloadListener * listener; + webImageDownloaderListener *mWebListener; +}; + + +#endif /* WEBIMAGEDOWNLOADER_H_ */ diff --git a/testPrograms/notification/PushNotificationReceiver/Config.h b/testPrograms/notification/PushNotificationReceiver/Config.h new file mode 100644 index 000000000..7c70309e1 --- /dev/null +++ b/testPrograms/notification/PushNotificationReceiver/Config.h @@ -0,0 +1,17 @@ +/* + * @file Config.h + * + * Before you can build and run the sample application on Android, you need to fill the GCM_PROJECT_ID + * field, that is the Google API project ID you obtained when enabling GCM service: + * http://developer.android.com/guide/google/gcm/gs.html + * + * @author emma + */ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#define GCM_PROJECT_ID "YourProjectIdHere" + + +#endif /* CONFIG_H_ */ diff --git a/testPrograms/notification/PushNotificationReceiver/MainScreen.cpp b/testPrograms/notification/PushNotificationReceiver/MainScreen.cpp index b236a01de..0c2c8fd9a 100644 --- a/testPrograms/notification/PushNotificationReceiver/MainScreen.cpp +++ b/testPrograms/notification/PushNotificationReceiver/MainScreen.cpp @@ -29,8 +29,7 @@ MA 02110-1301, USA. #include "TCPConnection.h" #include "HTTPConnection.h" #include "Util.h" - -#define GCM_PROJECT_ID "yourProjectId_here" +#include "Config.h" /** * Constructor. diff --git a/testPrograms/notification/PushNotificationReceiver/ReadMe.txt b/testPrograms/notification/PushNotificationReceiver/ReadMe.txt index 0166b9151..4c0fd5b58 100644 --- a/testPrograms/notification/PushNotificationReceiver/ReadMe.txt +++ b/testPrograms/notification/PushNotificationReceiver/ReadMe.txt @@ -1,11 +1,16 @@ +Enable Android GCM service following these steps: http://developer.android.com/guide/google/gcm/gs.html , and write down +the Google API project ID of the registered account. + +Android server setup steps can be found here: http://developer.android.com/guide/google/gcm/demo.html#webserver-setup + Android requirements: + - Complete Config.h file, by filling the GCM_PROJECT_ID field: that is the Google API project ID you obtained in the service enabling steps above. - The device must be running Android 2.2 or higher and have the Market application installed. - an existing connection for Google services. This requires users to set up their Google account on their mobile devices. - to use it on the emulator you need to emulate a device with Google API 8 or higher. You also have to register a Google user on the virtual device under Settings > Accounts Sync. The application consists of a Tab Screen with 2 Screens: - 1. The received Notification screen. Here you will see all the info related to the latest received push notification: - on IOS the badge number @@ -15,6 +20,8 @@ Here you will see all the info related to the latest received push notification: On iOS the registration_id is sent to the server via a TCP connection, while on Android it's sent using an HTTP connection ( This is because the GCM server-demo web server supplied by Google is waiting for the registration via an HTTP POST). Follow this link for setting up the Web server for Android: http://developer.android.com/guide/google/gcm/demo.html#webserver-setup +<> Remember to press Connect after you got the registration result - you will be updated in the 2nd screen when this occurs. Also, remember that on Android the registration is done only once per app and so you don't need to connect to the server more that once. @@ -28,4 +35,4 @@ When the app is launched it will automatically try to register for push notifica - On iOS the registration process is done every time the app is launched. -On Android the registration is done only the first time the app is launched. Because it is recommended that the application registers with Google GCM only the first time it’s launched, and then stores the registration ID for later use. Due to this, - the server side should wait for the REGISTRATION_ID only once. + the server side should wait for the REGISTRATION_ID only once. If you wish to register again you should go to Settings->Apps ->PushNotificationReceiver and ClearData or Uninstall. diff --git a/testPrograms/notification/PushNotificationReceiver/SettingsScreen.cpp b/testPrograms/notification/PushNotificationReceiver/SettingsScreen.cpp index f36ea0511..fb8dae4b8 100644 --- a/testPrograms/notification/PushNotificationReceiver/SettingsScreen.cpp +++ b/testPrograms/notification/PushNotificationReceiver/SettingsScreen.cpp @@ -92,8 +92,6 @@ SettingsScreen::SettingsScreen(SettingsScreenListener* listener): mShowOnlyIfInBackground->addCheckBoxListener(this); } - mIPEditBox->setText("192.168.1.111"); - mPortEditBox->setText("6789"); Notification::NotificationManager::getInstance()->setPushNotificationsTickerText(mTickerText->getText()); Notification::NotificationManager::getInstance()->setPushNotificationsTitle(mContentTitle->getText()); } @@ -159,6 +157,9 @@ void SettingsScreen::createMainLayout() mPortEditBox->setInputMode(EDIT_BOX_INPUT_MODE_NUMERIC); listView->addChild(this->createListViewItem(PORT_LABEL_TEXT, mPortEditBox)); + mIPEditBox->setText("192.168.1.111"); + mPortEditBox->setText("6789"); + if ( isAndroid() ) { mShowOnlyIfInBackground = new CheckBox();