2013-11-30

BeagleBone Black with AnTuTu Benchmark

底下敘述在 BeagleBone Black 上執行 Android AnTuTu App (4.1.1) 的流程 。

A. 製作 Android SDCard :
參考這裡提供的 Android 映象檔,只要將它放在 microSD 卡上就可以直接用了,將下載下來的壓縮檔解開,然後在該資料夾底下輸入 :
sudo./mkmmc-android.sh /dev/sdX MLO u-boot.img uImage uEnv_beagleboneblack.txt rootfs.tar.bz2
注意這行指令必須要在 Linux 環境下執行 ! 但本文要敘述在 mac osx mavericks 環境下 ( 利用 MacBook Air 3,2 內建之 SD Card Reader,但值得注意的是,目前 VirtualBox 尚不支援 USB 3.0,因此較新的 Macbook 可能不適用 ) 的製作流程 :
1. 安裝 VirtualBox,並在上面安裝 linux 作業系統,這裡使用的是 ubuntu server 13.10。
2. 安裝 VirtualBox Extension Pack。

3. 在 Settings --> Ports --> USB 底下將 Enable USB 2.0 (EHCI) Controller 打勾。
4. 新增 Empty Filter

5. 關閉 VirtualBox
5. 在 Terminal 底下輸入 :
sudo launchctl list | grep diskarbitrationd
6. 將前面顯示的數字 (如圖為 20) 代入至底下指令 :
sudo kill -SIGSTOP 20

7. 插入 SD 卡 !
8. 啟動 VirtualBox 之 Linux Virtual Machine
9. 點選底下 USB 圖示,然後選擇  Apple Internal Memory Card Reader。
若是安裝正確,在 /dev 底下會出多 sdb

10. 在 linux terminal 底下取得 這裡 提供的檔案 (可用 wget 指令),將檔案解壓縮後在該資料夾底下輸入 :
sudo./mkmmc-android.sh /dev/sdb MLO u-boot.img uImage uEnv_beagleboneblack.txt rootfs.tar.bz2

11. 恢復 mac osx sdcard reader 之運作,在 Terminal 底下輸入 :
sudo kill -SIGCONT 20

B. 將 sd card 安裝至 beaglebone black 然後按住 Boot 按鈕並插上電源後等待 android 字串出現到螢幕上為止。
C. 底下是 Android 4.2.2 畫面擷圖。

D. 系統資訊擷圖。


D. 底下是 Antutu 4.1.1 跑分結果。

E. 底下是 Antutu 4.1.1 顯示的系統資訊。



ref:http://www.ezequielaceto.com.ar/techblog/?page_id=910
ref:http://www.ezequielaceto.com.ar/techblog/?p=958
ref:http://superuser.com/questions/373463/how-to-access-an-sd-card-from-a-virtual-machine

2013-11-07

Cocos2d-x JNI 筆記

底下整理幾個常用的情況 :
  1. 新增 C++ 檔案
  2. 查看 Java Method Signature
  3. Java 呼叫 C++ 函數
  4. C++ 呼叫 Java 函數
  5. Java 呼叫 C++ 時傳遞數字變數
  6. C++ 呼叫 Java 時傳遞數字變數
  7. Java 呼叫 C++ 時傳遞字串
  8. C++ 呼叫 Java 時傳遞字串
  9. Java 呼叫 C++ 時傳遞矩陣
  10. C++ 呼叫 Java 時傳遞矩陣
  11. Java 呼叫 C++ 時傳遞回呼函數
  12. C++ 呼叫 Java 時傳遞回呼函數

1. C++ 新增 .h/.cpp 檔案 :
   i. 在 Classes 資料夾內新增 .h/.cpp 檔案
   ii. 編輯 proj.android/jni/Android.mk :
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := cocos2dcpp_shared

LOCAL_MODULE_FILENAME := libcocos2dcpp

#新增的檔案加在 LOCAL_SRC_FILES
LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/HelloWorldScene.cpp \
                   ../../Classes/AMGamebarUtil.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes

