Add local frames for parsing properties and processing events.

We were running out of local refs when there are lots of devices.
Instead of deleting every single local ref, create a local stack frame.
This operation is inexpensive so doesn't add a high overload and keeps
the code clean instead of deleting every single local ref.
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index 14da1fd..a185d8d 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -211,10 +211,6 @@
                             method_onSinkPropertyChanged,
                             env->NewStringUTF(c_path),
                             str_array);
-        for (int i = 0; i < env->GetArrayLength(str_array); i++) {
-            env->DeleteLocalRef(env->GetObjectArrayElement(str_array, i));
-        }
-        env->DeleteLocalRef(str_array);
         result = DBUS_HANDLER_RESULT_HANDLED;
         return result;
     } else {
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 527bf07..1bfabd7 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -57,6 +57,8 @@
 
 typedef event_loop_native_data_t native_data_t;
 
+#define EVENT_LOOP_REFS 10
+
 static inline native_data_t * get_native_data(JNIEnv *env, jobject object) {
     return (native_data_t *)(env->GetIntField(object,
                                                  field_mNativeData));
@@ -679,6 +681,7 @@
     native_data_t *nat;
     JNIEnv *env;
     DBusError err;
+    DBusHandlerResult ret;
 
     dbus_error_init(&err);
 
@@ -694,6 +697,7 @@
         dbus_message_get_interface(msg), dbus_message_get_member(msg),
         dbus_message_get_path(msg));
 
+    env->PushLocalFrame(EVENT_LOOP_REFS);
     if (dbus_message_is_signal(msg,
                                "org.bluez.Adapter",
                                "DeviceFound")) {
@@ -711,10 +715,9 @@
                                 method_onDeviceFound,
                                 env->NewStringUTF(c_address),
                                 str_array);
-            env->DeleteLocalRef(str_array);
         } else
             LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_signal(msg,
                                      "org.bluez.Adapter",
                                      "DeviceDisappeared")) {
@@ -726,7 +729,7 @@
             env->CallVoidMethod(nat->me, method_onDeviceDisappeared,
                                 env->NewStringUTF(c_address));
         } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_signal(msg,
                                      "org.bluez.Adapter",
                                      "DeviceCreated")) {
@@ -739,7 +742,7 @@
                                 method_onDeviceCreated,
                                 env->NewStringUTF(c_object_path));
         } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_signal(msg,
                                      "org.bluez.Adapter",
                                      "DeviceRemoved")) {
@@ -752,8 +755,7 @@
                                method_onDeviceRemoved,
                                env->NewStringUTF(c_object_path));
         } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_signal(msg,
                                       "org.bluez.Adapter",
                                       "PropertyChanged")) {
@@ -775,9 +777,8 @@
             env->CallVoidMethod(nat->me,
                               method_onPropertyChanged,
                               str_array);
-            env->DeleteLocalRef(str_array);
         } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_signal(msg,
                                       "org.bluez.Device",
                                       "PropertyChanged")) {
@@ -788,12 +789,17 @@
                             method_onDevicePropertyChanged,
                             env->NewStringUTF(remote_device_path),
                             str_array);
-            env->DeleteLocalRef(str_array);
         } else LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, msg);
-        return DBUS_HANDLER_RESULT_HANDLED;
-
+        goto success;
     }
-    return a2dp_event_filter(msg, env);
+
+    ret = a2dp_event_filter(msg, env);
+    env->PopLocalFrame(NULL);
+    return ret;
+
+success:
+    env->PopLocalFrame(NULL);
+    return DBUS_HANDLER_RESULT_HANDLED;
 }
 
 // Called by dbus during WaitForAndDispatchEventNative()
@@ -811,6 +817,8 @@
     if (nat == NULL) return DBUS_HANDLER_RESULT_HANDLED;
 
     nat->vm->GetEnv((void**)&env, nat->envVer);
+    env->PushLocalFrame(EVENT_LOOP_REFS);
+
     if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "Cancel")) {
 
@@ -820,11 +828,11 @@
         DBusMessage *reply = dbus_message_new_method_return(msg);
         if (!reply) {
             LOGE("%s: Cannot create message reply\n", __FUNCTION__);
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            goto failure;
         }
         dbus_connection_send(nat->conn, reply, NULL);
         dbus_message_unref(reply);
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
 
     } else if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "Authorize")) {
@@ -835,7 +843,7 @@
                                    DBUS_TYPE_STRING, &uuid,
                                    DBUS_TYPE_INVALID)) {
             LOGE("%s: Invalid arguments for Authorize() method", __FUNCTION__);
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            goto failure;
         }
 
         LOGV("... object_path = %s", object_path);
