Change dali demo launching using DaliDemoNativeActivity JNI. 73/228773/4
authorAnton Obzhirov <a.obzhirov@samsung.com>
Wed, 25 Mar 2020 10:14:36 +0000 (10:14 +0000)
committerRichard Huang <r.huang@samsung.com>
Fri, 27 Mar 2020 16:19:10 +0000 (16:19 +0000)
Also start new activity in its own private process.

Change-Id: I4ad00730247ce39d9acf26eabb3f06ecc3d8e8b8

build/android/app/src/main/AndroidManifest.xml
build/android/app/src/main/cpp/CMakeLists.txt
build/android/app/src/main/cpp/dali-demo-native-activity-jni.h [new file with mode: 0644]
build/android/app/src/main/cpp/main.cpp
build/android/app/src/main/java/com/sec/dalidemo/DaliDemoNativeActivity.java
build/android/app/src/main/java/com/sec/dalidemo/DaliDemosNativeActivity.java [new file with mode: 0644]
build/tizen/CMakeLists.txt
shared/execute-process-android.cpp

index 15e8dc0..e10568e 100644 (file)
       android:label="@string/app_name"
       android:name="com.sec.dalidemo.DaliDemoApplication">
 
       android:label="@string/app_name"
       android:name="com.sec.dalidemo.DaliDemoApplication">
 
+    <activity android:name="com.sec.dalidemo.DaliDemoNativeActivity"
+        android:icon="@mipmap/dali_launcher"
+        android:label="DALi Example"
+        android:screenOrientation="portrait"
+        android:windowSoftInputMode="stateAlwaysVisible"
+        android:process=":example">
+      <!-- Tell NativeActivity the name of our .so -->
+      <meta-data android:name="android.app.lib_name"
+          android:value="native-activity" />
+      <meta-data android:name="start"
+          android:value="blocks.example" />
+      <intent-filter>
+        <action android:name="android.intent.action.RUN" />
+      </intent-filter>
+    </activity>
+
     <!-- Our activity is the built-in NativeActivity framework class.
          This will take care of integrating with our NDK code. -->
     <!-- Our activity is the built-in NativeActivity framework class.
          This will take care of integrating with our NDK code. -->
-    <activity android:name="com.sec.dalidemo.DaliDemoNativeActivity"
+    <activity android:name="com.sec.dalidemo.DaliDemosNativeActivity"
               android:icon="@mipmap/dali_launcher"
               android:label="@string/demo_name"
               android:screenOrientation="portrait"
               android:icon="@mipmap/dali_launcher"
               android:label="@string/demo_name"
               android:screenOrientation="portrait"
-              android:windowSoftInputMode="stateAlwaysVisible">
+              android:windowSoftInputMode="stateAlwaysVisible"
+              android:process=":dalidemos">
       <!-- Tell NativeActivity the name of our .so -->
       <meta-data android:name="android.app.lib_name"
                  android:value="native-activity" />
       <!-- Tell NativeActivity the name of our .so -->
       <meta-data android:name="android.app.lib_name"
                  android:value="native-activity" />
@@ -37,7 +54,8 @@
         android:icon="@mipmap/dali_examples"
         android:label="@string/examples_name"
         android:screenOrientation="portrait"
         android:icon="@mipmap/dali_examples"
         android:label="@string/examples_name"
         android:screenOrientation="portrait"
-        android:windowSoftInputMode="stateAlwaysVisible">
+        android:windowSoftInputMode="stateAlwaysVisible"
+        android:process=":daliexamples">
       <!-- Tell NativeActivity the name of our .so -->
       <meta-data android:name="android.app.lib_name"
           android:value="native-activity" />
       <!-- Tell NativeActivity the name of our .so -->
       <meta-data android:name="android.app.lib_name"
           android:value="native-activity" />
@@ -54,7 +72,8 @@
         android:icon="@mipmap/dali_tests"
         android:label="@string/tests_name"
         android:screenOrientation="portrait"
         android:icon="@mipmap/dali_tests"
         android:label="@string/tests_name"
         android:screenOrientation="portrait"