LOCAL_WHOLE_STATIC_LIBRARIES += cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += box2d_static
LOCAL_WHOLE_STATIC_LIBRARIES += chipmunk_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static

include $(BUILD_SHARED_LIBRARY)

$(call import-module,cocos2dx)
$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl)
$(call import-module,CocosDenshion/android)
$(call import-module,extensions)
$(call import-module,external/Box2D)
$(call import-module,external/chipmunk)
2. 查看 Java Method Signature :
javap -s -classpath <path to jar file> <package name>.<class name>
javap -s -classpath ./AMGameBar.jar com.appmaster.AMCocos2dxInterface
javap -s com.appmaster.AMCocos2dxInterface (尚未壓縮成jar, 相對路徑 com/appmaster/AMCocos2dxInterface.class)
3. Java 呼叫 C++ 函數 :
   i. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  //1.定義
  private static native void nativeLoginHandler();
  ...
  
  static public void callNative(){
    //2. 呼叫 c method
    nativeLoginHandler();
  }
}
   ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

extern "C"
{
  //c method 定義 :
  //Java_<package name (replace point with under line)>_<class>_<method>
  void Java_com_appmaster_AMCocos2dxInterface_nativeLoginHandler(JNIEnv* env, jobject thiz)
  {
    CCLOG("I HAVE BEEN TRIGGERED BY JAVA !");
  }

  ...
}
4. C++ 呼叫 Java 函數 :
   i. C++  檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

  JNIEnv *env  =NULL;
  jclass classid;
  jmethodID methodid;

  JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
  if (NULL == jvm) {
      return;
  }

  //setup env
  jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
  if (ret !=JNI_OK) {
      env =NULL;
      return;
  }

  classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
  if (!classid){
      return;
  }

  methodid =env->GetStaticMethodID(classid, "initGameBarLib", "()V");
  if (!methodid){
      return;
  }

  env->CallStaticObjectMethod(classid, methodid);
   ii. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  static public void initGameBarLib(){
    ...
  }
}

5. Java 呼叫 C++ 時傳遞數字變數 :
   i. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  private static native void nativeMethod(int val);
  ...

  static public void run(){
    nativeMethod(9527);
  }
}
   ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

extern "C"
{
  void Java_com_appmaster_AMCocos2dxInterface_ nativeMethod(JNIEnv* env, jobject thiz, jint val)
  {
    int nval =(int)val;
    CCLOG("val=%d", nval);

    ...

  }

  ...
}
6. C++ 呼叫 Java 時傳遞數字變數 :
   i. C++  檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

  JNIEnv *env  =NULL;
  jclass classid;
  jmethodID methodid;

  JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
  if (NULL == jvm) {
      return;
  }

  //setup env
  jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
  if (ret !=JNI_OK) {
      env =NULL;
      return;
  }

  classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
  if (!classid){
      return;
  }

  methodid =env->GetStaticMethodID(classid, "magicNumber", "(I)V");
  if (!methodid){
      return;
  }

  env->CallStaticObjectMethod(classid, methodid, (jint)9527);
   ii. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  static public void magicNumber(int val){
    ...
  }
}
7. Java 呼叫 C++ 時傳遞字串 :
   i. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  private static native void nativeMethod(final string data);
  ...

  static public void run(){
    nativeMethod("hello C++");
  }
}
   ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

extern "C"
{
  void Java_com_appmaster_AMCocos2dxInterface_ nativeMethod(JNIEnv* env, jobject thiz, jstring data)
  {
    const char* pData =env->GetStringUTFChars(data, 0);
    CCLOG("data=%s", pData);

    ...

    env->ReleaseStringUTFChars(data, pData);
  }

  ...
}
8. C++ 呼叫 Java 時傳遞字串 :
   i. C++  檔案如下 :
#include <jni/JniHelper.h>
#include <jni.h>