@@ -850,7 +858,7 @@
             DBusMessage *reply = dbus_message_new_method_return(msg);
             if (!reply) {
                 LOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+                goto failure;
             }
             dbus_connection_send(nat->conn, reply, NULL);
             dbus_message_unref(reply);
@@ -859,12 +867,12 @@
                     "org.bluez.Error.Rejected", "Authorization rejected");
             if (!reply) {
                 LOGE("%s: Cannot create message reply\n", __FUNCTION__);
-                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+                goto failure;
             }
             dbus_connection_send(nat->conn, reply, NULL);
             dbus_message_unref(reply);
         }
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "RequestPinCode")) {
         char *object_path;
@@ -872,14 +880,14 @@
                                    DBUS_TYPE_OBJECT_PATH, &object_path,
                                    DBUS_TYPE_INVALID)) {
             LOGE("%s: Invalid arguments for RequestPinCode() method", __FUNCTION__);
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            goto failure;
         }
 
         dbus_message_ref(msg);  // increment refcount because we pass to java
         env->CallVoidMethod(nat->me, method_onRequestPinCode,
                                        env->NewStringUTF(object_path),
                                        int(msg));
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "RequestPasskey")) {
         char *object_path;
@@ -887,13 +895,14 @@
                                    DBUS_TYPE_OBJECT_PATH, &object_path,
                                    DBUS_TYPE_INVALID)) {
             LOGE("%s: Invalid arguments for RequestPasskey() method", __FUNCTION__);
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            goto failure;
         }
 
         dbus_message_ref(msg);  // increment refcount because we pass to java
         env->CallVoidMethod(nat->me, method_onRequestPasskey,
                                        env->NewStringUTF(object_path),
                                        int(msg));
+        goto success;
     } else if (dbus_message_is_method_call(msg,
             "org.bluez.Agent", "RequestConfirmation")) {
         char *object_path;
@@ -903,7 +912,7 @@
                                    DBUS_TYPE_UINT32, &passkey,
                                    DBUS_TYPE_INVALID)) {
             LOGE("%s: Invalid arguments for RequestConfirmation() method", __FUNCTION__);
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            goto failure;
         }
 
         dbus_message_ref(msg);  // increment refcount because we pass to java
@@ -911,23 +920,30 @@
                                        env->NewStringUTF(object_path),
                                        passkey,
                                        int(msg));
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else if (dbus_message_is_method_call(msg,
                   "org.bluez.Agent", "Release")) {
         // reply
         DBusMessage *reply = dbus_message_new_method_return(msg);
         if (!reply) {
             LOGE("%s: Cannot create message reply\n", __FUNCTION__);
-            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+            goto failure;
         }
         dbus_connection_send(nat->conn, reply, NULL);
         dbus_message_unref(reply);
-        return DBUS_HANDLER_RESULT_HANDLED;
+        goto success;
     } else {
         LOGV("%s:%s is ignored", dbus_message_get_interface(msg), dbus_message_get_member(msg));
     }
 
+failure:
+    env->PopLocalFrame(NULL);
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+success:
+    env->PopLocalFrame(NULL);
+    return DBUS_HANDLER_RESULT_HANDLED;
+
 }
 #endif
 
diff --git a/core/jni/android_server_BluetoothService.cpp b/core/jni/android_server_BluetoothService.cpp
index 326052b..d1901b4 100644
--- a/core/jni/android_server_BluetoothService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -46,6 +46,7 @@
 namespace android {
 
 #define BLUETOOTH_CLASS_ERROR 0xFF000000
+#define PROPERTIES_NREFS 10
 
 #ifdef HAVE_BLUETOOTH
 // We initialize these variables when we load class
@@ -576,11 +577,16 @@
                 LOGE("DBus reply is NULL in function %s", __FUNCTION__);
             return NULL;
         }
+        env->PushLocalFrame(PROPERTIES_NREFS);
+
         DBusMessageIter iter;
         jobjectArray str_array = NULL;
         if (dbus_message_iter_init(reply, &iter))
            str_array =  parse_remote_device_properties(env, &iter);
         dbus_message_unref(reply);
+
+        env->PopLocalFrame(NULL);
+
         return str_array;
     }
 #endif
@@ -607,11 +613,15 @@
                 LOGE("DBus reply is NULL in function %s", __FUNCTION__);
             return NULL;
         }
+        env->PushLocalFrame(PROPERTIES_NREFS);
+
         DBusMessageIter iter;
         jobjectArray str_array = NULL;
         if (dbus_message_iter_init(reply, &iter))
             str_array = parse_adapter_properties(env, &iter);
         dbus_message_unref(reply);
+
+        env->PopLocalFrame(NULL);
         return str_array;
     }
 #endif