130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni/*
230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Copyright (C) 2011 The Android Open Source Project
330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Licensed under the Apache License, Version 2.0 (the "License");
530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * you may not use this file except in compliance with the License.
630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * You may obtain a copy of the License at
730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *      http://www.apache.org/licenses/LICENSE-2.0
930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni *
1030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * Unless required by applicable law or agreed to in writing, software
1130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * distributed under the License is distributed on an "AS IS" BASIS,
1230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * See the License for the specific language governing permissions and
1430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni * limitations under the License.
1530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni */
1630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include <jni.h>
1830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
1930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include <hash_map>
2030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include <string>
2130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#include "base/utilities.h"
23cfda0a38d6f394724e0cbd831ec9bc71d951fc74Marius Renn#include "core/value.h"
2430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
25e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala#ifndef ANDROID_FILTERFW_JNI_JNI_UTIL_H
26e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala#define ANDROID_FILTERFW_JNI_JNI_UTIL_H
2730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
2830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// We add this JNI_NULL macro to allow consistent code separation of Java and
2930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// C++ types.
3030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#define JNI_NULL NULL
3130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
3230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#if 0
3330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Pointer to current JavaVM. Do not use this directly. Instead use the funciton
3430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// GetCurrentJavaVM().
3530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniextern JavaVM* g_current_java_vm_;
3630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
3730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Wrapper around a java object pointer, which includes the environment
3830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// pointer in which the object "lives". This is used for passing down Java
3930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// objects from the Java layer to C++.
4030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// While an instance of this class does not own the underlying java object, it
4130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// does hold a global reference to it, so that the Java garbage collector does
4230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// not destroy it. It uses reference counting to determine when it can destroy
4330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// the reference.
4430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// TODO: Add multi-thread support!
4530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniclass JavaObject {
4630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  public:
4730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Creates a NULL JavaObject.
4830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    JavaObject();
4930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Creates a wrapper around the given object in the given JNI environment.
5130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    JavaObject(jobject object, JNIEnv* env);
5230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Copy constructor.
5430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    JavaObject(const JavaObject& java_obj);
5530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Destructor.
5730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    ~JavaObject();
5830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
5930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Assignment operator.
6030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    JavaObject& operator=(const JavaObject& java_obj);
6130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Access to the object (non-const as JNI functions are non-const).
6330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    jobject object() const {
6430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return object_;
6530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
6630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
6730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Resets this object to the NULL JavaObject.
6830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    void Reset();
6930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
7030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  private:
7130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Retain the instance, i.e. increase reference count.
7230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    void Retain();
7330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
7430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Release the instance, i.e. decrease reference count.
7530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    void Release();
7630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
7730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // The object pointer (not owned).
7830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    jobject object_;
7930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
8030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // The reference count of this object
8130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    int* ref_count_;
8230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni};
8330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#endif
8430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
8530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// ObjectPool template class. This class keeps track of C++ instances that are
8630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// coupled to Java objects. This is done by using an "id" field in the Java
8730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// object, which is then mapped to the correct instance here. It should not be
8830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// necessary to use this class directly. Instead, the convenience functions
8930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// below can be used.
9030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronitemplate<class T>
9130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroniclass ObjectPool {
9230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  public:
9330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Create a new ObjectPool for a specific object type. Pass the path to the
9430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Java equivalent class of the C++ class, and the name of the java member
9530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // field that will store the object's ID.
96e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala    static void Setup(const std::string& jclass_name,
97e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala                      const std::string& id_fld_name) {
9830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      instance_ = new ObjectPool<T>(jclass_name, id_fld_name);
9930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
10030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
10130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Return the shared instance to this type's pool.
10230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    static ObjectPool* Instance() {
10330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return instance_;
10430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
10530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
10630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Delete this type's pool.
10730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    static void TearDown() {
10830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      delete instance_;
10930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
11030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
11130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Register a new C++ object with the pool. This does not affect the Java
11230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // layer. Use WrapObject() instead to perform the necessary Java-side
11330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // assignments. Pass true to owns if the object pool owns the object.
11430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    int RegisterObject(T* object, bool owns) {
11530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      const int id = next_id_;
11630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      objects_[id] = object;
11730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      owns_[id] = owns;
11830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      ++next_id_;
11930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return id;
12030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
12130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
12230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Return the object in the pool with the specified ID.
12330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    T* ObjectWithID(int obj_id) const {
12430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      typename CObjMap::const_iterator iter = objects_.find(obj_id);
12530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return iter == objects_.end() ? NULL : iter->second;
12630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
12730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
12830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Get the ID of a Java object. This ID can be used to look-up the C++
12930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // object.
13030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    int GetObjectID(JNIEnv* env, jobject j_object) {
13130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jclass cls = env->GetObjectClass(j_object);
13230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jfieldID id_field = env->GetFieldID(cls, id_field_name_.c_str(), "I");
13330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      const int result = env->GetIntField(j_object, id_field);
13430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      env->DeleteLocalRef(cls);
13530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return result;
13630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
13730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
13830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Take a C++ object and wrap it with a given Java object. This will
13930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // essentially set the ID member of the Java object to the ID of the C++
14030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // object. Pass true to owns if the object pool owns the object.
14130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    bool WrapObject(T* c_object, JNIEnv* env, jobject j_object, bool owns) {
14230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      const int id = RegisterObject(c_object, owns);
14330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jclass cls = env->GetObjectClass(j_object);
14430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jfieldID id_field = env->GetFieldID(cls, id_field_name_.c_str(), "I");
14530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      env->SetIntField(j_object, id_field, id);
14630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      env->DeleteLocalRef(cls);
14730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return true;
14830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
14930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
15030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Remove the object with the given ID from this pool, and delete it. This
15130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // does not affect the Java layer.
15230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    bool DeleteObjectWithID(int obj_id) {
15330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      typename CObjMap::iterator iter = objects_.find(obj_id);
15430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      const bool found = iter != objects_.end();
15530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      if (found) {
15630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        if (owns_[obj_id])
15730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni          delete iter->second;
15830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        objects_.erase(iter);
15930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      }
16030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return found;
16130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
16230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
16330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // Instantiates a new java object for this class. The Java class must have
16430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    // a default constructor for this to succeed.
16530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    jobject CreateJavaObject(JNIEnv* env) {
16630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jclass cls = env->FindClass(jclass_name_.c_str());
16730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jmethodID constructor = env->GetMethodID(
16830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        cls,
16930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "<init>",
17030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        "(Landroid/filterfw/core/NativeAllocatorTag;)V");
17130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      jobject result = env->NewObject(cls, constructor, JNI_NULL);
17230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      env->DeleteLocalRef(cls);
17330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return result;
17430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
17530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
17630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    int GetObjectCount() const {
17730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return objects_.size();
17830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
17930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
180e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala    const std::string& GetJavaClassName() const {
18130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return jclass_name_;
18230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    }
18330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
18430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  private:
185e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala    explicit ObjectPool(const std::string& jclass_name,
186e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala                        const std::string& id_fld_name)
18730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      : jclass_name_(jclass_name),
18830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        id_field_name_(id_fld_name),
18930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni        next_id_(0) { }
19030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
19130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    typedef std::hash_map<int, T*>    CObjMap;
19230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    typedef std::hash_map<int, bool>  FlagMap;
19330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    static ObjectPool* instance_;
194e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala    std::string jclass_name_;
195e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala    std::string id_field_name_;
19630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    int next_id_;
19730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    CObjMap objects_;
19830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    FlagMap owns_;
19930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
20030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    DISALLOW_COPY_AND_ASSIGN(ObjectPool);
20130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni};
20230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
20330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronitemplate<typename T> ObjectPool<T>* ObjectPool<T>::instance_ = NULL;
20430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
20530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convenience Functions ///////////////////////////////////////////////////////
20630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
20730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// This function "links" the C++ instance and the Java instance, so that they
20830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// can be mapped to one another. This must be called for every C++ instance
20930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// which is wrapped by a Java front-end interface. Pass true to owns, if the
21030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Java layer should own the object.
21130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronitemplate<typename T>
21230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool WrapObjectInJava(T* c_object, JNIEnv* env, jobject j_object, bool owns) {
21330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  ObjectPool<T>* pool = ObjectPool<T>::Instance();
21430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return pool ? pool->WrapObject(c_object, env, j_object, owns) : false;
21530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
21630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
21730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Creates a new Java instance, which wraps the passed C++ instance. Returns
21830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// the wrapped object or JNI_NULL if there was an error. Pass true to owns, if
21930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// the Java layer should own the object.
22030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronitemplate<typename T>
22130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronijobject WrapNewObjectInJava(T* c_object, JNIEnv* env, bool owns) {
22230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  ObjectPool<T>* pool = ObjectPool<T>::Instance();
22330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  if (pool) {
22430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    jobject result = pool->CreateJavaObject(env);
22530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    if (WrapObjectInJava(c_object, env, result, owns))
22630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni      return result;
22730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  }
22830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return JNI_NULL;
22930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
23030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
23130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Use ConvertFromJava to obtain a C++ instance given a Java object. This
23230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// instance must have been wrapped in Java using the WrapObjectInJava()
23330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// function.
23430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronitemplate<typename T>
23530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniT* ConvertFromJava(JNIEnv* env, jobject j_object) {
23630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  ObjectPool<T>* pool = ObjectPool<T>::Instance();
23730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return pool && j_object
23830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    ? pool->ObjectWithID(pool->GetObjectID(env, j_object))
23930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    : NULL;
24030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
24130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
24230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Delete the native object given a Java instance. This should be called from
24330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// the Java object's finalizer.
24430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronitemplate<typename T>
24530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool DeleteNativeObject(JNIEnv* env, jobject j_object) {
24630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  ObjectPool<T>* pool = ObjectPool<T>::Instance();
24730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni  return pool && j_object
24830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    ? pool->DeleteObjectWithID(pool->GetObjectID(env, j_object))
24930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni    : false;
25030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni}
25130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
25230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#if 0
25330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Get the current JNI VM, or NULL if there is no current VM
25430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniJavaVM* GetCurrentJavaVM();
25530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
25630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Get the current JNI environment, or NULL if this is not a JNI thread
25730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniJNIEnv* GetCurrentJNIEnv();
25830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni#endif
25930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
26030ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convert C++ boolean to Java boolean.
26130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronijboolean ToJBool(bool value);
26230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
26330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convert Java boolean to C++ boolean.
26430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronibool ToCppBool(jboolean value);
26530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
26630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convert Java String to C++ string.
267e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalajstring ToJString(JNIEnv* env, const std::string& value);
26830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
26930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convert C++ string to Java String.
270e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalastd::string ToCppString(JNIEnv* env, jstring value);
27130ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
27230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convert Java object to a (C) Value object.
27330ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo CarceroniValue ToCValue(JNIEnv* env, jobject object);
27430ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
27530ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Convert a (C) Value object to a Java object.
27630ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceronijobject ToJObject(JNIEnv* env, const Value& value);
27730ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
27830ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// Returns true, iff the passed object is an instance of the class specified
27930ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni// by its fully qualified class name.
280e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvalabool IsJavaInstanceOf(JNIEnv* env, jobject object,
281e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala                      const std::string& class_name);
28230ab3fc173709a491c9e2e103f53fb7c0d1b96b7Rodrigo Carceroni
283e9912de34684f1b8deaf36bcf77686152d33765dEino-Ville Talvala#endif // ANDROID_FILTERFW_JNI_JNI_UTIL_H
284