...

  JNIEnv *env  =NULL;
  jclass classid;
  jmethodID methodid;

  JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
  if (NULL == jvm) {
      return;
  }

  //setup env
  jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
  if (ret !=JNI_OK) {
      env =NULL;
      return;
  }

  classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
  if (!classid){
      return;
  }

  methodid =env->GetStaticMethodID(classid, "initGameBarLib", "(Ljava/lang/String;Ljava/lang/String;)V");
  if (!methodid){
      return;
  }

  jstring arg0 =env->NewStringUTF(pArg0); //char* pArg0
  jstring arg1 =env->NewStringUTF(pArg1); //char* pArg1
  env->CallStaticObjectMethod(classid, methodid, arg0, arg1);
  env->DeleteLocalRef(arg0);
  env->DeleteLocalRef(arg1);
   ii. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  static public void initGameBarLib(String arg0, String arg1){
    ...
  }
}
9. Java 呼叫 C++ 時傳遞矩陣 :
   i. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  private static native void nativeLoginHandler(int[] array);
  ...
  
  static public void run(){
    int[] array ={9, 5, 2, 7};
    nativeLoginHandler(array);
  }
}
   ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

extern "C"
{
  void Java_com_appmaster_AMCocos2dxInterface_nativeLoginHandler(JNIEnv* env, jobject thiz, jintArray ptr)
  {
      jsize length =env->GetArrayLength(ptr);
      if (length>0){
          jint* intarr =env->GetIntArrayElements(ptr, 0);
          for (int i=0;i<length;++i){
              printf("val[%d] =%d", i, intarr[i]);
          }

          env->ReleaseIntArrayElements(ptr, intarr, 0); 
      }
  }

  ...
}
10. C++ 呼叫 Java 時傳遞矩陣 :
   i. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

  ...

  int* praw_int =new int[4];
  praw_int[0] =9;
  praw_int[1] =5;
  praw_int[2] =2;
  praw_int[3] =7;

  jintArray arrdata =env->NewIntArray(4);
  env->SetIntArrayRegion(arrdata, 0, 4, (jint*)praw_int);

  ...

  JNIEnv *env  =NULL;
  jclass classid;
  jmethodID methodid;

  JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
  if (NULL == jvm) {
      return;
  }

  //setup env
  jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
  if (ret !=JNI_OK) {
      env =NULL;
      return;
  }

  classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
  if (!classid){
      return;
  }

  methodid =env->GetStaticMethodID(classid, "initGameBarLib", "([II)V");
  if (!methodid){
      return;
  }

  env->CallStaticObjectMethod(classid, methodid, arrdata, 4);

  delete [] praw_int;

}
   ii. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  
  static public void initGameBarLib(int[] data, int num){

    ...

  }

}
11. Java 呼叫 C++ 時傳遞回呼函數 :
   i. JAVA 檔案如下 :
package com.appmaster;

import org.cocos2dx.lib.Cocos2dxActivity;
import android.app.Activity;

public class AMCocos2dxInterface
{
  //傳遞回呼函數名稱 (字串)
  private static native void nativeAsyncMethod(final string funcString);
  ...
  
  static public void callbackFunc(){
    //i will be callback from c++
  }

  static public void run(){
    nativeAsyncMethod("callbackFunc");
  }
}
   ii. C++ 檔案如下 :
#include "cocos2d.h"
#include <jni/JniHelper.h>
#include <jni.h>

...

extern "C"
{
  void Java_com_appmaster_AMCocos2dxInterface_ nativeAsyncMethod(JNIEnv* env, jobject thiz, jstring funcString)
  {
    const char* pFuncString =env->GetStringUTFChars(funcString, 0);
    
    ...

    //callback
    JNIEnv *env  =NULL;
    jclass classid;
    jmethodID methodid;

    JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
    if (NULL == jvm) {
        env->ReleaseStringUTFChars(funcString, pFuncString);
        return;
    }

    //setup env
    jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
    if (ret !=JNI_OK) {
        env =NULL;
        env->ReleaseStringUTFChars(funcString, pFuncString);
        return;
    }

    classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
    if (!classid){
        env->ReleaseStringUTFChars(funcString, pFuncString);
        return;
    }

    methodid =env->GetStaticMethodID(classid, pFuncString, "()V");
    if (!methodid){
        env->ReleaseStringUTFChars(funcString, pFuncString);
        return;
    }

    env->CallStaticObjectMethod(classid, methodid);

    env->ReleaseStringUTFChars(funcString, pFuncString);
  }

  ...
}
12. C++ 呼叫 Java 時傳遞回呼函數 :
(ps. 底下的實作並未真正的把 C function pointer 傳遞到 java 環境)
   i. C++ (AMGamebarUtil.h)檔案如下 :