-        android:windowSoftInputMode="stateAlwaysVisible">
+        android:windowSoftInputMode="stateAlwaysVisible"
+        android:process=":dalitests">
       <!-- Tell NativeActivity the name of our .so -->
       <meta-data android:name="android.app.lib_name"
           android:value="native-activity" />
       <!-- Tell NativeActivity the name of our .so -->
       <meta-data android:name="android.app.lib_name"
           android:value="native-activity" />
index 39e67ad..fff12ab 100644 (file)
@@ -24,6 +24,7 @@ ADD_LIBRARY(native-activity SHARED main.cpp)
 TARGET_INCLUDE_DIRECTORIES(native-activity PRIVATE
   ${ANDROID_NDK}/sources/android/native_app_glue)
 
 TARGET_INCLUDE_DIRECTORIES(native-activity PRIVATE
   ${ANDROID_NDK}/sources/android/native_app_glue)
 
+INCLUDE_DIRECTORIES(.)
 INCLUDE_DIRECTORIES(${DALI_ENV_DIR}/include)
 INCLUDE_DIRECTORIES(${DALI_ENV_DIR}/include/dali)
 
 INCLUDE_DIRECTORIES(${DALI_ENV_DIR}/include)
 INCLUDE_DIRECTORIES(${DALI_ENV_DIR}/include/dali)
 
diff --git a/build/android/app/src/main/cpp/dali-demo-native-activity-jni.h b/build/android/app/src/main/cpp/dali-demo-native-activity-jni.h
new file mode 100644 (file)
index 0000000..2b2df8d
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_DALI_DEMO_NATIVE_ACTIVITY_JNI_H
+#define ANDROID_DALI_DEMO_NATIVE_ACTIVITY_JNI_H
+
+#include <string>
+#include <android_native_app_glue.h>
+
+class DaliDemoNativeActivity
+{
+public:
+  DaliDemoNativeActivity(ANativeActivity* activity)
+  : activity(activity)
+  {
+  }
+
+  class JString
+  {
+  public:
+    JString(JNIEnv* env, const std::string& str)
+    : env(env),
+      string(env->NewStringUTF(str.c_str()))
+    {
+    }
+
+    JString(JNIEnv* env, jstring str)
+    : env(env),
+      string(str)
+    {
+    }
+
+    std::string ToString()
+    {
+      std::string out;
+      if (string)
+      {
+        const char* utf = env->GetStringUTFChars(string, 0);
+        out = std::string(utf);
+        env->ReleaseStringUTFChars(string, utf);
+      }
+      return out;
+    }
+
+    ~JString()
+    {
+      if (string)
+      {
+        env->DeleteLocalRef(string);
+      }
+    }
+
+  private:
+    friend class DaliDemoNativeActivity;
+    JNIEnv* env;
+    jstring string;
+  };
+
+  class NativeActivityJNI
+  {
+  public:
+    NativeActivityJNI(ANativeActivity* activity)
+    : activity(activity)
+    {
+      activity->vm->AttachCurrentThread(&env, nullptr);
+      clazz = env->GetObjectClass(activity->clazz);
+    }
+
+    ~NativeActivityJNI()
+    {
+      activity->vm->DetachCurrentThread();
+    }
+
+    std::string CallStringMethod(const std::string& name, const std::string& arg)
+    {
+      jmethodID methodID = env->GetMethodID(clazz, name.c_str(), "(Ljava/lang/String;)Ljava/lang/String;");
+      JString argument(env, arg);
+      JString returnValue(env, (jstring)env->CallObjectMethod(activity->clazz, methodID, argument.string));
+      return returnValue.ToString();
+    }
+
+    void CallVoidMethod(const std::string& name, const std::string& arg)
+    {
+      jmethodID methodID = env->GetMethodID(clazz, name.c_str(), "(Ljava/lang/String;)V");
+      JString argument(env, arg);
+      env->CallVoidMethod(activity->clazz, methodID, argument.string);
+    }
+
+  private:
+    ANativeActivity* activity;
+    JNIEnv* env;
+    jclass clazz;
+  };
+
+  std::string GetMetaData(const std::string& key)
+  {
+    NativeActivityJNI nativeActivityJNI(activity);
+    return nativeActivityJNI.CallStringMethod("getMetaData", key);
+  }
+
+  std::string GetIntentStringExtra(const std::string& key)
+  {
+    NativeActivityJNI nativeActivityJNI(activity);
+    return nativeActivityJNI.CallStringMethod("getIntentStringExtra", key);
+  }
+
+  void LaunchExample(const std::string& exampleName)
+  {
+    NativeActivityJNI nativeActivityJNI(activity);
+    return nativeActivityJNI.CallVoidMethod("launchExample", exampleName);
+  }
+
+private:
+  ANativeActivity* activity;
+};
+
+#endif //ANDROID_DALI_DEMO_NATIVE_ACTIVITY_JNI_H
index 02fb4c4..09fe76a 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <android/log.h>
 #include <android_native_app_glue.h>
 
 #include <android/log.h>
 #include <android_native_app_glue.h>
