Permalink
Browse files

Modified system.event extension to use a single open event poll for a…

…ll events.

This reduces the active load on the BrowserField thread pool (max 5) and allows
all hardware key events to be registered simultaneously.

Change applies to both onCoverage and onHardwareKey events.
  • Loading branch information...
1 parent 866c5f7 commit cf5ae01ca27fd5dfd1728f2c57bcd001c014feb2 @ababut ababut committed Nov 4, 2011
@@ -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 cf5ae01

Please sign in to comment.