#include "cocos2d.h"

 ...

//定義回呼函數
typedef void (*onLoginCallback)(const cocos2d::CCString* pStrAccountID, const cocos2d::CCString* pStrNickname);

class AMGamebarUtil
{
public:
  static void initGameBarLib(onLoginCallback pCBFunc1);

}

 ...

   i. C++ (AMGamebarUtil.cpp)檔案如下 :
#include <jni/JniHelper.h>
#include <jni.h>
#include "AMGamebarUtil.h"

 ...

onLoginCallback pLC =NULL;

//預先建立 function 讓 java 回呼
extern "C"
{
  void Java_com_appmaster_AMCocos2dxInterface_nativeLoginHandler(JNIEnv*  env, jobject thiz, jstring aid, jstring nickname)
  {
    const char* pAid =env->GetStringUTFChars(aid, 0);
    const char* pNick =env->GetStringUTFChars(nickname, 0);

    //若是回呼函數已指定則回呼之
    if (pLC !=NULL){
      pLC(
        cocos2d::CCString::createWithFormat("%s", pAid),
        cocos2d::CCString::createWithFormat("%s", pNick)
      );
    }

    env->ReleaseStringUTFChars(aid, pAid);
    env->ReleaseStringUTFChars(nickname, pNick);
  }
}

void AMGamebarUtil::initGameBarLib(onLoginCallback pCBFunc1)
{

  //呼叫 JAVA
  JNIEnv *env  =NULL;
  jclass classid;
  jmethodID methodid;

  JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
  if (NULL == jvm) {
      CCLOG("Unity - AMGamebarUtil.cpp, Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
      return;
  }

  //setup env
  jint ret = jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
  if (ret !=JNI_OK) {
      env =NULL;
      return;
  }

  if (env ==NULL){
    return;
  }

  classid =env->FindClass("com/appmaster/AMCocos2dxInterface");
  if (!classid){
      return;
  }

  methodid =env->GetStaticMethodID(classid, "initGameBarLib", "()V");
  if (!methodid){
      return;
  }

  //REGISTER CALLBACK FUNCTION
  pLC   =pCBFunc1;

  //CALLING METHOD
  env->CallStaticObjectMethod(classid, methodid);

}
   i. C++ (.cpp)執行如下 :
//實作回呼函數
void onLoginCallbackHandler(const cocos2d::CCString* pStrAccountID, const cocos2d::CCString* pStrNickname)
{
    CCLOG("onLoginCallbackHandler(), aid=%s, nickname=%s", pStrAccountID->getCString(), pStrNickname->getCString());
}

 ...

//實際呼叫 initGameBarLib 並傳遞回呼函數指標
AMGamebarUtil::initGameBarLib(&onLoginCallbackHandler);


   ii. JAVA 檔案如下 :

public class AMCocos2dxInterface
{
    //預先定義回呼之 c++ method
    private static native void nativeLoginHandler(final String aid, final String nickname);

    static public void initGameBarLib(){
       ...
       
       //回呼 c++ method
       nativeLoginHandler("THIS_IS_AID", "THIS_IS_NICKNAME");
    }
   
    ...
}

ref:http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
ref:http://stackoverflow.com/questions/1232236/retrieving-byte-array-of-unknow-length-from-java-store
ref:http://www.lyceemermoz.com/iris/jlp/util/java/jdk/graphic/graphic.cpp
ref:http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html