+#include <dali-demo-native-activity-jni.h>
 #include <dali/devel-api/adaptor-framework/application-devel.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/adaptor-framework/android/android-framework.h>
 #include <dali/devel-api/adaptor-framework/application-devel.h>
 #include <dali/integration-api/debug.h>
 #include <dali/integration-api/adaptor-framework/android/android-framework.h>
@@ -39,16 +40,17 @@ namespace
 
 void free_saved_state(struct android_app *android_app)
 {
 
 void free_saved_state(struct android_app *android_app)
 {
-    pthread_mutex_lock(&android_app->mutex);
+  LOGV("free_saved_state");
+  pthread_mutex_lock(&android_app->mutex);
 
 
-    if (android_app->savedState != NULL)
-    {
-      free(android_app->savedState);
-      android_app->savedState = NULL;
-      android_app->savedStateSize = 0;
-    }
+  if (android_app->savedState != NULL)
+  {
+    free(android_app->savedState);
+    android_app->savedState = NULL;
+    android_app->savedStateSize = 0;
+  }
 
 
-    pthread_mutex_unlock(&android_app->mutex);
+  pthread_mutex_unlock(&android_app->mutex);
 }
 
 void android_app_destroy(struct android_app *android_app)
 }
 
 void android_app_destroy(struct android_app *android_app)
@@ -145,77 +147,12 @@ void ExtractFontConfig(struct android_app* state, std::string assetFontConfig, s
   }
 }
 
   }
 }
 
