Permalink
Browse files

Merge pull request #13 from blackberry-webworks/next-system-event-fix

Modified system.event extension to use a single open event poll for all e
  • Loading branch information...
qingbiao committed Nov 8, 2011
2 parents 866c5f7 + cf5ae01 commit 0c30ccd4aea432f79152d0834f1e6f95101190c0
@@ -179,8 +179,11 @@
blackberry.transport.call(url, opts, function (response) {
if (callback(response)) {
- this.blackberry.transport.poll(url, opts, callback);
- }
+ setTimeout(
+ function() { this.blackberry.transport.poll(url, opts, callback); },
+ 0
+ );
+ }
});
};
})();
@@ -13,62 +13,94 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-(function () {
- var OK = 0;
- var FUNCTION_ON_COVERAGE_CHANGE = "onCoverageChange";
- var FUNCTION_ON_HARDWARE_KEY = "onHardwareKey";
-
- var _callbacks = {};
-
- function SystemEventDispatcher() {
- };
-
- function poll(evt, args, handler) {
- if (evt == FUNCTION_ON_HARDWARE_KEY) {
- var keyCallbacks = _callbacks[evt];
- keyCallbacks = keyCallbacks || {};
- keyCallbacks[args["get"]["key"]] = handler;
- _callbacks[evt] = keyCallbacks;
- } else {
- _callbacks[evt] = handler;
- }
-
- blackberry.transport.poll("blackberry/system/event/" + evt, args, function(response) {
- if (response.code < OK) {
- // do not invoke callback unless return code is OK
+(function () {
+ var OK = 0,
+ CHANNEL_CLOSED = 1,
+ _polling = false,
+ FUNCTION_ON_COVERAGE_CHANGE = "onCoverageChange",
+ FUNCTION_ON_HARDWARE_KEY = "onHardwareKey",
+ _callbacks = {};
+
+ function poll() {
+
+ blackberry.transport.poll("blackberry/system/event/poll", {}, function(response) {
+ // do not invoke callback unless return code is OK (negative codes for errors, or channel closed from Java side)
+ // stop polling if response code is not OK
+ if (response.code < OK || response.code === CHANNEL_CLOSED) {
+ _polling = false;
return false;
}
-
- var func;
-
- if (evt == FUNCTION_ON_HARDWARE_KEY) {
- func = _callbacks[evt][response.data["key"]];
- } else {
- func = _callbacks[evt];
- }
-
- if (func) {
+
+ var event = response.data.event,
+ func = (event === FUNCTION_ON_HARDWARE_KEY) ? _callbacks[event][response.data.arg] : _callbacks[event];
+
+ if (typeof(func) !== "undefined") {
func();
}
return !!func;
});
- };
-
- function initPoll(evt, args, handler) {
- args = args || {};
-
- args["monitor"] = (handler ? true : false);
-
- poll(evt, { "get" : args }, handler);
- };
+
+ }
+
+ function registerForEvent(evt, args) {
+ blackberry.transport.call(
+ "blackberry/system/event/register",
+ { get : { event : evt, arg : args } },
+ function(response) {
+ if(response.code < OK) {
+ throw new Error("Unable to register event handler for " + evt + ". Implementation returned: " + response.code);
+ }
+ }
+ );
+
+ if(!_polling) {
+ _polling = true;
+ poll();
+ }
+ }
+
+ function unregisterForEvent(evt, args) {
+ blackberry.transport.call(
+ "blackberry/system/event/unregister",
+ { get : { event : evt, arg : args } },
+ function(response) {
+ if(response.code < OK) {
+ throw new Error("Unable to unregister event handler for " + evt + ". Implementation returned: " + response.code);
+ }
+ }
+ );
+ }
+
+ function SystemEventDispatcher() {
+ _callbacks[FUNCTION_ON_COVERAGE_CHANGE] = {};
+ _callbacks[FUNCTION_ON_HARDWARE_KEY] = {};
+ }
SystemEventDispatcher.prototype.onCoverageChange = function(onSystemEvent) {
- initPoll(FUNCTION_ON_COVERAGE_CHANGE, {}, onSystemEvent);
+ var listen = (typeof(onSystemEvent) === "function"),
+ alreadyListening = (typeof(_callbacks[FUNCTION_ON_COVERAGE_CHANGE]) === "function");
+
+ if(listen) {
+ //Update the callback reference
+ _callbacks[FUNCTION_ON_COVERAGE_CHANGE] = onSystemEvent;
+
+ //If we are already listening, don't re-register
+ if(!alreadyListening) {
+ //Start listening for this event
+ registerForEvent(FUNCTION_ON_COVERAGE_CHANGE);
+ }
+ } else {
+ //Update the callback reference
+ _callbacks[FUNCTION_ON_COVERAGE_CHANGE] = undefined;
+ if(alreadyListening) {
+ unregisterForEvent(FUNCTION_ON_COVERAGE_CHANGE);
+ }
+ }
};
- SystemEventDispatcher.prototype.onHardwareKey = function(key, onSystemEvent) {
+ SystemEventDispatcher.prototype.onHardwareKey = function(onSystemEvent, key) {
switch (key) {
case blackberry.system.event.KEY_BACK:
case blackberry.system.event.KEY_MENU:
@@ -82,9 +114,27 @@
default:
throw new Error("key parameter must be one of the pre-defined KEY_* constants");
}
-
- initPoll(FUNCTION_ON_HARDWARE_KEY, { "key" : key }, onSystemEvent);
+
+ var listen = (typeof(onSystemEvent) === "function"),
+ alreadyListening = (typeof(_callbacks[FUNCTION_ON_HARDWARE_KEY][key]) === "function");
+
+ if(listen) {
+ //Update the callback reference
+ _callbacks[FUNCTION_ON_HARDWARE_KEY][key] = onSystemEvent;
+
+ //Only register with the implementation if we're not already listening
+ if(!alreadyListening) {
+ //Start listening for this event
+ registerForEvent(FUNCTION_ON_HARDWARE_KEY, key);
+ }
+ } else {
+ //Update the callback reference
+ _callbacks[FUNCTION_ON_HARDWARE_KEY][key] = undefined;
+ if(alreadyListening) {
+ unregisterForEvent(FUNCTION_ON_HARDWARE_KEY, key);
+ }
+ }
};
blackberry.Loader.javascriptLoaded("blackberry.system.event", SystemEventDispatcher);
-})();
+}());
@@ -18,7 +18,7 @@
function SystemEvent(disp) {
this.onCoverageChange = function(onSystemEvent) { return disp.onCoverageChange(onSystemEvent); };
- this.onHardwareKey = function(key, onSystemEvent) { return disp.onHardwareKey(key, onSystemEvent); };
+ this.onHardwareKey = function(key, onSystemEvent) { return disp.onHardwareKey(onSystemEvent, key); };
}
SystemEvent.prototype.__defineGetter__("KEY_BACK", function() { return 0; });
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package blackberry.system.event;
+
+import blackberry.system.event.ISystemEventListener;
+
+import net.rim.device.api.system.CoverageInfo;
+import net.rim.device.api.system.CoverageStatusListener;
+
+/**
+ * Coverage listener implementation. Proxy for system coverage listener that
+ * notifies manager generically of coverage change events.
+ *
+ * @author ababut
+ */
+public class CoverageChangeHandler {
+ private ISystemEventListener _manager;
+
+ private CoverageStatusListener _currentCoverageMonitor;
+
+ CoverageChangeHandler(ISystemEventListener manager) {
+ _manager = manager;
+ }
+
+ /**
+ * Creates a listener if not present and registers it.
+ *
+ */
+ public void listen() {
+ if( _currentCoverageMonitor == null ) {
+ _currentCoverageMonitor = new CoverageStatusListener() {
+ public void coverageStatusChanged( int newCoverage ) {
+ //Notify manager of coverage changed event
+ //TODO: Add new coverage to the event argument if JS cares about it
+ _manager.onSystemEvent(_manager.EVENT_COV_CHANGE, "");
+ }
+ };
+
+ CoverageInfo.addListener(_currentCoverageMonitor);
+ }
+ }
+
+ /**
+ * Removes system listener if present.
+ *
+ */
+ public void stopListening() {
+ if(_currentCoverageMonitor != null) {
+ CoverageInfo.removeListener(_currentCoverageMonitor);
+ //Explicitly null it out to avoid memory leaks
+ _currentCoverageMonitor = null;
+ }
+ }
+
+ /**
+ * Indicates listener status
+ *
+ * @return true if listener is active
+ */
+ public boolean isListening() {
+ return (_currentCoverageMonitor != null);
+ }
+}
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2010-2011 Research In Motion Limited.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package blackberry.system.event;
+
+import java.util.Vector;
+import blackberry.system.event.SystemEventReturnValue;
+
+ /** Thread safe queue implementation based on Vector.
+ *
+ * @author ababut
+ */
+public class EventQueue {
+ private Vector _queue;
+ private Object _lock;
+
+ EventQueue() {
+ _queue = new Vector();
+ _lock = new Object();
+ }
+
+ /**
+ * Queues a SystemReturnValue object and signals the lock that there are items
+ * waiting.
+ *
+ * @param event the event to queue up
+ */
+ public void enqueue(SystemEventReturnValue event) {
+ synchronized(_lock) {
+ _queue.addElement(event);
+ _lock.notify();
+ }
+ }
+
+ /**
+ * Removes first SystemReturnValue object in queue. If queue is empty, wait
+ * on lock until signalled.
+ *
+ * @param event the event to queue up
+ */
+ public SystemEventReturnValue dequeueWaitIfEmpty() {
+ SystemEventReturnValue result = null;
+
+ if(_queue.isEmpty()) {
+ try {
+ synchronized(_lock) {
+ _lock.wait();
+ }
+ } catch(InterruptedException e) {
+ System.out.println("InterrupedException while waiting on event queue");
+ throw new RuntimeException("Polling thread interrupted while waiting.");
+ }
+
+ }
+
+ synchronized(_lock) {
+ result = (SystemEventReturnValue)_queue.elementAt(0);
+ _queue.removeElementAt(0);
+ }
+
+ return result;
+ }
+}
@@ -1,50 +0,0 @@
-/*
- * Copyright 2010-2011 Research In Motion Limited.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package blackberry.system.event;
-
-/**
- * interface <code>ISystemEventExtensionConstants</code> contains constants
- * which are need by SystemEventExtension
- * @author rtse
- */
-public interface ISystemEventExtensionConstants {
- // Feature name
- public final static String FEATURE_ID = "blackberry.system.event";
-
- public static final String REQ_FUNCTION_ON_HARDWARE_KEY = "onHardwareKey";
- public static final String REQ_FUNCTION_ON_COVERAGE_CHANGE = "onCoverageChange";
-
- public static final String ARG_MONITOR = "monitor";
- public static final String ARG_KEY = "key";
-
- public static final String KEY_BACK = "KEY_BACK";
- public static final String KEY_MENU = "KEY_MENU";
- public static final String KEY_CONVENIENCE_1 = "KEY_CONVENIENCE_1";
- public static final String KEY_CONVENIENCE_2 = "KEY_CONVENIENCE_2";
- public static final String KEY_STARTCALL = "KEY_STARTCALL";
- public static final String KEY_ENDCALL = "KEY_ENDCALL";
- public static final String KEY_VOLUME_UP = "KEY_VOLUMEUP";
- public static final String KEY_VOLUME_DOWN = "KEY_VOLUMEDOWN";
-
- public static final int IKEY_BACK = 0;
- public static final int IKEY_MENU = 1;
- public static final int IKEY_CONVENIENCE_1 = 2;
- public static final int IKEY_CONVENIENCE_2 = 3;
- public static final int IKEY_STARTCALL = 4;
- public static final int IKEY_ENDCALL = 5;
- public static final int IKEY_VOLUME_DOWN = 6;
- public static final int IKEY_VOLUME_UP = 7;
-}
Oops, something went wrong.

0 comments on commit 0c30ccd

Please sign in to comment.