-class DaliDemoNativeActivity
-{
-public:
-  ANativeActivity* activity;
-  DaliDemoNativeActivity(ANativeActivity* activity)
-  : activity(activity)
-  {
-  }
-
-  class NativeActivityJNI
-  {
-  public:
-    ANativeActivity* activity;
-    JNIEnv* env;
-    jclass clazz;
-
-    NativeActivityJNI(ANativeActivity* activity)
-    : activity(activity)
-    {
-      activity->vm->AttachCurrentThread(&env, NULL);
-      clazz = env->GetObjectClass(activity->clazz);
-    }
-
-    ~NativeActivityJNI()
-    {
-      activity->vm->DetachCurrentThread();
-    }
-
-    jstring toJString(const std::string& str)
-    {
-      return env->NewStringUTF(str.c_str());
-    }
-
-    std::string toString(jstring jstr)
-    {
-      std::string out;
-      if (jstr)
-      {
-        const char* utf = env->GetStringUTFChars(jstr, 0);
-        out = std::string(utf);
-        env->ReleaseStringUTFChars(jstr, utf);
-      }
-
-      return out;
-    }
-
-    std::string callStringMethod(const std::string& name, const std::string& arg)
-    {
-      jmethodID methodID = env->GetMethodID(clazz, name.c_str(), "(Ljava/lang/String;)Ljava/lang/String;");
-      jstring jstr = (jstring)env->CallObjectMethod(activity->clazz, methodID, toJString(arg));
-      return toString(jstr);
-    }
-  };
-
-  std::string getMetaData(const std::string& key)
-  {
-    NativeActivityJNI nativeActivityJNI(activity);
-    return nativeActivityJNI.callStringMethod("getMetaData", key);
-  }
-
-  std::string getIntentStringExtra(const std::string& key)
-  {
-    NativeActivityJNI nativeActivityJNI(activity);
-    return nativeActivityJNI.callStringMethod("getIntentStringExtra", key);
-  }
-};
-
 extern "C" void FcConfigPathInit(const char* path, const char* file);
 
 void android_main( struct android_app* state )
 {
 extern "C" void FcConfigPathInit(const char* path, const char* file);
 
 void android_main( struct android_app* state )
 {
+  LOGV("android_main() >>");
+
   std::string filesDir = state->activity->internalDataPath;
 
   std::string fontconfigPath = filesDir + "/fonts";
   std::string filesDir = state->activity->internalDataPath;
 
   std::string fontconfigPath = filesDir + "/fonts";
@@ -239,19 +176,19 @@ void android_main( struct android_app* state )
   }
 
   Dali::Integration::AndroidFramework::New();
   }
 
   Dali::Integration::AndroidFramework::New();
-  Dali::Integration::AndroidFramework::Get().SetNativeApplication( state );
-  Dali::Integration::AndroidFramework::Get().SetApplicationConfiguration( state->config );
-  Dali::Integration::AndroidFramework::Get().SetApplicationAssets( state->activity->assetManager );
-  Dali::Integration::AndroidFramework::Get().SetInternalDataPath( filesDir );
+  Dali::Integration::AndroidFramework::Get().SetNativeApplication(state);
+  Dali::Integration::AndroidFramework::Get().SetApplicationConfiguration(state->config);
+  Dali::Integration::AndroidFramework::Get().SetApplicationAssets(state->activity->assetManager);
+  Dali::Integration::AndroidFramework::Get().SetInternalDataPath(filesDir);
 
   DaliDemoNativeActivity nativeActivity(state->activity);
 
   int status = 0;
   std::string libpath = "/data/data/com.sec.dalidemo/lib/libdali-demo.so";
 
   DaliDemoNativeActivity nativeActivity(state->activity);
 
   int status = 0;
   std::string libpath = "/data/data/com.sec.dalidemo/lib/libdali-demo.so";
-  std::string callParam = nativeActivity.getIntentStringExtra("start");
+  std::string callParam = nativeActivity.GetIntentStringExtra("start");
   if (callParam.empty())
   {
   if (callParam.empty())
   {
-    callParam = nativeActivity.getMetaData("start");
+    callParam = nativeActivity.GetMetaData("start");
   }
 
   if (!callParam.empty())
   }
 
   if (!callParam.empty())
@@ -259,7 +196,7 @@ void android_main( struct android_app* state )
     libpath = "/data/data/com.sec.dalidemo/lib/lib" +  callParam + ".so";
   }
 
     libpath = "/data/data/com.sec.dalidemo/lib/lib" +  callParam + ".so";
   }
 
-  void* handle = dlopen( libpath.c_str(), RTLD_LAZY );
+  void* handle = dlopen(libpath.c_str(), RTLD_LAZY);
   if (!handle)
   {
     std::exit(status);
   if (!handle)
   {
     std::exit(status);
@@ -286,7 +223,9 @@ void android_main( struct android_app* state )
   Dali::Integration::AndroidFramework::Get().SetApplicationAssets(nullptr);
   Dali::Integration::AndroidFramework::Delete();
 
   Dali::Integration::AndroidFramework::Get().SetApplicationAssets(nullptr);
   Dali::Integration::AndroidFramework::Delete();
 
-  // We need to kill the application process manually, DALi cannot restart in the same process due to memory leaks
+  LOGV("android_main() <<");
+
+  // We need to kill the application process manually, DALi cannot exit the process properly due to memory leaks
   std::exit(status);
 }
 
   std::exit(status);
 }
 
index 64a7853..e894f60 100644 (file)
@@ -4,6 +4,7 @@ import android.annotation.TargetApi;
 import android.app.NativeActivity;
 import android.content.ComponentName;
 import android.content.Context;
 import android.app.NativeActivity;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -94,4 +95,10 @@ public class DaliDemoNativeActivity extends NativeActivity {
     public final String getIntentStringExtra(String key) {
         return getIntent().getStringExtra(key);
     }
     public final String getIntentStringExtra(String key) {
         return getIntent().getStringExtra(key);
     }
+
+    public final void launchExample(String exampleName) {
+        Intent intent = new Intent(this, DaliDemoNativeActivity.class);
+        intent.putExtra("start", exampleName);
+        startActivity(intent);
+    }
 }
 }
diff --git a/build/android/app/src/main/java/com/sec/dalidemo/DaliDemosNativeActivity.java b/build/android/app/src/main/java/com/sec/dalidemo/DaliDemosNativeActivity.java
new file mode 100644 (file)
index 0000000..a2a735c
--- /dev/null
@@ -0,0 +1,4 @@
+package com.sec.dalidemo;
+
+public class DaliDemosNativeActivity extends DaliDemoNativeActivity {
+}
index 838f3c3..53fa788 100644 (file)
@@ -207,6 +207,12 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${REQUIRED_CFLAGS} ${DALI_DEMO_CFLAGS} -Werr
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}")
 
 INCLUDE_DIRECTORIES(${ROOT_SRC_DIR})
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS}")
 
 INCLUDE_DIRECTORIES(${ROOT_SRC_DIR})
+IF(ANDROID)
+  INCLUDE_DIRECTORIES( ${ANDROID_NDK}/sources/android/native_app_glue )
+  INCLUDE_DIRECTORIES( ${ANDROID_NDK}/sysroot/usr )
+  INCLUDE_DIRECTORIES( ${ANDROID_NDK}/sysroot/usr/include/android )
+  INCLUDE_DIRECTORIES( ${ROOT_SRC_DIR}/build/android/app/src/main/cpp )
+ENDIF()
 
 ADD_SUBDIRECTORY(demo)
 ADD_SUBDIRECTORY(examples)
 
 ADD_SUBDIRECTORY(demo)
 ADD_SUBDIRECTORY(examples)
index d042a55..2b91241 100644 (file)
  // EXTERNAL INCLUDES
 #include <sstream>
 #include <unistd.h>
  // EXTERNAL INCLUDES
 #include <sstream>
 #include <unistd.h>
+
 #include <dali/public-api/common/dali-common.h>
 #include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/adaptor-framework/android/android-framework.h>
+
+#include <android_native_app_glue.h>
+#include <dali-demo-native-activity-jni.h>
 
 void ExecuteProcess( const std::string& processName, Dali::Application& application )
 {
 
 void ExecuteProcess( const std::string& processName, Dali::Application& application )
 {
-  std::stringstream stream;
-  stream << "am start -a android.intent.action.MAIN -n com.sec.dalidemo/.DaliDemoNativeActivity --user 0 --es start " << processName.c_str();
-  pid_t parentPID = getpid();
-
-  pid_t pid = fork();
-  if( pid == 0 )
+  struct android_app* nativeApp = Dali::Integration::AndroidFramework::Get().GetNativeApplication();
+  if (!nativeApp)
   {
   {
-    do
-    {
-      sleep( 1 );
-    }
-    while( kill( parentPID, 0 ) == 0 );
-
-    system( stream.str().c_str() );
-    exit( 0 );
-  }
-  else
-  {
-    application.Quit();
+    DALI_LOG_ERROR("Couldn't get native app.");
+    return;
   }
   }
+
+  DaliDemoNativeActivity nativeActivity(nativeApp->activity);
+  nativeActivity.LaunchExample(processName);
 }
 }