Added an application to test GC in Tizen (#573)
author최종헌/MDE Lab(SR)/삼성전자 <j-h.choi@samsung.com>
Fri, 30 Aug 2024 07:46:54 +0000 (16:46 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 30 Aug 2024 07:46:54 +0000 (16:46 +0900)
64 files changed:
tests/GC/AndroidGCTest/.gitignore [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/.gitignore [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/compiler.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/deploymentTargetSelector.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/gradle.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/migrations.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/misc.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/.idea/other.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/.gitignore [new file with mode: 0644]
tests/GC/AndroidGCTest/app/achartengine/achartengine-1.2.0.jar [new file with mode: 0644]
tests/GC/AndroidGCTest/app/build.gradle [new file with mode: 0644]
tests/GC/AndroidGCTest/app/proguard-rules.pro [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/androidTest/java/com/android/gctest/ExampleInstrumentedTest.java [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/AndroidManifest.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/AndroidGCTestMain.java [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/MainActivity.java [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/Profile.java [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/ProfileSettingActivity.java [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/ResultActivity.java [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/drawable/ic_launcher_background.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/drawable/ic_launcher_foreground.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/layout/activity_main.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/layout/activity_profile_config.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/layout/activity_result.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/menu/main.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-anydpi/ic_launcher.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/raw/profile.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/values-night/themes.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/values/colors.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/values/dimens.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/values/strings.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/values/styles.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/values/themes.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/xml/backup_rules.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/main/res/xml/data_extraction_rules.xml [new file with mode: 0644]
tests/GC/AndroidGCTest/app/src/test/java/com/android/gctest/ExampleUnitTest.java [new file with mode: 0644]
tests/GC/AndroidGCTest/build.gradle [new file with mode: 0644]
tests/GC/AndroidGCTest/gradle.properties [new file with mode: 0644]
tests/GC/AndroidGCTest/gradle/libs.versions.toml [new file with mode: 0644]
tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.jar [new file with mode: 0644]
tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.properties [new file with mode: 0644]
tests/GC/AndroidGCTest/gradlew [new file with mode: 0755]
tests/GC/AndroidGCTest/gradlew.bat [new file with mode: 0644]
tests/GC/AndroidGCTest/settings.gradle [new file with mode: 0644]
tests/GC/TizenGCTest/Directory.Build.targets [new file with mode: 0755]
tests/GC/TizenGCTest/GCTest.cs [new file with mode: 0755]
tests/GC/TizenGCTest/Profile.cs [new file with mode: 0755]
tests/GC/TizenGCTest/TizenGCTest.cs [new file with mode: 0755]
tests/GC/TizenGCTest/TizenGCTest.csproj [new file with mode: 0755]
tests/GC/TizenGCTest/res/profile.xml [new file with mode: 0755]
tests/GC/TizenGCTest/shared/res/TizenGCTest.png [new file with mode: 0755]
tests/GC/TizenGCTest/tizen-manifest.xml [new file with mode: 0755]
tests/GC/TizenGCTest/tizen_dotnet_project.yaml [new file with mode: 0755]

diff --git a/tests/GC/AndroidGCTest/.gitignore b/tests/GC/AndroidGCTest/.gitignore
new file mode 100644 (file)
index 0000000..aa724b7
--- /dev/null
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/tests/GC/AndroidGCTest/.idea/.gitignore b/tests/GC/AndroidGCTest/.idea/.gitignore
new file mode 100644 (file)
index 0000000..26d3352
--- /dev/null
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/tests/GC/AndroidGCTest/.idea/compiler.xml b/tests/GC/AndroidGCTest/.idea/compiler.xml
new file mode 100644 (file)
index 0000000..b589d56
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <bytecodeTargetLevel target="17" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/.idea/deploymentTargetSelector.xml b/tests/GC/AndroidGCTest/.idea/deploymentTargetSelector.xml
new file mode 100644 (file)
index 0000000..b268ef3
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="deploymentTargetSelector">
+    <selectionStates>
+      <SelectionState runConfigName="app">
+        <option name="selectionMode" value="DROPDOWN" />
+      </SelectionState>
+    </selectionStates>
+  </component>
+</project>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/.idea/gradle.xml b/tests/GC/AndroidGCTest/.idea/gradle.xml
new file mode 100644 (file)
index 0000000..0897082
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleMigrationSettings" migrationVersion="1" />
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+          </set>
+        </option>
+        <option name="resolveExternalAnnotations" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/.idea/migrations.xml b/tests/GC/AndroidGCTest/.idea/migrations.xml
new file mode 100644 (file)
index 0000000..f8051a6
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectMigrations">
+    <option name="MigrateToGradleLocalJavaHome">
+      <set>
+        <option value="$PROJECT_DIR$" />
+      </set>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/.idea/misc.xml b/tests/GC/AndroidGCTest/.idea/misc.xml
new file mode 100644 (file)
index 0000000..8978d23
--- /dev/null
@@ -0,0 +1,9 @@
+<project version="4">
+  <component name="ExternalStorageConfigurationManager" enabled="true" />
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/.idea/other.xml b/tests/GC/AndroidGCTest/.idea/other.xml
new file mode 100644 (file)
index 0000000..94c96f6
--- /dev/null
@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="direct_access_persist.xml">
+    <option name="deviceSelectionList">
+      <list>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="27" />
+          <option name="brand" value="DOCOMO" />
+          <option name="codename" value="F01L" />
+          <option name="id" value="F01L" />
+          <option name="manufacturer" value="FUJITSU" />
+          <option name="name" value="F-01L" />
+          <option name="screenDensity" value="360" />
+          <option name="screenX" value="720" />
+          <option name="screenY" value="1280" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="28" />
+          <option name="brand" value="DOCOMO" />
+          <option name="codename" value="SH-01L" />
+          <option name="id" value="SH-01L" />
+          <option name="manufacturer" value="SHARP" />
+          <option name="name" value="AQUOS sense2 SH-01L" />
+          <option name="screenDensity" value="480" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2160" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="31" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="a51" />
+          <option name="id" value="a51" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy A51" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="akita" />
+          <option name="id" value="akita" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 8a" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="b0q" />
+          <option name="id" value="b0q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S22 Ultra" />
+          <option name="screenDensity" value="600" />
+          <option name="screenX" value="1440" />
+          <option name="screenY" value="3088" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="32" />
+          <option name="brand" value="google" />
+          <option name="codename" value="bluejay" />
+          <option name="id" value="bluejay" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 6a" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="caiman" />
+          <option name="id" value="caiman" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 9 Pro" />
+          <option name="screenDensity" value="360" />
+          <option name="screenX" value="960" />
+          <option name="screenY" value="2142" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="comet" />
+          <option name="id" value="comet" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 9 Pro Fold" />
+          <option name="screenDensity" value="390" />
+          <option name="screenX" value="2076" />
+          <option name="screenY" value="2152" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="29" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="crownqlteue" />
+          <option name="id" value="crownqlteue" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Note9" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2220" />
+          <option name="screenY" value="1080" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="dm3q" />
+          <option name="id" value="dm3q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S23 Ultra" />
+          <option name="screenDensity" value="600" />
+          <option name="screenX" value="1440" />
+          <option name="screenY" value="3088" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="e1q" />
+          <option name="id" value="e1q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S24" />
+          <option name="screenDensity" value="480" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2340" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="felix" />
+          <option name="id" value="felix" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Fold" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2208" />
+          <option name="screenY" value="1840" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="felix" />
+          <option name="id" value="felix" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Fold" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2208" />
+          <option name="screenY" value="1840" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="felix_camera" />
+          <option name="id" value="felix_camera" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Fold (Camera-enabled)" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="2208" />
+          <option name="screenY" value="1840" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="gts8uwifi" />
+          <option name="id" value="gts8uwifi" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Tab S8 Ultra" />
+          <option name="screenDensity" value="320" />
+          <option name="screenX" value="1848" />
+          <option name="screenY" value="2960" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="husky" />
+          <option name="id" value="husky" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 8 Pro" />
+          <option name="screenDensity" value="390" />
+          <option name="screenX" value="1008" />
+          <option name="screenY" value="2244" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="30" />
+          <option name="brand" value="motorola" />
+          <option name="codename" value="java" />
+          <option name="id" value="java" />
+          <option name="manufacturer" value="Motorola" />
+          <option name="name" value="G20" />
+          <option name="screenDensity" value="280" />
+          <option name="screenX" value="720" />
+          <option name="screenY" value="1600" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="komodo" />
+          <option name="id" value="komodo" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 9 Pro XL" />
+          <option name="screenDensity" value="360" />
+          <option name="screenX" value="1008" />
+          <option name="screenY" value="2244" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="lynx" />
+          <option name="id" value="lynx" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 7a" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="31" />
+          <option name="brand" value="google" />
+          <option name="codename" value="oriole" />
+          <option name="id" value="oriole" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 6" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="panther" />
+          <option name="id" value="panther" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 7" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="q5q" />
+          <option name="id" value="q5q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy Z Fold5" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1812" />
+          <option name="screenY" value="2176" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="30" />
+          <option name="brand" value="google" />
+          <option name="codename" value="r11" />
+          <option name="id" value="r11" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Watch" />
+          <option name="screenDensity" value="320" />
+          <option name="screenX" value="384" />
+          <option name="screenY" value="384" />
+          <option name="type" value="WEAR_OS" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="30" />
+          <option name="brand" value="google" />
+          <option name="codename" value="redfin" />
+          <option name="id" value="redfin" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 5" />
+          <option name="screenDensity" value="440" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2340" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="shiba" />
+          <option name="id" value="shiba" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 8" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2400" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="33" />
+          <option name="brand" value="google" />
+          <option name="codename" value="tangorpro" />
+          <option name="id" value="tangorpro" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel Tablet" />
+          <option name="screenDensity" value="320" />
+          <option name="screenX" value="1600" />
+          <option name="screenY" value="2560" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="34" />
+          <option name="brand" value="google" />
+          <option name="codename" value="tokay" />
+          <option name="id" value="tokay" />
+          <option name="manufacturer" value="Google" />
+          <option name="name" value="Pixel 9" />
+          <option name="screenDensity" value="420" />
+          <option name="screenX" value="1080" />
+          <option name="screenY" value="2424" />
+        </PersistentDeviceSelectionData>
+        <PersistentDeviceSelectionData>
+          <option name="api" value="29" />
+          <option name="brand" value="samsung" />
+          <option name="codename" value="x1q" />
+          <option name="id" value="x1q" />
+          <option name="manufacturer" value="Samsung" />
+          <option name="name" value="Galaxy S20" />
+          <option name="screenDensity" value="480" />
+          <option name="screenX" value="1440" />
+          <option name="screenY" value="3200" />
+        </PersistentDeviceSelectionData>
+      </list>
+    </option>
+  </component>
+</project>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/.gitignore b/tests/GC/AndroidGCTest/app/.gitignore
new file mode 100644 (file)
index 0000000..42afabf
--- /dev/null
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/achartengine/achartengine-1.2.0.jar b/tests/GC/AndroidGCTest/app/achartengine/achartengine-1.2.0.jar
new file mode 100644 (file)
index 0000000..6356acc
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/achartengine/achartengine-1.2.0.jar differ
diff --git a/tests/GC/AndroidGCTest/app/build.gradle b/tests/GC/AndroidGCTest/app/build.gradle
new file mode 100644 (file)
index 0000000..bb39129
--- /dev/null
@@ -0,0 +1,41 @@
+plugins {
+    alias(libs.plugins.android.application)
+}
+
+android {
+    namespace 'com.android.gctest'
+    compileSdk 34
+
+    defaultConfig {
+        applicationId "com.android.gctest"
+        minSdk 29
+        targetSdk 34
+        versionCode 1
+        versionName "1.0"
+
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+}
+
+dependencies {
+
+    implementation libs.appcompat
+    implementation libs.material
+    implementation libs.activity
+    implementation libs.constraintlayout
+    implementation files('achartengine/achartengine-1.2.0.jar')
+    testImplementation libs.junit
+    androidTestImplementation libs.ext.junit
+    androidTestImplementation libs.espresso.core
+}
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/proguard-rules.pro b/tests/GC/AndroidGCTest/app/proguard-rules.pro
new file mode 100644 (file)
index 0000000..481bb43
--- /dev/null
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/androidTest/java/com/android/gctest/ExampleInstrumentedTest.java b/tests/GC/AndroidGCTest/app/src/androidTest/java/com/android/gctest/ExampleInstrumentedTest.java
new file mode 100644 (file)
index 0000000..8583426
--- /dev/null
@@ -0,0 +1,26 @@
+package com.android.gctest;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+    @Test
+    public void useAppContext() {
+        // Context of the app under test.
+        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+        assertEquals("com.android.gctest", appContext.getPackageName());
+    }
+}
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/AndroidManifest.xml b/tests/GC/AndroidGCTest/app/src/main/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..6177998
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <application
+        android:allowBackup="true"
+        android:dataExtractionRules="@xml/data_extraction_rules"
+        android:fullBackupContent="@xml/backup_rules"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:roundIcon="@mipmap/ic_launcher_round"
+        android:supportsRtl="true"
+        android:theme="@style/Theme.AndroidGCTest"
+        tools:targetApi="31"
+        android:largeHeap="true">
+        <activity
+            android:name=".MainActivity"
+            android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity
+            android:name=".ResultActivity" >
+        </activity>
+        <activity
+            android:name=".ProfileSettingActivity" >
+        </activity>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/AndroidGCTestMain.java b/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/AndroidGCTestMain.java
new file mode 100644 (file)
index 0000000..4923f46
--- /dev/null
@@ -0,0 +1,1166 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.gctest;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Random;
+import java.lang.reflect.Method;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.Message;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.Log;
+
+// 6 kinds of small objects
+class TreeNode { // object size = 16
+    TreeNode left, right;
+    TreeNode (TreeNode l, TreeNode r) { left = l; right = r; }
+    TreeNode () { }
+    int count() {
+        int c = 1;
+        if (left != null)
+            c += left.count();
+        if (right != null)
+            c += right.count();
+        return c;
+    }
+}
+
+class TreeNode32 extends TreeNode { // object size = 24
+    private long payload1;
+    TreeNode32(TreeNode32 l, TreeNode32 r) { left = l; right = r; }
+    TreeNode32() { }
+}
+
+class TreeNode64 extends TreeNode { // object size = 40
+    private long payload1, payload2, payload3;
+    TreeNode64(TreeNode64 l, TreeNode64 r) { left = l; right = r; }
+    TreeNode64() { }
+}
+
+class TreeNode128 extends TreeNode { // object size = 96
+    private long payload1, payload2, payload3, payload4, payload5;
+    private long payload6, payload7, payload8, payload9, payload10;
+    TreeNode128(TreeNode128 l, TreeNode128 r) { left = l; right = r; }
+    TreeNode128() { }
+}
+
+class TreeNode256 extends TreeNode { // object size = 192
+    private long payload1, payload2, payload3, payload4, payload5;
+    private long payload6, payload7, payload8, payload9, payload10;
+    private long payload11, payload12, payload13, payload14, payload15;
+    private long payload16, payload17, payload18, payload19, payload20;
+    private long payload21, payload22;
+    TreeNode256(TreeNode256 l, TreeNode256 r) { left = l; right = r; }
+    TreeNode256() { }
+}
+
+class TreeNode512 extends TreeNode { // object size = 336
+    private long payload1, payload2, payload3, payload4, payload5;
+    private long payload6, payload7, payload8, payload9, payload10;
+    private long payload11, payload12, payload13, payload14, payload15;
+    private long payload16, payload17, payload18, payload19, payload20;
+    private long payload101, payload102, payload103, payload104, payload105;
+    private long payload106, payload107, payload108, payload109, payload100;
+    private long payload111, payload112, payload113, payload114, payload115;
+    private long payload116, payload117, payload118, payload119, payload120;
+    TreeNode512(TreeNode512 l, TreeNode512 r) { left = l; right = r; }
+    TreeNode512() { }
+}
+
+class LinkNode {
+    LinkNode next;
+    TreeNode treeNode;
+    LinkNode(TreeNode n) { treeNode = n; }
+    LinkNode() { }
+}
+
+class LivedLink {
+    public LinkNode treeHead;
+    LivedLink() { treeHead = null;}
+    void insertNode(TreeNode newTree) {
+        if (treeHead == null) {
+            treeHead = new LinkNode(newTree);
+            treeHead.next = null;
+        } else {
+            LinkNode newNode = new LinkNode(newTree);
+            newNode.next = treeHead;
+            treeHead = newNode;
+        }
+    }
+}
+
+public class AndroidGCTestMain {
+    private final String mTag = "AndroidGCTest";
+    private MainActivity mActivity = null;
+
+    // size of small objects
+    public static final int OBJECT_16_BYTE = 0;
+    public static final int OBJECT_32_BYTE = 1;
+    public static final int OBJECT_64_BYTE = 2;
+    public static final int OBJECT_128_BYTE = 3;
+    public static final int OBJECT_256_BYTE = 4;
+    public static final int OBJECT_512_BYTE = 5;
+    public static final int OBJECT_LARGE_BYTE = 6;
+    public static final int OBJECT_SIZE_TYPE = 7;
+    private final int[] mObjectSize = new int[]{16, 24, 40, 96, 192, 336};
+
+    // size of large object, default is 12KByte
+    private int mLargeObjectSize = 0;
+    // array element type distribution for large object
+    // {1-byte array, 2-byte array, 4-byte array, 8-byte array}
+    private float[] mLargeObjectDistribution = null;
+
+    // allocation configuration
+    // total allocate size
+    private int mTotalAllocateSize = 0;
+    // total allocate size by one thread
+    private int mTotalAllocSizePerThread = 0;
+
+    // unit for tree allocation/deletion operation.
+    // mBucketSize is also the unit to measure object lifetime.
+    // Benchmark allocates mBucketSize of data -> deletes some data
+    // -> allocates mBucketSize of Data
+    private int mBucketSize = 0;
+
+    // allocated object size distribution
+    // {[1-16], [17-32], [33-64], [65, 128], [129, 256], [257, 512], >12K}
+    private float[] mSizeDistribution = null;
+
+    // allocated object lifetime:
+    // mLifetime[X][0] is long lived object percentage of object size X,
+    // mLifetime[X][1] is percentage of object die immediately,
+    // mLifetime[X][2] is percentage of object die in next period after
+    // creation period ...
+    private float[][] mLifetime =  null;
+
+    private int mLongLiveSmallObjectSize;
+
+    // a big array to store random values to decide object size of next allocated object
+    private byte[][] mObjectSizeRandom = null;
+    // a big array to store random values to decide lifetime of next allocated object
+    private byte[][] mLifetimeRandom = null;
+    private int mShortLiveTreeCount;
+    private int mTotalNodeCount;
+    private final int mTreeCountParallel = 4;
+
+    private int[] mLargeArrayLength = null;
+    private int[] mLargeArrayNum = null;
+    private int[] mLargeArrayInter = null;
+    private int mLongLiveLargeObjectSize;
+    private int[][] mDieNumLargeObject = null;
+
+    // thread mode configuration
+    private int mThreadNum;
+    private boolean mSingleThread = false;
+
+    private long[] mElapseTime = null;
+    private int[] mHeapFootprint = null;
+    private long[] mHeapBytesAllocated = null;
+
+    private long mTotalGcCount;
+    private long mTotalGcTime;
+    private long mTotalBlockingGcCount;
+    private long mTotalBlockingGcTime;
+    public final String[] GC_CAUSE_ART = new String[]{"Alloc", "Background", "Explicit",
+            "NativeAlloc", "CollectorTransition", "DisableMovingGc", "HomogeneousSpaceCompact",
+            "HeapTrim"};
+    public final String[] GC_CAUSE_DALVIK = new String[]{"GC_FOR_ALLOC","GC_CONCURRENT",
+            "GC_EXPLICIT", "GC_BEFORE_OOM"};
+    private int[] mGcCauseCount = null;
+    private float[] mGcPauseTime = null;
+    private float[] mGcTotalTime = null;
+    private String[] mGcCause = null;
+
+    private boolean isArt;
+    private boolean mWorkloadComplete;
+    private int mIterNum = 100;
+
+    private FileWriter fileOutput;
+    private BenchThread[] mTestThreads;
+    private boolean mOutOfMemory;
+
+    // initialize benchmark setting
+    private void init() {
+        // thread number;
+        if (mSingleThread) {
+            mThreadNum = 1;
+        } else if (mThreadNum == 0) {
+            mThreadNum = Runtime.getRuntime().availableProcessors();
+        }
+        if (mThreadNum == 0) {
+            mThreadNum = 1;
+        }
+
+        if (mSizeDistribution == null) {
+            mSizeDistribution = new float[]{0.0436f,0.5465f,0.2103f,0.1499f,
+                    0.0275f,0.0125f,0.0097f};
+        }
+        if (mLifetime == null) {
+            mLifetime = new float[][] {
+                    {0.0865f,0.5404f,0.2887f,0.0865f},
+                    {0.0469f,0.7724f,0.1460f,0.0346f},
+                    {0.1154f,0.5982f,0.1880f,0.0984f},
+                    {0.0662f,0.7851f,0.1077f,0.0411f},
+                    {0.0520f,0.8778f,0.0503f,0.0198f},
+                    {0.1628f,0.7137f,0.0821f,0.0414f},
+                    {0.0923f,0.7117f,0.1769f,0.0192f} // large object lifetime
+            };
+        }
+
+        if (mLargeObjectDistribution == null) {
+            mLargeObjectDistribution = new float[]{0.9f, 0.07f, 0.02f, 0.01f};
+        }
+
+        if (mTotalAllocateSize == 0) {
+            mTotalAllocateSize = 100 * 1024 * 1024;
+        }
+        mTotalAllocSizePerThread = mTotalAllocateSize / mThreadNum;
+
+        if (mBucketSize == 0) {
+            mBucketSize = 1 * 1024 * 1024;
+        }
+
+        if (mLargeObjectSize == 0) {
+            mLargeObjectSize = 12 * 1024;
+        }
+
+        Log.i(mTag, "Allocate Size: " + (mTotalAllocateSize / 1024) + " kB");
+        Log.i(mTag, "BucketSize: " + (mBucketSize / 1024) + " kB");
+        Log.i(mTag, "Large object size: " + (mLargeObjectSize / 1024) + " kB");
+        Log.i(mTag, "Single Thread: " + mSingleThread);
+        Log.i(mTag, "Thread number: " + mThreadNum);
+        Log.i(mTag, "Stress test part iterates " + mIterNum + " times");
+
+        String curDate = DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
+        try {
+            fileOutput = new FileWriter("/sdcard/AndroidGCTest-result.txt", true);
+            fileOutput.append("\n\n" + curDate);
+
+            fileOutput.append("\nWorkload configuration:");
+            fileOutput.append("\n\tAllocate Size: " + (mTotalAllocateSize / 1024) + " kB");
+            fileOutput.append("\n\tBucketSize: " + (mBucketSize / 1024) + " kB");
+            fileOutput.append("\n\tLarge object size: " + (mLargeObjectSize / 1024) + " kB");
+            fileOutput.append("\n\tThread mode: "
+                    + (mSingleThread? "Single-Thread" : "Multi-Thread"));
+            fileOutput.append("\n\tThread number: " + mThreadNum);
+            fileOutput.append("\n\tStress test part iterates " + mIterNum + " times");
+        } catch (IOException e) {
+            Log.i(mTag, "Cannot open /sdcard/AndroidGCTest-result.txt" + e.getMessage());
+        }
+
+        int smallObjectSize, largeObjectSize;
+        largeObjectSize = (int)(mTotalAllocSizePerThread * mSizeDistribution[OBJECT_LARGE_BYTE]);
+        smallObjectSize = mTotalAllocSizePerThread - largeObjectSize;
+
+        float[] countDistr = new float[OBJECT_LARGE_BYTE];
+        float nodeSize = 0.0f;
+        int[] sizeThreshold = new int[OBJECT_LARGE_BYTE];
+        int lifetimeLen = mLifetime[0].length;
+        int[][] lifetimeThreshold = new int[OBJECT_LARGE_BYTE][lifetimeLen];
+        float sum = 0.0f;
+        for (int i = 0; i < OBJECT_LARGE_BYTE; i++) {
+            countDistr[i] = mSizeDistribution[i]
+                    / (1 - mSizeDistribution[OBJECT_LARGE_BYTE]) / mObjectSize[i];
+            sum += countDistr[i];
+        }
+
+        mLongLiveSmallObjectSize = 0;
+        float sum1 = 0.0f;
+        for (int i = 0; i < OBJECT_LARGE_BYTE; i++) {
+            sum1 += countDistr[i];
+            sizeThreshold[i] = (int)(sum1 * 1000 / sum + 0.5);
+            nodeSize += mObjectSize[i] * countDistr[i] / sum;
+
+            float sum2 = 0.0f;
+            for (int j = 1; j < lifetimeLen; j++) {
+                sum2 += mLifetime[i][j];
+                lifetimeThreshold[i][j-1] = (int)(sum2 * 1000 + 0.5);
+            }
+            lifetimeThreshold[i][lifetimeLen - 1] = 1000;
+
+            mLongLiveSmallObjectSize += mTotalAllocSizePerThread * mSizeDistribution[i]
+                    * mLifetime[i][0];
+        }
+        sizeThreshold[OBJECT_512_BYTE] = 1000;
+
+
+        mShortLiveTreeCount = (int)(smallObjectSize / mBucketSize + 0.5);
+        mTotalNodeCount = (int)(mBucketSize / nodeSize * 1.11);
+
+        mObjectSizeRandom = new byte[mThreadNum][mTotalNodeCount];
+        mLifetimeRandom = new byte[mThreadNum][mTotalNodeCount];
+        for (int i = 0; i < mThreadNum; i++) {
+            Random r_size = new Random(i);
+            Random r_lifetime = new Random(i + mThreadNum);
+            for (int j = 0; j < mTotalNodeCount; j++) {
+                int vs = r_size.nextInt(1000);
+                int vl = r_lifetime.nextInt(1000);
+                for (int k = 0; k < OBJECT_LARGE_BYTE; k++) {
+                    if (vs < sizeThreshold[k]) {
+                        mObjectSizeRandom[i][j] = (byte)(OBJECT_16_BYTE + k);
+                        for (int l = 0; l < lifetimeLen; l++) {
+                            if (vl < lifetimeThreshold[k][l]) {
+                                mLifetimeRandom[i][j] = (byte)l;
+                                break;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+
+        mLongLiveLargeObjectSize = (int)(largeObjectSize * mLifetime[OBJECT_LARGE_BYTE][0]);
+        mDieNumLargeObject = new int[4][lifetimeLen - 1];
+        mLargeArrayInter = new int[4];
+        mLargeArrayLength = new int[4];
+        mLargeArrayNum = new int[4];
+        for (int i = 0; i < 4; i++) {
+            mLargeArrayLength[i] = (int)((largeObjectSize * mLargeObjectDistribution[i]
+                    / mLargeObjectSize) + 0.5);
+            if (mLargeArrayLength[i] == 0) {
+                mLargeArrayInter[i] = mShortLiveTreeCount + 1;
+                mLargeArrayNum[i] = 0;
+                continue;
+            }
+            if (mShortLiveTreeCount > mLargeArrayLength[i]) {
+                mLargeArrayInter[i] = mShortLiveTreeCount / mLargeArrayLength[i];
+                mLargeArrayNum[i] = 1;
+                mLargeArrayLength[i] = mShortLiveTreeCount/mLargeArrayInter[i] + 1;
+            } else {
+                mLargeArrayInter[i] = 1;
+                mLargeArrayNum[i] = (int)(mLargeArrayLength[i]/(float)mShortLiveTreeCount + 0.5);
+                mLargeArrayLength[i] = mLargeArrayNum[i] * mShortLiveTreeCount;
+            }
+
+            sum = 0.0f;
+            for (int j = 1; j < lifetimeLen; j++) {
+                sum += mLifetime[OBJECT_LARGE_BYTE][j];
+                mDieNumLargeObject[i][j-1] = (int)(mLargeArrayNum[i] * sum);
+            }
+        }
+
+        Log.i(mTag, "init done");
+    }
+
+    private void clearInitData() {
+        Log.i(mTag, "clear auxiliary data to run workload");
+        mLifetime = null;
+        mLargeObjectDistribution = null;
+        mSizeDistribution = null;
+        mObjectSizeRandom = null;
+        mLifetimeRandom = null;
+        mLargeArrayInter = null;
+        mLargeArrayLength = null;
+        mLargeArrayNum = null;
+        mDieNumLargeObject = null;
+        Runtime.getRuntime().runFinalization();
+        Runtime.getRuntime().gc();
+    }
+
+    AndroidGCTestMain() {
+        init();
+    }
+    AndroidGCTestMain(MainActivity activity, int heapSize, int bucketSize, int largeObjectSize,
+                      float[]sizeDistr, float[][] lifetimeDistr, float[] largeObjectSizeDist,
+                      boolean singleThread, int thread_num, int exeTime) {
+        mActivity = activity;
+        mTotalAllocateSize = heapSize * 1024 * 1024;
+        mBucketSize = bucketSize * 1024 * 1024;
+        mLargeObjectSize = largeObjectSize * 1024;
+        mSizeDistribution = sizeDistr;
+        mLifetime = lifetimeDistr;
+        mLargeObjectDistribution = largeObjectSizeDist;
+        mSingleThread = singleThread;
+        mThreadNum = mSingleThread? 1 : thread_num;
+        mIterNum = exeTime > 0 ? exeTime : 100;
+        init();
+    }
+
+    private void freeArrays(byte[][] byteArray, char[][] charArray, int[][] intArray,
+                            long[][] longArray, int[] arrayIdx, int treeCount) {
+        int len = mDieNumLargeObject[0].length;
+        int died, release, phase;
+
+        phase = treeCount % mLargeArrayInter[0];
+        if (byteArray != null && phase <= len) {
+            int curIdx = arrayIdx[0] - mLargeArrayNum[0];
+            while (curIdx >= 0 && phase <= len) {
+                if (phase == 0)
+                    died = 0;
+                else
+                    died = mDieNumLargeObject[0][phase - 1];
+                if (phase == len) {
+                    if (byteArray[curIdx + died] != null) {
+                        for (int i = died; i < mLargeArrayNum[0]; i++)
+                            byteArray[curIdx + i] = null;
+                    }
+                    break;
+                }
+                release = mDieNumLargeObject[0][phase];
+                for (int i = died; i < release; i++) {
+                    if (i >= mLargeArrayNum[0])
+                        break;
+                    byteArray[curIdx + i] = null;
+                }
+                curIdx -= mLargeArrayNum[0];
+                phase += mLargeArrayInter[0];
+            }
+        }
+
+        phase = treeCount % mLargeArrayInter[1];
+        if (charArray != null && phase < mLargeArrayNum[1]) {
+            int curIdx = arrayIdx[1] - mLargeArrayNum[1];
+            while (curIdx >= 0 && phase <= len) {
+                if (phase == 0)
+                    died = 0;
+                else
+                    died = mDieNumLargeObject[1][phase - 1];
+                if (phase == len) {
+                    if (charArray[curIdx + died] != null) {
+                        for (int i = died; i < mLargeArrayNum[1]; i++)
+                            charArray[curIdx + i] = null;
+                    }
+                    break;
+                }
+                release = mDieNumLargeObject[1][phase];
+                for (int i = died; i < release; i++) {
+                    if (i >= mLargeArrayNum[1])
+                        break;
+                    charArray[curIdx + i] = null;
+                }
+                curIdx -= mLargeArrayNum[1];
+                phase += mLargeArrayInter[1];
+            }
+        }
+
+        phase = treeCount % mLargeArrayInter[2];
+        if (intArray != null && phase < mLargeArrayNum[2]) {
+            int curIdx = arrayIdx[2] - mLargeArrayNum[2];
+            while (curIdx >= 0 && phase <= len) {
+                if (phase == 0)
+                    died = 0;
+                else
+                    died = mDieNumLargeObject[2][phase - 1];
+                if (phase == len) {
+                    if (intArray[curIdx + died] != null) {
+                        for (int i = died; i < mLargeArrayNum[2]; i++)
+                            intArray[curIdx + i] = null;
+                    }
+                    break;
+                }
+                release = mDieNumLargeObject[2][phase];
+                for (int i = died; i < release; i++) {
+                    if (i >= mLargeArrayNum[2])
+                        break;
+                    intArray[curIdx + i] = null;
+                }
+                curIdx -= mLargeArrayNum[2];
+                phase += mLargeArrayInter[2];
+            }
+        }
+
+        phase = treeCount % mLargeArrayInter[3];
+        if (longArray != null && phase < mLargeArrayNum[3]) {
+            int curIdx = arrayIdx[3] - mLargeArrayNum[3];
+            while (curIdx >= 0 && phase <= len) {
+                if (phase == 0)
+                    died = 0;
+                else
+                    died = mDieNumLargeObject[3][phase - 1];
+                if (phase == len) {
+                    if (longArray[curIdx + died] != null) {
+                        for (int i = died; i < mLargeArrayNum[3]; i++)
+                            longArray[curIdx + i] = null;
+                    }
+                    break;
+                }
+                release = mDieNumLargeObject[3][phase];
+                for (int i = died; i < release; i++) {
+                    if (i >= mLargeArrayNum[3])
+                        break;
+                    longArray[curIdx + i] = null;
+                }
+                curIdx -= mLargeArrayNum[3];
+                phase += mLargeArrayInter[3];
+            }
+        }
+    }
+
+    private void makeTreesLongLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount) {
+        while (true) {
+            if (allocSize <= 0) {
+                trees = null;
+                return;
+            }
+
+            int len = trees.length;
+            TreeNode[] nextTrees = new TreeNode[len*2];
+            byte random;
+            for (int i = 0; i < len; i++) {
+                TreeNode node = null;
+                random = mObjectSizeRandom[myId][nodeCount[0]];
+                switch (random) {
+                    case OBJECT_16_BYTE:
+                        node = new TreeNode();
+                        break;
+                    case OBJECT_32_BYTE:
+                        node = new TreeNode32();
+                        break;
+                    case OBJECT_64_BYTE:
+                        node = new TreeNode64();
+                        break;
+                    case OBJECT_128_BYTE:
+                        node = new TreeNode128();
+                        break;
+                    case OBJECT_256_BYTE:
+                        node = new TreeNode256();
+                        break;
+                    case OBJECT_512_BYTE:
+                        node = new TreeNode512();
+                        break;
+                }
+                trees[i].left = node;
+                nextTrees[2 * i] = node;
+                allocSize -= mObjectSize[random];
+                nodeCount[0]++;
+                if (nodeCount[0] == mTotalNodeCount)
+                    nodeCount[0] = 0;
+
+                random = mObjectSizeRandom[myId][nodeCount[0]];
+                switch (random) {
+                    case OBJECT_16_BYTE:
+                        node = new TreeNode();
+                        break;
+                    case OBJECT_32_BYTE:
+                        node = new TreeNode32();
+                        break;
+                    case OBJECT_64_BYTE:
+                        node = new TreeNode64();
+                        break;
+                    case OBJECT_128_BYTE:
+                        node = new TreeNode128();
+                        break;
+                    case OBJECT_256_BYTE:
+                        node = new TreeNode256();
+                        break;
+                    case OBJECT_512_BYTE:
+                        node = new TreeNode512();
+                        break;
+                }
+                trees[i].right = node;
+                nextTrees[2*i + 1] = node;
+                allocSize -= mObjectSize[random];
+                nodeCount[0]++;
+                if (nodeCount[0] == mTotalNodeCount)
+                    nodeCount[0] = 0;
+
+                if (allocSize <= 0) {
+                    trees = null;
+                    break;
+                }
+            }
+            trees = null;
+            trees = nextTrees;
+        }
+    }
+
+    private void makeTreesShortLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount) {
+        int lifetimeLen = mLifetime[0].length;
+        int[] curTreeIdx = new int[lifetimeLen];
+        int[] nextTreeIdx = new int[lifetimeLen];
+        TreeNode[][] curTrees = new TreeNode[lifetimeLen][1];
+        TreeNode[][] nextTrees = new TreeNode[lifetimeLen][];
+        for (int i = 0; i < lifetimeLen; i++) {
+            curTrees[i][0] = trees[i];
+            curTreeIdx[i] = 0;
+        }
+
+        while (true) {
+            if (allocSize <= 0) {
+                trees = null;
+                return;
+            }
+
+            byte rs = mObjectSizeRandom[myId][nodeCount[0]];
+            TreeNode node = null;
+            switch (rs) {
+                case OBJECT_16_BYTE:
+                    node = new TreeNode();
+                    break;
+                case OBJECT_32_BYTE:
+                    node = new TreeNode32();
+                    break;
+                case OBJECT_64_BYTE:
+                    node = new TreeNode64();
+                    break;
+                case OBJECT_128_BYTE:
+                    node = new TreeNode128();
+                    break;
+                case OBJECT_256_BYTE:
+                    node = new TreeNode256();
+                    break;
+                case OBJECT_512_BYTE:
+                    node = new TreeNode512();
+                    break;
+            }
+
+            byte rl = mLifetimeRandom[myId][nodeCount[0]];
+            if (nextTrees[rl] == null) {
+                nextTrees[rl] = new TreeNode[curTrees[rl].length << 1];
+                nextTreeIdx[rl] = 0;
+                nextTrees[rl][0] = node;
+            } else {
+                nextTrees[rl][++nextTreeIdx[rl]] = node;
+            }
+            TreeNode parent = curTrees[rl][curTreeIdx[rl]];
+            if (parent.left == null) {
+                parent.left = node;
+            } else {
+                parent.right = node;
+                curTreeIdx[rl]++;
+                if (curTreeIdx[rl] == curTrees[rl].length) {
+                    curTrees[rl] = nextTrees[rl];
+                    nextTrees[rl] = null;
+                    curTreeIdx[rl] = 0;
+                }
+            }
+
+            allocSize -= mObjectSize[rs];
+            nodeCount[0]++;
+            if (nodeCount[0] == mTotalNodeCount) nodeCount[0] = 0;
+        }
+    }
+
+    public boolean allocTrace(int myId) throws OutOfMemoryError {
+        // long-lived data
+        Log.i(mTag, "Thread-" + myId + " ----- Build long lived trees -----");
+
+        LivedLink longLiveTreeLink = new LivedLink();
+        TreeNode[] trees = new TreeNode[mTreeCountParallel];
+
+        int[] nodeCount = new int[]{0};
+        for (int i = 0; i < mTreeCountParallel; i++) {
+            TreeNode node = new TreeNode();
+            longLiveTreeLink.insertNode(node);
+            trees[i] = node;
+        }
+
+        makeTreesLongLive(trees, mLongLiveSmallObjectSize, myId, nodeCount);
+
+        trees = null;
+
+        Log.i(mTag, "Thread-" + myId + " ----- Build long lived byte array -----");
+        int longLiveArrayCount = (int)(mLongLiveLargeObjectSize / mLargeObjectSize + 0.5);
+        if (longLiveArrayCount <= 0)
+            longLiveArrayCount = 1;
+        byte[][] longLiveByteArrays = new byte[longLiveArrayCount][];
+        for (int i = 0; i < longLiveArrayCount; i++) {
+            longLiveByteArrays[i] = new byte[mLargeObjectSize];
+            for (int j = 0; j < mLargeObjectSize; j+=100)
+                longLiveByteArrays[i][j] = (byte) 0xff;
+        }
+
+        // stress test
+        Log.i(mTag, "Thread-" + myId + " ----- Stress test -----");
+        Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
+
+        int lifetimeLen = mLifetime[0].length;
+        TreeNode[][] shortLiveTrees = new TreeNode[lifetimeLen][lifetimeLen];
+
+        byte[][] shortLiveByteArray = null;
+        char[][] shortLiveCharArray = null;
+        int[][] shortLiveIntArray = null;
+        long[][] shortLiveLongArray = null;
+
+        nodeCount[0] = 0;
+        int round = 0;
+
+        for (int iter = 0; iter < mIterNum; iter++) {
+            if (mOutOfMemory)
+                break;
+            int[] allocIdx = new int[]{0, 0, 0, 0};
+
+            if (mLargeArrayLength[0] != 0)
+                shortLiveByteArray = new byte[mLargeArrayLength[0]][];
+            if (mLargeArrayLength[1] != 0)
+                shortLiveCharArray = new char[mLargeArrayLength[1]][];
+            if (mLargeArrayLength[2] != 0)
+                shortLiveIntArray = new int[mLargeArrayLength[2]][];
+            if (mLargeArrayLength[3] != 0)
+                shortLiveLongArray = new long[mLargeArrayLength[3]][];
+
+            int treeCount = 0;
+            while (treeCount < mShortLiveTreeCount) {
+                int treesIdx = round % lifetimeLen;
+                round++;
+                for (int i = 0; i < lifetimeLen; i++) {
+                    TreeNode node = new TreeNode();
+                    shortLiveTrees[treesIdx][i] = node;
+                }
+                makeTreesShortLive(shortLiveTrees[treesIdx], mBucketSize, myId, nodeCount);
+
+                for (int i = 0; i < lifetimeLen; i++) {
+                    int idx = (treesIdx - i + lifetimeLen) % lifetimeLen;
+                    shortLiveTrees[idx][i] = null;
+                }
+
+                if ((mLargeArrayLength[0] > 0) && ((treeCount % mLargeArrayInter[0]) == 0)) {
+                    for (int n = 0; n < mLargeArrayNum[0]; n++)
+                        shortLiveByteArray[allocIdx[0] + n] = new byte[mLargeObjectSize];
+                    allocIdx[0] += mLargeArrayNum[0];
+                }
+
+                if ((mLargeArrayLength[1] > 0) && ((treeCount % mLargeArrayInter[1]) == 0)) {
+                    for (int n = 0; n < mLargeArrayNum[1]; n++)
+                        shortLiveCharArray[allocIdx[1] + n] = new char[mLargeObjectSize/2];
+                    allocIdx[1] += mLargeArrayNum[1];
+                }
+
+                if ((mLargeArrayLength[2] > 0) && ((treeCount % mLargeArrayInter[2]) == 0)) {
+                    for (int n = 0; n < mLargeArrayNum[2]; n++)
+                        shortLiveIntArray[allocIdx[2] + n] = new int[mLargeObjectSize/4];
+                    allocIdx[2] += mLargeArrayNum[2];
+                }
+
+                if ((mLargeArrayLength[3] > 0) && ((treeCount % mLargeArrayInter[3]) == 0)) {
+                    for (int n = 0; n < mLargeArrayNum[3]; n++)
+                        shortLiveLongArray[allocIdx[3] + n] = new long[mLargeObjectSize/8];
+                    allocIdx[3] += mLargeArrayNum[3];
+                }
+
+                freeArrays(shortLiveByteArray, shortLiveCharArray, shortLiveIntArray,
+                        shortLiveLongArray, allocIdx, treeCount);
+
+                treeCount++;
+            }
+
+            if (myId == 0) {
+                Debug.getMemoryInfo(memInfo);
+                mHeapFootprint[iter] = memInfo.dalvikPss;
+                if (getRuntimeStatMethod != null)
+                    mHeapBytesAllocated[iter] = (getRuntimeStat("art.gc.bytes-allocated")
+                            - getRuntimeStat("art.gc.bytes-freed")) / 1024;
+                else
+                    mHeapBytesAllocated[iter] = (Runtime.getRuntime().totalMemory()
+                            - Runtime.getRuntime().freeMemory()) / 1024;
+
+                Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkProgress);
+                m.arg1 = iter + 1;
+                mActivity.getHandler().sendMessage(m);
+            }
+        }
+
+        if (longLiveTreeLink.treeHead.treeNode != null
+                && longLiveByteArrays[0][100] == (byte)0xff
+                && longLiveByteArrays[longLiveArrayCount - 1][200] == (byte)0xff)
+            return true;
+        return false;
+    }
+
+    class BenchThread extends Thread {
+        private  int myId;
+        BenchThread (int id) {
+            super();
+            myId = id;
+        }
+        public void run() {
+            mElapseTime[myId] = 0;
+            long start = System.currentTimeMillis();
+            try {
+                if (!allocTrace(myId))
+                    Log.i(mTag, "Error in thread-" + myId);
+            } catch (OutOfMemoryError e) {
+                mOutOfMemory = true;
+                Log.i(mTag, "Thread-" + myId + " meets OutOfMemory");
+
+                Message m = mActivity.getHandler().obtainMessage(
+                        MainActivity.BenchmarkOutOfMemoryError);
+                m.arg1 = myId;
+                mActivity.getHandler().sendMessage(m);
+            }
+            mElapseTime[myId] = System.currentTimeMillis() - start;
+        }
+    }
+
+    public void start() {
+        if (getRuntimeStatMethod == null) {
+            try {
+                Class c = Class.forName("android.os.Debug");
+                getRuntimeStatMethod = c.getDeclaredMethod("getRuntimeStat", String.class);
+            } catch (ClassNotFoundException e) {
+                Log.w(mTag, "Cannot find android.os.Debug class");
+            } catch (NoSuchMethodException e) {
+                Log.w(mTag, "No getRuntimeStat method in android.os.Debug");
+            }
+        }
+        mElapseTime = new long[mThreadNum];
+        mHeapFootprint = new int[mIterNum];
+        mHeapBytesAllocated = new long[mIterNum];
+        isArt = false;
+        String vmVersion = System.getProperty("java.vm.version");
+        isArt = vmVersion != null && vmVersion.startsWith("2");
+        String androidVersion = Build.VERSION.RELEASE;
+        String deviceName = Build.MODEL;
+        String deviceDesc = deviceName + "/" + "android-" + androidVersion
+                + ", runtime: " + (isArt? "ART" :"Dalvik");
+        mTotalGcCount = getRuntimeStat("art.gc.gc-count");
+        mTotalGcTime = getRuntimeStat("art.gc.gc-time");
+        mTotalBlockingGcCount = getRuntimeStat("art.gc.blocking-gc-count");
+        mTotalBlockingGcTime = getRuntimeStat("art.gc.blocking-gc-time");
+        if (isArt)
+            mGcCauseCount = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
+        else
+            mGcCauseCount = new int[]{0, 0, 0, 0};
+
+        mWorkloadComplete = false;
+        clearLogcat();
+        Thread logcat = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                readLogcat();
+            }
+        });
+        logcat.start();
+
+        mOutOfMemory = false;
+        mTestThreads = new BenchThread[mThreadNum];
+        for (int i = 1; i < mThreadNum; i++) {
+            mTestThreads[i] = new BenchThread(i);
+            mTestThreads[i].start();
+        }
+
+        mElapseTime[0] = 0;
+        long start = System.currentTimeMillis();
+        try {
+            if (!allocTrace(0))
+                Log.i(mTag, "Error in thread-0");
+        } catch (OutOfMemoryError e) {
+            mOutOfMemory = true;
+            Log.i(mTag, "Thread-0 meets OutOfMemory");
+            Message m = mActivity.getHandler().obtainMessage(
+                    MainActivity.BenchmarkOutOfMemoryError);
+            m.arg1 = 0;
+            mActivity.getHandler().sendMessage(m);
+        }
+        mElapseTime[0] = System.currentTimeMillis() - start;
+
+        for (int i = 1; i < mThreadNum; i++) {
+            try {
+                mTestThreads[i].join();
+            } catch (InterruptedException e) {
+                Log.i(mTag, "Waiting thread " + i + " finish interrupted by "
+                        + e.getLocalizedMessage());
+            }
+        }
+        SystemClock.sleep(1000);
+        mWorkloadComplete = true;
+        Runtime.getRuntime().runFinalization();
+        Runtime.getRuntime().gc();
+        try {
+            logcat.join();
+        } catch (InterruptedException e) {
+            Log.i(mTag, "Waiting logcat finish interrupted by " + e.getLocalizedMessage());
+        }
+        if (mOutOfMemory) {
+            try {
+                if (fileOutput != null) {
+                    fileOutput.append("\nOutOfMemory! Please config proifle or "
+                            + "Java Runtime and run again!\n");
+                    fileOutput.flush();
+                    fileOutput.close();
+                }
+            } catch (IOException e) {
+                Log.i(mTag, "Cannot write to /sdcard/AndroidGCTest-result.txt"
+                        + e.getMessage());
+            }
+        } else {
+            mTotalGcCount = getRuntimeStat("art.gc.gc-count") - mTotalGcCount;
+            mTotalGcTime = getRuntimeStat("art.gc.gc-time") - mTotalGcTime;
+            mTotalBlockingGcCount = getRuntimeStat("art.gc.blocking-gc-count")
+                    - mTotalBlockingGcCount;
+            mTotalBlockingGcTime = getRuntimeStat("art.gc.blocking-gc-time")
+                    - mTotalBlockingGcTime;
+            long maxTime = 0;
+            String completionTime = "";
+            for (int i = 0; i < mThreadNum; i++) {
+                if (maxTime < mElapseTime[i])
+                    maxTime = mElapseTime[i];
+                Log.i(mTag, "Thread-" + i + " completion time: "
+                        + String.valueOf((mElapseTime[i])) + "ms");
+                completionTime += "Thread-" + i + " completion time: "
+                        + String.valueOf((mElapseTime[i])) + "ms\n";
+            }
+            String totalTime = "AndroidGCTest is done by " + mThreadNum
+                    + " threads. Completion time is " + maxTime + "ms";
+            Log.i(mTag, totalTime);
+            completionTime += totalTime + "\n";
+            String gcDesc = "Total GC count: " + mTotalGcCount;
+            gcDesc += "\nTotal GC time: " + mTotalGcTime + "ms";
+            gcDesc += "\nTotal Blocking GC count: " + mTotalBlockingGcCount;
+            gcDesc += "\nTotal Blocking GC time: " + mTotalBlockingGcTime + "ms";
+            Log.i(mTag, "Total GC count: " + mTotalGcCount);
+            Log.i(mTag, "Total GC time: " + mTotalGcTime + "ms");
+            Log.i(mTag, "Total Blocking GC count: " + mTotalBlockingGcCount);
+            Log.i(mTag, "Total Blocking GC time: " + mTotalBlockingGcTime + "ms");
+            String pauseDesc = "";
+            String[] causes;
+            if (isArt)
+                causes = GC_CAUSE_ART;
+            else
+                causes = GC_CAUSE_DALVIK;
+            for (int i = 0; i < causes.length; i++) {
+                Log.i(mTag, mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat");
+                gcDesc += "\n" + mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat";
+            }
+            for (int i = 0; i < mGcPauseTime.length; i++) {
+                String gc_time = "GC-" + i + ": " + mGcCause[i] + ", pause "
+                        + mGcPauseTime[i] + "ms, total " + mGcTotalTime[i] + "ms";
+                pauseDesc += "\n" + gc_time;
+                Log.i(mTag, gc_time);
+            }
+            try {
+                if (fileOutput != null) {
+                    fileOutput.append("\n" + "Device config:\n\t" + deviceDesc);
+                    fileOutput.append("\n" + completionTime);
+                    fileOutput.append("\n" + "Heap status after each iteration "
+                            + "(footprint, bytes allocated):\n");
+                    for (int j = 0; j < mIterNum; j++)
+                        fileOutput.append("\t" + mHeapFootprint[j] + " kB, "
+                                + mHeapBytesAllocated[j] + " kB\n");
+                    fileOutput.append(gcDesc);
+                    fileOutput.append(pauseDesc);
+                    fileOutput.flush();
+                    fileOutput.close();
+                }
+            } catch (IOException e) {
+                Log.i(mTag, "Cannot write to /sdcard/AndroidGCTest-result.txt"
+                        + e.getMessage());
+            }
+            if (mActivity != null) {
+                Message m = mActivity.getHandler().obtainMessage(
+                        MainActivity.BenchmarkDone);
+                Bundle b = new Bundle();
+                b.putBoolean(ResultActivity.KEY_VM_TYPE, isArt);
+                b.putString("device", deviceDesc);
+                b.putLongArray(ResultActivity.KEY_THREAD_COMPLETE_TIME, mElapseTime);
+                b.putLong(ResultActivity.KEY_WORKLOAD_COMPLETE_TIME, maxTime);
+                b.putLongArray(ResultActivity.KEY_BYTES_LIVING, mHeapBytesAllocated);
+                b.putIntArray(ResultActivity.KEY_HEAP_FOOTPRINT, mHeapFootprint);
+                b.putFloatArray(ResultActivity.KEY_GC_PAUSE_TIME, mGcPauseTime);
+                b.putFloatArray(ResultActivity.KEY_GC_COMPLETION_TIME, mGcTotalTime);
+                b.putStringArray(ResultActivity.KEY_GC_CAUSE, mGcCause);
+                m.setData(b);
+                mActivity.getHandler().sendMessage(m);
+            }
+        }
+        mElapseTime = null;
+        mHeapFootprint = null;
+        mHeapBytesAllocated = null;
+        mGcPauseTime = null;
+        mGcTotalTime = null;
+        mGcCause = null;
+
+        clearInitData();
+    }
+
+    public void stop() {
+    }
+
+    private void clearLogcat() {
+        try {
+            Process process = Runtime.getRuntime().exec("logcat -c");
+            try {
+                process.waitFor();
+            } catch (InterruptedException e) {
+                Log.e(mTag, "Clear logcat fails, interrupted by " + e.getLocalizedMessage());
+            }
+            Log.i(mTag, "Clear logcat before workload running");
+        } catch (Exception e) {
+            Log.e(mTag, "Clear logcat fails, " + e.getLocalizedMessage());
+        }
+    }
+
+    private void readLogcat() {
+        String cmd;
+        if (isArt)
+            cmd = "logcat -s art";
+        else
+            cmd = "logcat -s dalvikvm";
+        ArrayList<Float> gcPauseTimeList = new ArrayList<Float>();
+        ArrayList<Float> gcTotalTimeList = new ArrayList<Float>();
+        ArrayList<String> gcCauseList = new ArrayList<String>();
+        int loggerGcCount = 0;
+        try {
+            Process process = Runtime.getRuntime().exec(cmd);
+            InputStream inStream = process.getInputStream();
+            InputStream errorStream = process.getErrorStream();
+            int error = errorStream.available();
+            if (error > 0) {
+                byte[] errorMsg = new byte[error];
+                errorStream.read(errorMsg);
+                Log.i(mTag, "executing logcat return error message: " + new String(errorMsg));
+            }
+            BufferedReader inReader = new BufferedReader(new InputStreamReader(inStream));
+            String line;
+            while (!mWorkloadComplete && (line = inReader.readLine()) != null) {
+                if (mWorkloadComplete)
+                    break;
+
+                int idx = line.indexOf(": ");
+                if (idx == -1)
+                    continue;
+                line = line.substring(idx+2);
+                boolean isGCLog = false;
+                String gcCause = "";
+                if (isArt) {
+                    for (int i = 0; i < GC_CAUSE_ART.length; i++) {
+                        if ((line.contains("mark sweep") || line.contains("marksweep")
+                                || line.contains("mark compact"))
+                                && line.startsWith(GC_CAUSE_ART[i])) {
+                            isGCLog = true;
+                            mGcCauseCount[i]++;
+                            idx = line.indexOf(" GC ");
+                            if (idx > 0)
+                                gcCause = line.substring(0, idx);
+                            else {
+                                Log.i(mTag, "Error: cannot find ' GC ' from this log, " + line);
+                                continue;
+                            }
+                            break;
+                        }
+                    }
+                } else {
+                    for (int i = 0; i < GC_CAUSE_DALVIK.length; i++) {
+                        if (line.startsWith(GC_CAUSE_DALVIK[i])) {
+                            isGCLog = true;
+                            mGcCauseCount[i]++;
+                            gcCause = GC_CAUSE_DALVIK[i];
+                            break;
+                        }
+                    }
+                }
+                if (!isGCLog)
+                    continue;
+                loggerGcCount++;
+
+                int idx0 = line.indexOf("paused ");
+                int idx1 = line.indexOf(" total ");
+                if (idx0 == -1 || idx1 == -1) {
+                    Log.i(mTag, "Cannot find pause or total completion time from the GC log "
+                            + line);
+                    continue;
+                }
+
+                String pauseTimeStr = line.substring(idx0+7, idx1);
+                String totalTimeStr = line.substring(idx1+7);
+                float completeTime = 0.0f;
+                float pauseTime = 0.0f;
+                idx = totalTimeStr.indexOf("ms");
+                int timeToSec = 1000;
+                if (idx == -1) {
+                    idx = totalTimeStr.indexOf("us");
+                    timeToSec = 1000000;
+                }
+                if (idx == -1) {
+                    idx = totalTimeStr.indexOf("s");
+                    timeToSec = 1;
+                }
+                if (idx == -1) {
+                    Log.i(mTag, "Cannot identify total complete time format, " + line);
+                    continue;
+                }
+                completeTime = Float.parseFloat(totalTimeStr.substring(0, idx)) * 1000 / timeToSec;
+                String[] pauseTimes = pauseTimeStr.split("\\+\\s*|,\\s*");
+                for (int i = 0; i < pauseTimes.length; i++) {
+                    String tmp = pauseTimes[i];
+                    idx = tmp.indexOf("ms");
+                    if (idx > 0) {
+                        pauseTime += Float.parseFloat(tmp.substring(0, idx));
+                    } else {
+                        idx = tmp.indexOf("us");
+                        if (idx > 0) {
+                            pauseTime += Float.parseFloat(tmp.substring(0, idx))/1000;
+                        } else {
+                            Log.i(mTag, "Cannot identify pause time format, " + line);
+                            continue;
+                        }
+                    }
+                }
+                gcPauseTimeList.add(pauseTime);
+                gcTotalTimeList.add(completeTime);
+                gcCauseList.add(gcCause);
+            }
+            errorStream.close();
+            inReader.close();
+            process.destroy();
+            Log.i(mTag, "workload complete, stop reading logcat");
+            mGcTotalTime = new float[loggerGcCount];
+            mGcPauseTime = new float[loggerGcCount];
+            mGcCause = new String[loggerGcCount];
+            for (int i = 0; i < gcPauseTimeList.size(); i++) {
+                mGcTotalTime[i] = gcTotalTimeList.get(i).floatValue();
+                mGcPauseTime[i] = gcPauseTimeList.get(i).floatValue();
+                mGcCause[i] = gcCauseList.get(i);
+            }
+        } catch (OutOfMemoryError e) {
+            mOutOfMemory = true;
+            Log.i(mTag, "logcat thread meets OutOfMemory");
+            Message m = mActivity.getHandler().obtainMessage(
+                    MainActivity.BenchmarkOutOfMemoryError);
+            m.arg1 = -1;
+            mActivity.getHandler().sendMessage(m);
+        } catch (Exception e) {
+            Log.i(mTag, "Cannot run logcat " + e.getMessage());
+        }
+        gcPauseTimeList.clear();
+        gcPauseTimeList = null;
+        gcTotalTimeList.clear();
+        gcTotalTimeList = null;
+        gcCauseList.clear();
+        gcCauseList = null;
+        Log.i(mTag, "logcat done");
+    }
+
+    private static Method getRuntimeStatMethod = null;
+    private long getRuntimeStat(String statName) {
+        if (getRuntimeStatMethod == null) {
+            return 0;
+        }
+        String valueStr;
+        try {
+            valueStr = (String) getRuntimeStatMethod.invoke(null, statName);
+        } catch (Exception e) {
+            Log.w(mTag, "Failed to invoke getRuntimeStat");
+            return 0;
+        }
+        if (valueStr != null)
+            return Long.parseLong(valueStr);
+        return 0;
+    }
+}
+
diff --git a/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/MainActivity.java b/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/MainActivity.java
new file mode 100644 (file)
index 0000000..8cc90ca
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.gctest;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.TextView;
+
+public class MainActivity extends Activity {
+    private final String mTag = "AndroidGCTest";
+    private boolean mRunning;
+
+    private Button mStartButton;
+    private Button mProfileSettingButton;
+    private Spinner mProfileNameList;
+    private SeekBar mSeekBar;
+    private LinearLayout mWorkloadResultLayout;
+    private Button mShowResultButton;
+    private TextView mExeTimeView;
+    private TextView mRuntimeView;
+    private TextView mWorkloadStatus;
+    private Profile mProfile = null;
+    private Bundle mResultData = null;
+
+    // handler to handle BenchmarkDone message
+    final static int BenchmarkDone = 100;
+    final static int BenchmarkProgress = 101;
+    final static int BenchmarkOutOfMemoryError = 102;
+    private class MyHandler extends Handler {
+        public void handleMessage(Message m) {
+            switch(m.what) {
+                case BenchmarkDone:
+                    if (mRunning) {
+                        mRunning = false;
+                        mStartButton.setVisibility(View.VISIBLE);
+                        mProfileSettingButton.setVisibility(View.VISIBLE);
+                        mWorkloadStatus.setText(R.string.workload_status_desc);
+                        mResultData = m.getData();
+                        String device = mResultData.getString("device");
+                        long execution_time = mResultData.getLong(ResultActivity.KEY_WORKLOAD_COMPLETE_TIME);
+                        mRuntimeView.setText(device);
+                        mExeTimeView.setText(String.valueOf(execution_time));
+                        mWorkloadResultLayout.setVisibility(View.VISIBLE);
+                        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                    }
+                    break;
+                case BenchmarkProgress:
+                    if (mRunning && mSeekBar != null) {
+                        int progress = m.arg1;
+                        if (progress < mSeekBar.getMax())
+                            mSeekBar.setProgress(progress);
+                    }
+                    break;
+                case BenchmarkOutOfMemoryError:
+                    if (mRunning) {
+                        mWorkloadStatus.setText(R.string.outofmemory_desc);
+                        mRunning = false;
+                    }
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+    private MyHandler mBenchmarkHandler = null;
+    public Handler getHandler() {
+        return mBenchmarkHandler;
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        Log.i(mTag, "MainActivity onCreate");
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_main);
+        mBenchmarkHandler = new MyHandler();
+
+        mWorkloadResultLayout = (LinearLayout)findViewById(R.id.workload_result_layout);
+        mSeekBar = (SeekBar)findViewById(R.id.seek_bar);
+        mSeekBar.setVisibility(View.INVISIBLE);
+        mWorkloadResultLayout.setVisibility(View.INVISIBLE);
+        mStartButton = (Button)findViewById(R.id.button_start);
+        mStartButton.setOnClickListener(startWorkload);
+        mWorkloadStatus = (TextView)findViewById(R.id.workload_status);
+
+        mProfileSettingButton = (Button)findViewById(R.id.button_set);
+        mProfileSettingButton.setOnClickListener(settingProfile);
+        mRuntimeView = (TextView)findViewById(R.id.runtime_info);
+        mExeTimeView = (TextView)findViewById(R.id.execution_time);
+        mShowResultButton = (Button)findViewById(R.id.button_result);
+        mShowResultButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                if (mResultData != null) {
+                    Intent intent = new Intent(getApplicationContext(), ResultActivity.class);
+                    Bundle b = new Bundle(mResultData);
+                    intent.putExtra("result_data", b);
+                    startActivity(intent);
+                } else
+                    Log.e(mTag, "no result to show now");
+            }
+        });
+
+        mProfileNameList = (Spinner)findViewById(R.id.profile_list_view);
+        mProfile = Profile.getInstance();
+        Bundle b = getIntent().getExtras();
+        if (b != null && b.containsKey("profile_file")) {
+            FileInputStream profileFile;
+            try {
+                profileFile = new FileInputStream(b.getString("profile_file"));
+                mProfile.parseProfileData(profileFile);
+            } catch (FileNotFoundException e) {
+                e.printStackTrace();
+                Log.i(mTag, "Cannot load profile. " + e.getMessage());
+            }
+        } else {
+            mProfile.parseProfileData(getResources().openRawResource(R.raw.profile));
+        }
+
+        if (mProfile.initialized()) {
+            String[] names = new String[mProfile.mData.size()];
+            for (int i = 0; i < mProfile.mData.size(); i++) {
+                Profile.ProfileData d = mProfile.mData.get(i);
+                names[i] = d.getName();
+            }
+            ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+                    android.R.layout.simple_spinner_item, names);
+            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+            mProfileNameList.setAdapter(adapter);
+            mProfileNameList.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+                @Override
+                public void onItemSelected(AdapterView<?> arg0, View arg1,
+                                           int arg2, long arg3) {
+                    String name = (String)(arg0.getAdapter().getItem(arg2));
+                    mProfile.setCurrentProfileData(name);
+                }
+
+                @Override
+                public void onNothingSelected(AdapterView<?> arg0) {
+                    // TODO Auto-generated method stub
+                }
+
+            });
+            mProfileNameList.setVisibility(View.VISIBLE);
+            if (b != null && b.containsKey("profile_name")) {
+                int pos = adapter.getPosition(b.getString("profile_name"));
+                mProfileNameList.setSelection(pos);
+            }
+        } else {
+            mProfileNameList.setVisibility(View.INVISIBLE);
+            Log.i(mTag, "Cannot get profile data");
+        }
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+    }
+
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
+            android.os.Process.killProcess(android.os.Process.myPid());
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+
+    @Override
+    protected void onResume() {
+        if (mRunning) {
+            if (mStartButton != null)
+                mStartButton.setVisibility(View.INVISIBLE);
+        }
+        super.onResume();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Inflate the menu; this adds items to the action bar if it is present.
+        getMenuInflater().inflate(R.menu.main, menu);
+        return true;
+    }
+
+    private View.OnClickListener startWorkload = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            // TODO Auto-generated method stub
+            Log.i(mTag, "Start Benchmark");
+            Profile.ProfileData profileData = mProfile.getCurrentProfileData();
+            if (profileData == null) {
+                Log.e(mTag, "no profile data?!");
+                return;
+            }
+            final AndroidGCTestMain benchMain = new AndroidGCTestMain((MainActivity)(v.getContext()),
+                    profileData.getTotalSize(), profileData.getBucketSize(),
+                    profileData.getLosThreshold(), profileData.getSizeDistribution(),
+                    profileData.getLifetime(), profileData.getLosElementDist(),
+                    profileData.getThreadMode(), profileData.getThreadNum(),
+                    profileData.getIterationNum());
+
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+            mResultData = null;
+            Runtime.getRuntime().runFinalization();
+            Runtime.getRuntime().gc();
+
+            mWorkloadResultLayout.setVisibility(View.INVISIBLE);
+            mProfileSettingButton.setVisibility(View.INVISIBLE);
+            v.setVisibility(View.INVISIBLE);
+            mWorkloadStatus.setText("AndroidGCTest is running");
+            mSeekBar.setVisibility(View.VISIBLE);
+            mSeekBar.setMax(profileData.getIterationNum());
+            mSeekBar.setProgress(0);
+
+            mRunning = true;
+            Thread worker = new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    // TODO Auto-generated method stub
+                    benchMain.start();
+                }
+
+            });
+            worker.start();
+        }
+    };
+
+    private View.OnClickListener settingProfile = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            // TODO Auto-generated method stub
+            Intent intent = new Intent(getApplicationContext(), ProfileSettingActivity.class);
+            startActivity(intent);
+        }
+    };
+}
diff --git a/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/Profile.java b/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/Profile.java
new file mode 100644 (file)
index 0000000..0d5e37a
--- /dev/null
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.gctest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.util.Log;
+import android.util.Xml;
+
+public class Profile {
+    private final String mTag = "AndroidGCTest";
+    public class ProfileData {
+        private int mId;
+        private String mName;
+        private int mTotalSize;
+        private int mBucketSize;
+        private int mLosThreshold;
+        private float[] mSizeDist;
+        private float[] mLosElementDist;
+        private float[][] mLifetime;
+        private boolean mThreadMode;
+        private int mThreadNum;
+        private int mIterationNum;
+
+        public ProfileData(int id, String name) {
+            mId = id;
+            mName = name;
+        }
+        public String getName() { return mName; }
+        public int getTotalSize() { return mTotalSize; }
+        public int getBucketSize() { return mBucketSize; }
+        public int getLosThreshold() { return mLosThreshold; }
+        public float[] getSizeDistribution() { return mSizeDist; }
+        public float[] getLosElementDist() { return mLosElementDist; }
+        public float[][] getLifetime() { return mLifetime; }
+        public boolean getThreadMode() { return mThreadMode; }
+        public int getThreadNum() { return mThreadMode? 1 : mThreadNum; }
+        public int getIterationNum() { return mIterationNum; }
+
+        public void setName(String name) { mName = name; }
+        public void setTotalSize(int total_size) { mTotalSize = total_size; }
+        public void setBucketSize(int bucket_size) { mBucketSize = bucket_size; }
+        public void setLosThreshold(int los_threshold) { mLosThreshold = los_threshold; }
+        public void setSizeDistribution(float[] size_dist) { mSizeDist = size_dist; }
+        public void setLosElementDist(float[] los_element_dist) {
+            mLosElementDist = los_element_dist;
+        }
+        public void setLifetime(float[][] lifetime) { mLifetime = lifetime; }
+        public void setThreadMode(boolean singleThread) { mThreadMode = singleThread; }
+        public void setThreadNum(int thread_num) {
+            mThreadNum = mThreadMode? 1 : thread_num;
+        }
+        public void setIterationNum(int iteration_num) { mIterationNum = iteration_num; }
+    }
+
+    public boolean mInit = false;
+    int mCurrentProfileId;
+    public ArrayList<ProfileData> mData = null;
+
+    private static Profile instance_;
+    private Profile() {
+        mCurrentProfileId = -1;
+        mInit = false;
+    }
+    public static Profile getInstance() {
+        if (instance_ == null)
+            instance_ = new Profile();
+        return instance_;
+    }
+
+    private boolean initProfileData(InputStream input) {
+        ProfileData newProfile = null;
+        XmlPullParser parser=Xml.newPullParser();
+        try {
+            parser.setInput(new InputStreamReader(input));
+            int eventType = parser.getEventType();
+            float[] floatValues = null;
+            String itemName, name;
+            int idx0 = -1, idx1 = 0;
+            while (eventType != XmlPullParser.END_DOCUMENT) {
+                switch(eventType) {
+                    case XmlPullParser.START_DOCUMENT:
+                        mData = new ArrayList<ProfileData>();
+                        break;
+                    case XmlPullParser.START_TAG:
+                        name = parser.getName();
+                        if (name.matches("profile")) {
+                            newProfile = new ProfileData(
+                                    Integer.parseInt(parser.getAttributeValue(0)),
+                                    parser.getAttributeValue(1));
+                        } else if (name.matches("item")) {
+                            itemName = parser.getAttributeValue(0);
+                            if (itemName.matches("total_size")) {
+                                newProfile.mTotalSize = Integer.parseInt(parser.nextText());
+                            } else if (itemName.matches("bucket_size")) {
+                                newProfile.mBucketSize = Integer.parseInt(parser.nextText());
+                            } else if (itemName.matches("los_threshold")) {
+                                newProfile.mLosThreshold = Integer.parseInt(parser.nextText());
+                            } else if (itemName.matches("thread-mode")) {
+                                newProfile.mThreadMode = Integer.parseInt(parser.nextText()) == 1;
+                            } else if (itemName.matches("thread-num")) {
+                                newProfile.mThreadNum = Integer.parseInt(parser.nextText());
+                            } else if (itemName.matches("iteration-times")) {
+                                newProfile.mIterationNum = Integer.parseInt(parser.nextText());
+                            }
+                        } else if (name.matches("float-array-2d")) {
+                            if ("lifetime".equals(parser.getAttributeValue(0))) {
+                                newProfile.mLifetime = new float[Integer.parseInt(
+                                        parser.getAttributeValue(1))][];
+                                idx0 = 0;
+                            }
+                        } else if(name.matches("float-array")) {
+                            itemName = parser.getAttributeValue(0);
+                            if (itemName.matches("size_dist")) {
+                                newProfile.mSizeDist = new float[Integer.parseInt(
+                                        parser.getAttributeValue(1))];
+                                floatValues = newProfile.mSizeDist;
+                            } else if (itemName.matches("los_element_dist")) {
+                                newProfile.mLosElementDist = new float[Integer.parseInt(
+                                        parser.getAttributeValue(1))];
+                                floatValues = newProfile.mLosElementDist;
+                            } else if (idx0 >= 0) {
+                                newProfile.mLifetime[idx0] = new float[Integer.parseInt(
+                                        parser.getAttributeValue(1))];
+                                floatValues = newProfile.mLifetime[idx0];
+                                idx0++;
+                            }
+                            idx1 = 0;
+                        } else if(name.matches("value")) {
+                            if (floatValues == null) {
+                                Log.i(mTag, "error in parsing profile.xml");
+                                return false;
+                            }
+                            floatValues[idx1++] = Float.parseFloat(parser.nextText());
+                        }
+                        break;
+                    case XmlPullParser.END_TAG:
+                        name = parser.getName();
+                        if ("profile".equals(name))
+                            mData.add(newProfile);
+                        else if ("float-array-2d".equals(name))
+                            idx0 = -1;
+                        break;
+                    default:
+                        break;
+                }
+                eventType = parser.next();
+            }
+        } catch (XmlPullParserException e) {
+            e.printStackTrace();
+            return false;
+        } catch (NumberFormatException e) {
+            e.printStackTrace();
+            return false;
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+
+    public ProfileData getProfile(String name) {
+        if (!mInit)
+            return null;
+        for (int i = 0; i < mData.size(); i++) {
+            ProfileData data = mData.get(i);
+            if (data.mName.matches(name)) {
+                mCurrentProfileId = data.mId;
+                return data;
+            }
+        }
+        return null;
+    }
+
+    public boolean parseProfileData(InputStream rawProfileFile) {
+        mInit = initProfileData(rawProfileFile);
+        return mInit;
+    }
+
+    public boolean initialized() {
+        return mInit;
+    }
+
+    public void setCurrentProfileData(String name) {
+        if (!mInit)
+            return;
+        for (int i = 0; i < mData.size(); i++) {
+            ProfileData data = mData.get(i);
+            if (data.mName.matches(name)) {
+                mCurrentProfileId = data.mId;
+                break;
+            }
+        }
+    }
+
+    public ProfileData getCurrentProfileData() {
+        if (!mInit)
+            return null;
+        for (int i = 0; i < mData.size(); i++)
+            if (mData.get(i).mId == mCurrentProfileId)
+                return mData.get(i);
+        return null;
+    }
+}
diff --git a/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/ProfileSettingActivity.java b/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/ProfileSettingActivity.java
new file mode 100644 (file)
index 0000000..eea6e55
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.gctest;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+
+public class ProfileSettingActivity extends Activity {
+    private final String mTag = "AndroidGCTest";
+    private Button mConfirmButton = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_profile_config);
+        mConfirmButton = (Button)findViewById(R.id.button_confirm);
+        mConfirmButton.setOnClickListener(settingProfile);
+        Profile profile = Profile.getInstance();
+        showProfileData(profile.getCurrentProfileData());
+    }
+    private View.OnClickListener settingProfile = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            // TODO Auto-generated method stub
+            int heapSize, bucketSize, largeObjectSize;
+            float[] sizeDist = null;
+            float[][] lifetimeDist = null;
+            float[] largeSizeDist = null;
+            boolean singleThread = false;
+            int thread_num = 0, exe_time = 1;
+            heapSize = Integer.parseInt(((EditText)findViewById(
+                    R.id.total_size_v)).getText().toString());
+            bucketSize = Integer.parseInt(((EditText)findViewById(
+                    R.id.bucket_size_v)).getText().toString());
+            largeObjectSize = Integer.parseInt(((EditText)findViewById(
+                    R.id.los_threshold_v)).getText().toString());
+            exe_time = Integer.parseInt(((EditText)findViewById(
+                    R.id.exe_time_v)).getText().toString());
+            thread_num = Integer.parseInt(((EditText)findViewById(
+                    R.id.thread_num)).getText().toString());
+
+            sizeDist = new float[AndroidGCTestMain.OBJECT_SIZE_TYPE];
+            sizeDist[0] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_16_v)).getText().toString());
+            sizeDist[1] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_32_v)).getText().toString());
+            sizeDist[2] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_64_v)).getText().toString());
+            sizeDist[3] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_128_v)).getText().toString());
+            sizeDist[4] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_256_v)).getText().toString());
+            sizeDist[5] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_512_v)).getText().toString());
+            sizeDist[6] = Float.parseFloat(((EditText)findViewById(
+                    R.id.size_dist_los_v)).getText().toString());
+
+            String[][] lifetimeStr = new String[AndroidGCTestMain.OBJECT_SIZE_TYPE][];
+            lifetimeDist = new float[AndroidGCTestMain.OBJECT_SIZE_TYPE][];
+            lifetimeStr[AndroidGCTestMain.OBJECT_16_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_16_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            lifetimeStr[AndroidGCTestMain.OBJECT_32_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_32_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            lifetimeStr[AndroidGCTestMain.OBJECT_64_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_64_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            lifetimeStr[AndroidGCTestMain.OBJECT_128_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_128_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            lifetimeStr[AndroidGCTestMain.OBJECT_256_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_256_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            lifetimeStr[AndroidGCTestMain.OBJECT_512_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_512_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            lifetimeStr[AndroidGCTestMain.OBJECT_LARGE_BYTE] = ((EditText)findViewById(
+                    R.id.lifetime_los_v))
+                    .getText().toString().replaceAll(", ", ",").split(",");
+            for (int i = 0; i < AndroidGCTestMain.OBJECT_SIZE_TYPE; i++) {
+                int len = lifetimeStr[i].length;
+                lifetimeDist[i] = new float[len];
+                for (int j = 0; j < len; j++) {
+                    lifetimeDist[i][j] = Float.parseFloat(lifetimeStr[i][j]);
+                }
+            }
+
+            largeSizeDist = new float[4];
+            largeSizeDist[0] = Float.parseFloat(((EditText)findViewById(
+                    R.id.los_dist_byte_v))
+                    .getText().toString());
+            largeSizeDist[1] = Float.parseFloat(((EditText)findViewById(
+                    R.id.los_dist_char_v))
+                    .getText().toString());
+            largeSizeDist[2] = Float.parseFloat(((EditText)findViewById(
+                    R.id.los_dist_int_v))
+                    .getText().toString());
+            largeSizeDist[3] = Float.parseFloat(((EditText)findViewById(
+                    R.id.los_dist_long_v))
+                    .getText().toString());
+
+            singleThread = ((CheckBox)findViewById(R.id.single_thread)).isChecked();
+            Profile profile = Profile.getInstance();
+            Profile.ProfileData profileData = profile.getCurrentProfileData();
+            profileData.setTotalSize(heapSize);
+            profileData.setBucketSize(bucketSize);
+            profileData.setLosThreshold(largeObjectSize);
+            profileData.setSizeDistribution(sizeDist);
+            profileData.setLifetime(lifetimeDist);
+            profileData.setLosElementDist(largeSizeDist);
+            profileData.setThreadMode(singleThread);
+            profileData.setThreadNum(thread_num);
+            profileData.setIterationNum(exe_time);
+            Intent intent = new Intent(getApplicationContext(), MainActivity.class);
+            intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
+            startActivity(intent);
+        }
+    };
+
+    private void showProfileData(Profile.ProfileData data) {
+        ((EditText)findViewById(R.id.total_size_v))
+                .setText(String.valueOf(data.getTotalSize()));
+        ((EditText)findViewById(R.id.bucket_size_v))
+                .setText(String.valueOf(data.getBucketSize()));
+        ((EditText)findViewById(R.id.los_threshold_v))
+                .setText(String.valueOf(data.getLosThreshold()));
+
+        int i = 0;
+        float[] size_dist = data.getSizeDistribution();
+        ((EditText)findViewById(R.id.size_dist_16_v)).setText(String.valueOf(size_dist[i++]));
+        ((EditText)findViewById(R.id.size_dist_32_v)).setText(String.valueOf(size_dist[i++]));
+        ((EditText)findViewById(R.id.size_dist_64_v)).setText(String.valueOf(size_dist[i++]));
+        ((EditText)findViewById(R.id.size_dist_128_v)).setText(String.valueOf(size_dist[i++]));
+        ((EditText)findViewById(R.id.size_dist_256_v)).setText(String.valueOf(size_dist[i++]));
+        ((EditText)findViewById(R.id.size_dist_512_v)).setText(String.valueOf(size_dist[i++]));
+        ((EditText)findViewById(R.id.size_dist_los_v)).setText(String.valueOf(size_dist[i++]));
+
+        i = 0;
+        float[] los_element_dist = data.getLosElementDist();
+        ((EditText)findViewById(R.id.los_dist_byte_v))
+                .setText(String.valueOf(los_element_dist[i++]));
+        ((EditText)findViewById(R.id.los_dist_char_v))
+                .setText(String.valueOf(los_element_dist[i++]));
+        ((EditText)findViewById(R.id.los_dist_int_v))
+                .setText(String.valueOf(los_element_dist[i++]));
+        ((EditText)findViewById(R.id.los_dist_long_v))
+                .setText(String.valueOf(los_element_dist[i++]));
+
+        String[] t = new String[]{"", "", "", "", "", "", ""};
+        float[][] lifetime = data.getLifetime();
+        for (i = 0; i < AndroidGCTestMain.OBJECT_SIZE_TYPE; i++) {
+            for (int j = 0; j < lifetime[i].length; j++) {
+                if (j != 0)
+                    t[i] += ",";
+                t[i] += String.valueOf(lifetime[i][j]);
+            }
+        }
+        i = 0;
+        ((EditText)findViewById(R.id.lifetime_16_v)).setText(t[i++]);
+        ((EditText)findViewById(R.id.lifetime_32_v)).setText(t[i++]);
+        ((EditText)findViewById(R.id.lifetime_64_v)).setText(t[i++]);
+        ((EditText)findViewById(R.id.lifetime_128_v)).setText(t[i++]);
+        ((EditText)findViewById(R.id.lifetime_256_v)).setText(t[i++]);
+        ((EditText)findViewById(R.id.lifetime_512_v)).setText(t[i++]);
+        ((EditText)findViewById(R.id.lifetime_los_v)).setText(t[i++]);
+
+        ((CheckBox)findViewById(R.id.single_thread)).setChecked(data.getThreadMode());
+
+        EditText thread_num_view = (EditText)findViewById(R.id.thread_num);
+        thread_num_view.setText(String.valueOf(data.getThreadNum()));
+        ((EditText)findViewById(R.id.exe_time_v))
+                .setText(String.valueOf(data.getIterationNum()));
+    }
+}
diff --git a/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/ResultActivity.java b/tests/GC/AndroidGCTest/app/src/main/java/com/android/gctest/ResultActivity.java
new file mode 100644 (file)
index 0000000..19f9bc1
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * 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 com.android.gctest;
+
+import org.achartengine.ChartFactory;
+import org.achartengine.GraphicalView;
+import org.achartengine.chart.PointStyle;
+import org.achartengine.model.XYMultipleSeriesDataset;
+import org.achartengine.model.XYSeries;
+import org.achartengine.renderer.XYMultipleSeriesRenderer;
+import org.achartengine.renderer.XYSeriesRenderer;
+
+import android.util.Log;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.LinearLayout.LayoutParams;
+
+public class ResultActivity extends Activity {
+    private final String mTag = "AndroidGCTest";
+    private long[] mThreadExeTime = null;
+    private long mWorkloadExeTime = 0;
+    private int[] mHeapFootprint = null;
+    private long[] mHeapBytesAllocated = null;
+    private float[] mGcPauseTime = null;
+    private float[] mGcTotalTime = null;
+    private String[] mGcCause = null;
+    private boolean mVmType; // true for ART, false for Dalvik
+
+    public static final String KEY_WORKLOAD_COMPLETE_TIME = "workload_completion_time";
+    public static final String KEY_THREAD_COMPLETE_TIME = "thread_completion_time";
+    public static final String KEY_VM_TYPE = "vm_type";
+    public static final String KEY_HEAP_FOOTPRINT = "heap_footprint";
+    public static final String KEY_BYTES_LIVING = "bytes_living";
+    public static final String KEY_GC_PAUSE_TIME = "gc_pause_time";
+    public static final String KEY_GC_COMPLETION_TIME = "gc_completion_time";
+    public static final String KEY_GC_CAUSE = "gc_cause";
+
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_result);
+
+        Bundle b = getIntent().getBundleExtra("result_data");
+        if (b == null) {
+            Log.i(mTag, "no result_data bundle!");
+        }
+
+        if (b.containsKey(KEY_VM_TYPE)) {
+            mVmType = b.getBoolean(KEY_VM_TYPE);
+        } else {
+            Log.i(mTag, "no " + KEY_VM_TYPE);
+        }
+
+        if (b.containsKey(KEY_WORKLOAD_COMPLETE_TIME)) {
+            mWorkloadExeTime = b.getLong(KEY_WORKLOAD_COMPLETE_TIME);
+            if (mWorkloadExeTime == 0) {
+                Log.i(mTag, "cannot read " + KEY_WORKLOAD_COMPLETE_TIME);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_WORKLOAD_COMPLETE_TIME);
+        }
+
+        if (b.containsKey(KEY_THREAD_COMPLETE_TIME)) {
+            mThreadExeTime = b.getLongArray(KEY_THREAD_COMPLETE_TIME);
+            if (mThreadExeTime == null) {
+                Log.i(mTag, "cannot read " + KEY_THREAD_COMPLETE_TIME);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_THREAD_COMPLETE_TIME);
+        }
+
+        if (b.containsKey(KEY_HEAP_FOOTPRINT)) {
+            mHeapFootprint = b.getIntArray(KEY_HEAP_FOOTPRINT);
+            if (mHeapFootprint == null) {
+                Log.i(mTag, "cannot read " + KEY_HEAP_FOOTPRINT);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_HEAP_FOOTPRINT);
+        }
+
+        if (b.containsKey(KEY_BYTES_LIVING)) {
+            mHeapBytesAllocated = b.getLongArray(KEY_BYTES_LIVING);
+            if (mHeapBytesAllocated == null) {
+                Log.i(mTag, "cannot read " + KEY_BYTES_LIVING);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_BYTES_LIVING);
+        }
+
+        if (b.containsKey(KEY_GC_PAUSE_TIME)) {
+            mGcPauseTime = b.getFloatArray(KEY_GC_PAUSE_TIME);
+            if (mGcPauseTime == null) {
+                Log.i(mTag, "cannot read " + KEY_GC_PAUSE_TIME);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_GC_PAUSE_TIME);
+        }
+
+        if (b.containsKey(KEY_GC_COMPLETION_TIME)) {
+            mGcTotalTime = b.getFloatArray(KEY_GC_COMPLETION_TIME);
+            if (mGcTotalTime == null) {
+                Log.i(mTag, "cannot read " + KEY_GC_COMPLETION_TIME);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_GC_COMPLETION_TIME);
+        }
+
+        if (b.containsKey(KEY_GC_CAUSE)) {
+            mGcCause = b.getStringArray(KEY_GC_CAUSE);
+            if (mGcCause == null) {
+                Log.i(mTag, "cannot read " + KEY_GC_CAUSE);
+            }
+        } else {
+            Log.i(mTag, "no " + KEY_GC_CAUSE);
+        }
+
+        TextView vm_type = (TextView)findViewById(R.id.vm_type);
+        vm_type.setText("Current runtime engine is " + (mVmType? "ART" : "Dalvik")
+                + ", workload completes in " + mWorkloadExeTime + " ms");
+        Button exeTimeButton = (Button)findViewById(R.id.button_exe_time);
+        exeTimeButton.setClickable(true);
+        exeTimeButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                mCurrentDataset.clear();
+                mCurrentRenderer.removeAllRenderers();
+                buildExeTimeInfoChart();
+                mChartView.repaint();
+            }
+        });
+
+        Button heapButton = (Button)findViewById(R.id.button_heap);
+        heapButton.setClickable(true);
+        heapButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                mCurrentDataset.clear();
+                mCurrentRenderer.removeAllRenderers();
+                buildHeapInfoChart();
+                mChartView.repaint();
+            }
+        });
+
+        Button gcButton = (Button)findViewById(R.id.button_gc);
+        gcButton.setClickable(true);
+        gcButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // TODO Auto-generated method stub
+                mCurrentDataset.clear();
+                mCurrentRenderer.removeAllRenderers();
+                buildGcInfoChart();
+                mChartView.repaint();
+            }
+        });
+        mCurrentRenderer.setApplyBackgroundColor(true);
+        mCurrentRenderer.setBackgroundColor(Color.argb(100, 50, 50, 50));
+        mCurrentRenderer.setAxisTitleTextSize(16);
+        mCurrentRenderer.setChartTitleTextSize(20);
+        mCurrentRenderer.setLabelsTextSize(15);
+        mCurrentRenderer.setLegendTextSize(15);
+        mCurrentRenderer.setMargins(new int[] { 20, 30, 15, 0 });
+        mCurrentRenderer.setZoomButtonsVisible(true);
+        mCurrentRenderer.setPointSize(5);
+    }
+    private XYMultipleSeriesDataset mCurrentDataset = new XYMultipleSeriesDataset();
+    private XYMultipleSeriesRenderer mCurrentRenderer = new XYMultipleSeriesRenderer();
+
+    private GraphicalView mChartView;
+    private void buildExeTimeInfoChart() {
+        Log.i(mTag, "buildExeTimeInfoChart");
+        // workload execution time
+        XYSeries series = new XYSeries("Workload Execution Time");
+        for (int i = 0; i < mThreadExeTime.length; i++) {
+            series.add(i, mThreadExeTime[i]);
+        }
+        mCurrentDataset.addSeries(series);
+        XYSeriesRenderer renderer = new XYSeriesRenderer();
+        // set some renderer properties
+        renderer.setPointStyle(PointStyle.CIRCLE);
+        renderer.setFillPoints(true);
+        renderer.setDisplayChartValues(true);
+        renderer.setDisplayChartValuesDistance(10);
+        renderer.setLineWidth(2.0f);
+        mCurrentRenderer.addSeriesRenderer(renderer);
+        mCurrentRenderer.setChartTitle("Workload Execution Time (ms)");
+        mCurrentRenderer.setYAxisMin(0);
+        mCurrentRenderer.setYAxisMax(mWorkloadExeTime*1.05);
+        mCurrentRenderer.setXAxisMin(0);
+        mCurrentRenderer.setXAxisMax(mThreadExeTime.length);
+    }
+
+    private void buildHeapInfoChart() {
+        Log.i(mTag, "buildHeapInfoChart");
+        // Heap footprint and bytes_allocated
+        double max = 0d;
+        XYSeries series2 = new XYSeries("Heap Footprint");
+        XYSeries series3 = new XYSeries("Bytes Allocated");
+        for (int i = 0; i < mHeapFootprint.length; i++) {
+            series2.add(i, mHeapFootprint[i]);
+            series3.add(i, mHeapBytesAllocated[i]);
+            if (max < mHeapFootprint[i])
+                max = mHeapFootprint[i];
+            if (max < mHeapBytesAllocated[i])
+                max = mHeapBytesAllocated[i];
+        }
+        mCurrentDataset.addSeries(series2);
+        mCurrentDataset.addSeries(series3);
+        XYSeriesRenderer renderer = new XYSeriesRenderer();
+        // set some renderer properties
+        renderer.setPointStyle(PointStyle.CIRCLE);
+        renderer.setFillPoints(true);
+        renderer.setDisplayChartValues(false);
+        renderer.setDisplayChartValuesDistance(10);
+        renderer.setColor(Color.RED);
+        renderer.setLineWidth(1.0f);
+        mCurrentRenderer.addSeriesRenderer(renderer);
+        renderer = new XYSeriesRenderer();
+        // set some renderer properties
+        renderer.setPointStyle(PointStyle.CIRCLE);
+        renderer.setFillPoints(true);
+        renderer.setDisplayChartValues(false);
+        renderer.setDisplayChartValuesDistance(10);
+        renderer.setColor(Color.BLUE);
+        renderer.setLineWidth(1.0f);
+        mCurrentRenderer.addSeriesRenderer(renderer);
+        mCurrentRenderer.setChartTitle("Heap Footprint/Bytes allocated (kB)");
+        mCurrentRenderer.setYAxisMin(0);
+        mCurrentRenderer.setYAxisMax(max*1.05);
+        mCurrentRenderer.setXAxisMin(0);
+        mCurrentRenderer.setXAxisMax(mHeapFootprint.length);
+    }
+
+    private void buildGcInfoChart() {
+        Log.i(mTag, "buildGcInfoChart");
+        // GC status
+        XYSeries series3 = new XYSeries("GC pause time");
+        double max = 0d;
+        for (int i = 0; i < mGcPauseTime.length; i++) {
+            series3.add(i, mGcPauseTime[i]);
+            if (max < mGcPauseTime[i])
+                max = mGcPauseTime[i];
+        }
+        mCurrentDataset.addSeries(series3);
+        XYSeriesRenderer renderer = new XYSeriesRenderer();
+        // set some renderer properties
+        renderer.setPointStyle(PointStyle.CIRCLE);
+        renderer.setFillPoints(true);
+        renderer.setDisplayChartValues(false);
+        renderer.setDisplayChartValuesDistance(10);
+        renderer.setColor(Color.BLUE);
+        renderer.setLineWidth(1.5f);
+        mCurrentRenderer.addSeriesRenderer(renderer);
+        mCurrentRenderer.setChartTitle("Gc Pause Time (ms)");
+        mCurrentRenderer.setYAxisMin(0);
+        mCurrentRenderer.setYAxisMax(max*1.05);
+        mCurrentRenderer.setXAxisMin(0);
+        mCurrentRenderer.setXAxisMax(mGcPauseTime.length);
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if (mChartView == null) {
+            buildExeTimeInfoChart();
+            LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
+            mChartView = ChartFactory.getLineChartView(this,
+                    mCurrentDataset, mCurrentRenderer);
+            layout.addView(mChartView, new LayoutParams(LayoutParams.WRAP_CONTENT,
+                    LayoutParams.WRAP_CONTENT));
+        } else {
+            mChartView.repaint();
+        }
+    }
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            mCurrentDataset = null;
+            mCurrentRenderer = null;
+            mThreadExeTime = null;
+            mWorkloadExeTime = 0;
+            mHeapFootprint = null;
+            mHeapBytesAllocated = null;
+            mGcPauseTime = null;
+            mGcTotalTime = null;
+            mGcCause = null;
+            Runtime.getRuntime().runFinalization();
+            Runtime.getRuntime().gc();
+        }
+        return super.onKeyUp(keyCode, event);
+    }
+}
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/drawable/ic_launcher_background.xml b/tests/GC/AndroidGCTest/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644 (file)
index 0000000..07d5da9
--- /dev/null
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path
+        android:fillColor="#3DDC84"
+        android:pathData="M0,0h108v108h-108z" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M9,0L9,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,0L19,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,0L29,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,0L39,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,0L49,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,0L59,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,0L69,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,0L79,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M89,0L89,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M99,0L99,108"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,9L108,9"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,19L108,19"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,29L108,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,39L108,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,49L108,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,59L108,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,69L108,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,79L108,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,89L108,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M0,99L108,99"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,29L89,29"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,39L89,39"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,49L89,49"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,59L89,59"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,69L89,69"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M19,79L89,79"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M29,19L29,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M39,19L39,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M49,19L49,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M59,19L59,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M69,19L69,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+    <path
+        android:fillColor="#00000000"
+        android:pathData="M79,19L79,89"
+        android:strokeWidth="0.8"
+        android:strokeColor="#33FFFFFF" />
+</vector>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/drawable/ic_launcher_foreground.xml b/tests/GC/AndroidGCTest/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644 (file)
index 0000000..2b068d1
--- /dev/null
@@ -0,0 +1,30 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:aapt="http://schemas.android.com/aapt"
+    android:width="108dp"
+    android:height="108dp"
+    android:viewportWidth="108"
+    android:viewportHeight="108">
+    <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
+        <aapt:attr name="android:fillColor">
+            <gradient
+                android:endX="85.84757"
+                android:endY="92.4963"
+                android:startX="42.9492"
+                android:startY="49.59793"
+                android:type="linear">
+                <item
+                    android:color="#44000000"
+                    android:offset="0.0" />
+                <item
+                    android:color="#00000000"
+                    android:offset="1.0" />
+            </gradient>
+        </aapt:attr>
+    </path>
+    <path
+        android:fillColor="#FFFFFF"
+        android:fillType="nonZero"
+        android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
+</vector>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/layout/activity_main.xml b/tests/GC/AndroidGCTest/app/src/main/res/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..1776e8f
--- /dev/null
@@ -0,0 +1,129 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/activity_main"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context=".MainActivity" >
+
+    <SeekBar
+        android:id="@+id/seek_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerInParent="true" />
+
+    <LinearLayout
+        android:id="@+id/workload_setting_layout"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:baselineAligned="false"
+        android:orientation="horizontal"
+        android:layout_above="@id/seek_bar" >
+
+        <LinearLayout
+            android:layout_width="200dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:orientation="vertical" >
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginTop="10dp"
+                android:textSize="18sp"
+                android:text="@string/profile_list_dest" />
+            <Spinner
+                android:id="@+id/profile_list_view"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="center_horizontal"
+                android:layout_marginLeft="20dp" />
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:orientation="vertical" >
+            <Button
+                android:id="@+id/button_set"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:text="@string/set_profile_button_desc" />
+
+            <Button
+                android:id="@+id/button_start"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:text="@string/start_button_desc" />
+
+            <TextView
+                android:id="@+id/workload_status"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_horizontal"
+                android:textSize="20sp"
+                android:text="@string/workload_status_desc" />
+        </LinearLayout>
+    </LinearLayout>
+
+
+    <LinearLayout
+        android:id="@+id/workload_result_layout"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/seek_bar"
+        android:layout_centerHorizontal="true"
+        android:orientation="vertical" >
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:text="@string/runtime_desc"
+                android:textSize="20sp" />
+
+            <TextView
+                android:id="@+id/runtime_info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textSize="20sp" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:text="@string/execution_time_desc"
+                android:textSize="20sp" />
+
+            <TextView
+                android:id="@+id/execution_time"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="@color/result_color"
+                android:textSize="24sp" />
+
+        </LinearLayout>
+
+        <Button
+            android:id="@+id/button_result"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/show_result_button_desc" />
+
+    </LinearLayout>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/layout/activity_profile_config.xml b/tests/GC/AndroidGCTest/app/src/main/res/layout/activity_profile_config.xml
new file mode 100644 (file)
index 0000000..66f42f4
--- /dev/null
@@ -0,0 +1,491 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/activity_profile_config"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context=".ProfileSettingActivity" >
+
+    <Button
+        android:id="@+id/button_confirm"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_centerHorizontal="true"
+        android:text="@string/setting_confirm_button_desc" />
+
+    <ScrollView
+        android:id="@+id/scrollView1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/button_confirm" >
+
+        <LinearLayout
+            android:id="@+id/config_table"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:layoutMode="clipBounds"
+            android:orientation="vertical" >
+
+
+            <TableLayout
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:shrinkColumns="0" >
+
+                <TableRow
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" >
+
+                    <TextView
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:singleLine="true"
+                        android:text="@string/total_size_desc" />
+
+                    <EditText
+                        android:id="@+id/total_size_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="left"
+                        android:inputType="number"
+                        android:text="@string/total_size_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" >
+
+                    <TextView
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:singleLine="true"
+                        android:text="@string/bucket_size_desc" />
+
+                    <EditText
+                        android:id="@+id/bucket_size_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="left"
+                        android:inputType="number"
+                        android:text="@string/bucket_size_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content" >
+
+                    <TextView
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:singleLine="true"
+                        android:text="@string/los_threshold_desc" />
+
+                    <EditText
+                        android:id="@+id/los_threshold_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="left"
+                        android:inputType="number"
+                        android:text="@string/los_threshold_default" />
+                </TableRow>
+
+            </TableLayout>
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:gravity="left"
+                android:singleLine="true"
+                android:text="@string/object_size_dist_desc" />
+
+            <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <TextView
+                    android:id="@+id/size_desc_16"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentLeft="true"
+                    android:layout_alignParentTop="true"
+                    android:gravity="center"
+                    android:text="@string/object_size_16_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_16_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_16"
+                    android:layout_below="@id/size_desc_16"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_16_default" />
+
+                <TextView
+                    android:id="@+id/size_desc_32"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/size_desc_16"
+                    android:gravity="center"
+                    android:text="@string/object_size_32_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_32_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_32"
+                    android:layout_below="@id/size_desc_32"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_32_default" />
+
+                <TextView
+                    android:id="@+id/size_desc_64"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/size_desc_32"
+                    android:gravity="center"
+                    android:text="@string/object_size_64_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_64_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_64"
+                    android:layout_below="@id/size_desc_64"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_64_default" />
+
+                <TextView
+                    android:id="@+id/size_desc_128"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/size_desc_64"
+                    android:gravity="center"
+                    android:text="@string/object_size_128_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_128_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_128"
+                    android:layout_below="@id/size_desc_128"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_128_default" />
+
+                <TextView
+                    android:id="@+id/size_desc_256"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/size_desc_128"
+                    android:gravity="center"
+                    android:text="@string/object_size_256_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_256_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_256"
+                    android:layout_below="@id/size_desc_256"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_256_default" />
+
+                <TextView
+                    android:id="@+id/size_desc_512"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/size_desc_256"
+                    android:gravity="center"
+                    android:text="@string/object_size_512_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_512_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_512"
+                    android:layout_below="@id/size_desc_512"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_512_default" />
+
+                <TextView
+                    android:id="@+id/size_desc_los"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/size_desc_512"
+                    android:gravity="center"
+                    android:text="@string/object_size_los_desc" />
+
+                <EditText
+                    android:id="@+id/size_dist_los_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/size_desc_los"
+                    android:layout_below="@id/size_desc_los"
+                    android:inputType="numberDecimal"
+                    android:text="@string/size_dist_los_default" />
+            </RelativeLayout>
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:gravity="left"
+                android:singleLine="true"
+                android:text="@string/los_dist_desc" />
+
+            <RelativeLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <TextView
+                    android:id="@+id/los_dist_desc_byte"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignParentLeft="true"
+                    android:layout_alignParentTop="true"
+                    android:gravity="center"
+                    android:text="@string/los_dist_byte_desc" />
+
+                <EditText
+                    android:id="@+id/los_dist_byte_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/los_dist_desc_byte"
+                    android:layout_below="@id/los_dist_desc_byte"
+                    android:inputType="numberDecimal"
+                    android:text="@string/los_dist_byte_default" />
+
+                <TextView
+                    android:id="@+id/los_dist_desc_char"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/los_dist_desc_byte"
+                    android:gravity="center"
+                    android:text="@string/los_dist_char_desc" />
+
+                <EditText
+                    android:id="@+id/los_dist_char_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/los_dist_desc_char"
+                    android:layout_below="@id/los_dist_desc_char"
+                    android:inputType="numberDecimal"
+                    android:text="@string/los_dist_char_default" />
+
+                <TextView
+                    android:id="@+id/los_dist_desc_int"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/los_dist_desc_char"
+                    android:gravity="center"
+                    android:text="@string/los_dist_int_desc" />
+
+                <EditText
+                    android:id="@+id/los_dist_int_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/los_dist_desc_int"
+                    android:layout_below="@id/los_dist_desc_int"
+                    android:inputType="numberDecimal"
+                    android:text="@string/los_dist_int_default" />
+
+                <TextView
+                    android:id="@+id/los_dist_desc_long"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="25dp"
+                    android:layout_toRightOf="@id/los_dist_desc_int"
+                    android:gravity="center"
+                    android:text="@string/los_dist_long_desc" />
+
+                <EditText
+                    android:id="@+id/los_dist_long_v"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_alignLeft="@id/los_dist_desc_long"
+                    android:layout_below="@id/los_dist_desc_long"
+                    android:inputType="numberDecimal"
+                    android:text="@string/los_dist_long_default" />
+            </RelativeLayout>
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:gravity="center"
+                android:text="@string/lifetime_desc" />
+
+            <TableLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_16_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_16_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_16_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_32_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_32_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_32_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_64_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_64_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_64_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_128_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_128_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_128_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_256_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_256_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_256_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_512_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_512_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_512_default" />
+                </TableRow>
+
+                <TableRow
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content" >
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:text="@string/object_size_los_desc" />
+
+                    <EditText
+                        android:id="@+id/lifetime_los_v"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:inputType="text"
+                        android:text="@string/lifetime_los_default" />
+                </TableRow>
+
+            </TableLayout>
+
+            <CheckBox
+                android:id="@+id/single_thread"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:text="@string/single_thread_desc" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:text="@string/thread_num_desc" />
+
+            <EditText
+                android:id="@+id/thread_num"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:inputType="number"
+                android:text="@string/thread_num_default" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center"
+                android:text="@string/exe_time_desc" />
+
+            <EditText
+                android:id="@+id/exe_time_v"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:inputType="number"
+                android:text="@string/exe_time_default" />
+
+        </LinearLayout>
+    </ScrollView>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/layout/activity_result.xml b/tests/GC/AndroidGCTest/app/src/main/res/layout/activity_result.xml
new file mode 100644 (file)
index 0000000..27c4685
--- /dev/null
@@ -0,0 +1,58 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/activity_result"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context=".ResultActivity" >
+
+    <TextView
+        android:id="@+id/vm_type"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_centerHorizontal="true"
+        android:textSize="20sp"
+        android:text="@string/vm_type">
+    </TextView>
+
+    <LinearLayout
+        android:id="@+id/buttons"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/vm_type"
+        android:layout_centerHorizontal="true"
+        android:orientation="horizontal" >
+
+        <Button
+            android:id="@+id/button_exe_time"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:text="@string/complete_time_desc" />
+
+        <Button
+            android:id="@+id/button_heap"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:text="@string/heap_desc" />
+
+        <Button
+            android:id="@+id/button_gc"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:text="@string/gc_desc" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/chart"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/buttons"
+        android:layout_marginTop="20dp"
+        android:layout_centerHorizontal="true"
+        android:orientation="horizontal" >
+    </LinearLayout>
+
+</RelativeLayout>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/menu/main.xml b/tests/GC/AndroidGCTest/app/src/main/res/menu/main.xml
new file mode 100644 (file)
index 0000000..3d9b531
--- /dev/null
@@ -0,0 +1,9 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item
+        android:id="@+id/action_button"
+        android:orderInCategory="100"
+        android:showAsAction="collapseActionView"
+        android:title="@string/action_settings"/>
+
+</menu>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644 (file)
index 0000000..6f3b755
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
new file mode 100644 (file)
index 0000000..6f3b755
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+    <background android:drawable="@drawable/ic_launcher_background" />
+    <foreground android:drawable="@drawable/ic_launcher_foreground" />
+    <monochrome android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644 (file)
index 0000000..c209e78
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644 (file)
index 0000000..b2dfe3d
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644 (file)
index 0000000..4f0f1d6
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644 (file)
index 0000000..62b611d
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644 (file)
index 0000000..948a307
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644 (file)
index 0000000..1b9a695
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644 (file)
index 0000000..28d4b77
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644 (file)
index 0000000..9287f50
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644 (file)
index 0000000..aa7d642
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644 (file)
index 0000000..9126ae3
Binary files /dev/null and b/tests/GC/AndroidGCTest/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/raw/profile.xml b/tests/GC/AndroidGCTest/app/src/main/res/raw/profile.xml
new file mode 100644 (file)
index 0000000..98a44db
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<profile id="0" name="default">
+    <item name="total_size">100</item>
+    <item name="bucket_size">1</item>
+    <item name="los_threshold">12</item>
+    <float-array name="size_dist" count="7">
+        <value>0.0436</value>
+        <value>0.5465</value>
+        <value>0.2103</value>
+        <value>0.1499</value>
+        <value>0.0275</value>
+        <value>0.0125</value>
+        <value>0.0097</value>
+    </float-array>
+    <float-array-2d name="lifetime" count="7">
+        <float-array name="16b" count="4">
+            <value>0.0865</value>
+            <value>0.5404</value>
+            <value>0.2887</value>
+            <value>0.0865</value>
+        </float-array>
+        <float-array name="32b" count="4">
+            <value>0.0469</value>
+            <value>0.7724</value>
+            <value>0.1460</value>
+            <value>0.0346</value>
+        </float-array>
+        <float-array name="64b" count="4">
+            <value>0.1154</value>
+            <value>0.5982</value>
+            <value>0.1880</value>
+            <value>0.0984</value>
+        </float-array>
+        <float-array name="128b" count="4">
+            <value>0.0662</value>
+            <value>0.7851</value>
+            <value>0.1077</value>
+            <value>0.0411</value>
+        </float-array>
+        <float-array name="256b" count="4">
+            <value>0.0520</value>
+            <value>0.8778</value>
+            <value>0.0503</value>
+            <value>0.0198</value>
+        </float-array>
+        <float-array name="512b" count="4">
+            <value>0.1628</value>
+            <value>0.7137</value>
+            <value>0.0821</value>
+            <value>0.0414</value>
+        </float-array>
+        <float-array name="los" count="4">
+            <value>0.0923</value>
+            <value>0.7117</value>
+            <value>0.1769</value>
+            <value>0.0192</value>
+        </float-array>
+    </float-array-2d>
+    <float-array name="los_element_dist" count="4">
+        <value>0.90</value>
+        <value>0.07</value>
+        <value>0.02</value>
+        <value>0.01</value>
+    </float-array>
+    <item name="thread-mode">0</item>
+    <item name="thread-num">0</item>
+    <item name="iteration-times">10</item>
+</profile>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/values-night/themes.xml b/tests/GC/AndroidGCTest/app/src/main/res/values-night/themes.xml
new file mode 100644 (file)
index 0000000..04eb47b
--- /dev/null
@@ -0,0 +1,7 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Base.Theme.AndroidGCTest" parent="Theme.Material3.DayNight.NoActionBar">
+        <!-- Customize your dark theme here. -->
+        <!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
+    </style>
+</resources>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/values/colors.xml b/tests/GC/AndroidGCTest/app/src/main/res/values/colors.xml
new file mode 100644 (file)
index 0000000..c8524cd
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <color name="black">#FF000000</color>
+    <color name="white">#FFFFFFFF</color>
+</resources>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/values/dimens.xml b/tests/GC/AndroidGCTest/app/src/main/res/values/dimens.xml
new file mode 100644 (file)
index 0000000..55c1e59
--- /dev/null
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/values/strings.xml b/tests/GC/AndroidGCTest/app/src/main/res/values/strings.xml
new file mode 100644 (file)
index 0000000..7e40352
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">AndroidGCTest</string>
+    <string name="action_settings">Setting</string>
+    <string name="button_desc">Start</string>
+
+    <string name="total_size_desc">Total object size(MB)</string>
+    <string name="total_size_default">100</string>
+
+    <string name="bucket_size_desc">Bucket size(MB)</string>
+    <string name="bucket_size_default">1</string>
+
+    <string name="los_threshold_desc">Large Object Size(KB)</string>
+    <string name="los_threshold_default">12</string>
+
+    <string name="fragment_desc">Placeholder Degree (1 - 10)</string>
+    <string name="fragment_default">6</string>
+
+    <string name="object_size_16_desc">16byte</string>
+    <string name="object_size_32_desc">32byte</string>
+    <string name="object_size_64_desc">64byte</string>
+    <string name="object_size_128_desc">128byte</string>
+    <string name="object_size_256_desc">256byte</string>
+    <string name="object_size_512_desc">512byte</string>
+    <string name="object_size_los_desc">Large Object</string>
+    <string name="object_size_smaollobject_desc">Small Object</string>
+
+    <string name="object_size_dist_desc">Object Size Distribution</string>
+    <string name="size_dist_16_default">0.0436</string>
+    <string name="size_dist_32_default">0.5465</string>
+    <string name="size_dist_64_default">0.2103</string>
+    <string name="size_dist_128_default">0.1499</string>
+    <string name="size_dist_256_default">0.0275</string>
+    <string name="size_dist_512_default">0.0125</string>
+    <string name="size_dist_los_default">0.0097</string>
+
+    <string name="los_dist_desc">Large Object Element Type Distribution</string>
+    <string name="los_dist_byte_desc">Byte Array</string>
+    <string name="los_dist_char_desc">Char Array</string>
+    <string name="los_dist_int_desc">Int Array</string>
+    <string name="los_dist_long_desc">Long Array</string>
+    <string name="los_dist_byte_default">0.90</string>
+    <string name="los_dist_char_default">0.07</string>
+    <string name="los_dist_int_default">0.02</string>
+    <string name="los_dist_long_default">0.01</string>
+
+    <string name="lifetime_desc">Object Lifetime (long lived ratio, die immediately ratio,...)</string>
+    <string name="lifetime_16_default">0.0865,0.5404,0.2887,0.0865</string>
+    <string name="lifetime_32_default">0.0469,0.7724,0.1460,0.0346</string>
+    <string name="lifetime_64_default">0.1154,0.5982,0.1880,0.0984</string>
+    <string name="lifetime_128_default">0.0662,0.7851,0.1077,0.0411</string>
+    <string name="lifetime_256_default">0.0520,0.8778,0.0503,0.0198</string>
+    <string name="lifetime_512_default">0.1628,0.7137,0.0821,0.0414</string>
+    <string name="lifetime_los_default">0.0923,0.7117,0.1769,0.0192</string>
+    <string name="lifetime_smallobject_default">0.0883,0.7146,0.1438,0.0533</string>
+
+    <string name="single_thread_desc">Run in single thread?</string>
+    <string name="thread_num_desc">Thread # (0 means setting #thread as #CPU)</string>
+    <string name="thread_num_default">0</string>
+
+    <string name="exe_time_default">100</string>
+    <string name="exe_time_desc">set the iteration times of stress test phase, iterating 100 times takes ~160s on Nexus 5/ART</string>
+    <!-- <string name="los_threads_desc">Allocate large object in all threads?</string> -->
+
+    <string name="complete_time_desc">Complete Time</string>
+    <string name="heap_desc">Heap Footprint</string>
+    <string name="gc_desc">Gc Pause Time</string>
+    <string name="runtime_desc">Device: </string>
+    <string name="execution_time_desc">Execution time:</string>
+    <string name="show_result_button_desc">Show result details</string>
+    <string name="set_profile_button_desc">Setting</string>
+    <string name="start_button_desc">Start</string>
+    <string name="setting_confirm_button_desc">Confirm changes</string>
+    <string name="profile_list_dest">Select a profile</string>
+    <string name="workload_status_desc">Click &quot;Setting&quot; to config profile, click &quot;Start&quot; to run workload</string>
+    <string name="outofmemory_desc">OutOfMemory! Please config profile or Java Runtime and run again.</string>
+
+    <string name="vm_type">vm type</string>
+</resources>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/values/styles.xml b/tests/GC/AndroidGCTest/app/src/main/res/values/styles.xml
new file mode 100644 (file)
index 0000000..088b892
--- /dev/null
@@ -0,0 +1,21 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+    <color name="result_color">#ff7f27</color>
+
+</resources>
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/values/themes.xml b/tests/GC/AndroidGCTest/app/src/main/res/values/themes.xml
new file mode 100644 (file)
index 0000000..64702ab
--- /dev/null
@@ -0,0 +1,9 @@
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Base application theme. -->
+    <style name="Base.Theme.AndroidGCTest" parent="Theme.Material3.DayNight.NoActionBar">
+        <!-- Customize your light theme here. -->
+        <!-- <item name="colorPrimary">@color/my_light_primary</item> -->
+    </style>
+
+    <style name="Theme.AndroidGCTest" parent="Base.Theme.AndroidGCTest" />
+</resources>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/xml/backup_rules.xml b/tests/GC/AndroidGCTest/app/src/main/res/xml/backup_rules.xml
new file mode 100644 (file)
index 0000000..fa0f996
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+   Sample backup rules file; uncomment and customize as necessary.
+   See https://developer.android.com/guide/topics/data/autobackup
+   for details.
+   Note: This file is ignored for devices older that API 31
+   See https://developer.android.com/about/versions/12/backup-restore
+-->
+<full-backup-content>
+    <!--
+   <include domain="sharedpref" path="."/>
+   <exclude domain="sharedpref" path="device.xml"/>
+-->
+</full-backup-content>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/main/res/xml/data_extraction_rules.xml b/tests/GC/AndroidGCTest/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644 (file)
index 0000000..9ee9997
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+   Sample data extraction rules file; uncomment and customize as necessary.
+   See https://developer.android.com/about/versions/12/backup-restore#xml-changes
+   for details.
+-->
+<data-extraction-rules>
+    <cloud-backup>
+        <!-- TODO: Use <include> and <exclude> to control what is backed up.
+        <include .../>
+        <exclude .../>
+        -->
+    </cloud-backup>
+    <!--
+    <device-transfer>
+        <include .../>
+        <exclude .../>
+    </device-transfer>
+    -->
+</data-extraction-rules>
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/app/src/test/java/com/android/gctest/ExampleUnitTest.java b/tests/GC/AndroidGCTest/app/src/test/java/com/android/gctest/ExampleUnitTest.java
new file mode 100644 (file)
index 0000000..86efc24
--- /dev/null
@@ -0,0 +1,17 @@
+package com.android.gctest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+    @Test
+    public void addition_isCorrect() {
+        assertEquals(4, 2 + 2);
+    }
+}
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/build.gradle b/tests/GC/AndroidGCTest/build.gradle
new file mode 100644 (file)
index 0000000..565f8c2
--- /dev/null
@@ -0,0 +1,4 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+alias(libs.plugins.android.application) apply false
+}
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/gradle.properties b/tests/GC/AndroidGCTest/gradle.properties
new file mode 100644 (file)
index 0000000..4387edc
--- /dev/null
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. For more details, visit
+# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/tests/GC/AndroidGCTest/gradle/libs.versions.toml b/tests/GC/AndroidGCTest/gradle/libs.versions.toml
new file mode 100644 (file)
index 0000000..4874452
--- /dev/null
@@ -0,0 +1,22 @@
+[versions]
+agp = "8.5.0"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+espressoCore = "3.6.1"
+appcompat = "1.7.0"
+material = "1.12.0"
+activity = "1.9.0"
+constraintlayout = "2.1.4"
+
+[libraries]
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
+constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+
diff --git a/tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.jar b/tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.jar
new file mode 100644 (file)
index 0000000..e708b1c
Binary files /dev/null and b/tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.properties b/tests/GC/AndroidGCTest/gradle/wrapper/gradle-wrapper.properties
new file mode 100644 (file)
index 0000000..ed94214
--- /dev/null
@@ -0,0 +1,6 @@
+#Tue Jul 16 16:27:48 KST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/tests/GC/AndroidGCTest/gradlew b/tests/GC/AndroidGCTest/gradlew
new file mode 100755 (executable)
index 0000000..4f906e0
--- /dev/null
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# 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
+#
+#      https://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.
+#
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=`expr $i + 1`
+    done
+    case $i in
+        0) set -- ;;
+        1) set -- "$args0" ;;
+        2) set -- "$args0" "$args1" ;;
+        3) set -- "$args0" "$args1" "$args2" ;;
+        4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/tests/GC/AndroidGCTest/gradlew.bat b/tests/GC/AndroidGCTest/gradlew.bat
new file mode 100644 (file)
index 0000000..ac1b06f
--- /dev/null
@@ -0,0 +1,89 @@
+@rem\r
+@rem Copyright 2015 the original author or authors.\r
+@rem\r
+@rem Licensed under the Apache License, Version 2.0 (the "License");\r
+@rem you may not use this file except in compliance with the License.\r
+@rem You may obtain a copy of the License at\r
+@rem\r
+@rem      https://www.apache.org/licenses/LICENSE-2.0\r
+@rem\r
+@rem Unless required by applicable law or agreed to in writing, software\r
+@rem distributed under the License is distributed on an "AS IS" BASIS,\r
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+@rem See the License for the specific language governing permissions and\r
+@rem limitations under the License.\r
+@rem\r
+\r
+@if "%DEBUG%" == "" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem  Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%" == "" set DIRNAME=.\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.\r
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if "%ERRORLEVEL%" == "0" goto execute\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto execute\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if "%ERRORLEVEL%"=="0" goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
+exit /b 1\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
diff --git a/tests/GC/AndroidGCTest/settings.gradle b/tests/GC/AndroidGCTest/settings.gradle
new file mode 100644 (file)
index 0000000..c0218cb
--- /dev/null
@@ -0,0 +1,23 @@
+pluginManagement {
+    repositories {
+        google {
+            content {
+                includeGroupByRegex("com\\.android.*")
+                includeGroupByRegex("com\\.google.*")
+                includeGroupByRegex("androidx.*")
+            }
+        }
+        mavenCentral()
+        gradlePluginPortal()
+    }
+}
+dependencyResolutionManagement {
+    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+    repositories {
+        google()
+        mavenCentral()
+    }
+}
+
+rootProject.name = "AndroidGCTest"
+include ':app'
diff --git a/tests/GC/TizenGCTest/Directory.Build.targets b/tests/GC/TizenGCTest/Directory.Build.targets
new file mode 100755 (executable)
index 0000000..67fcf5d
--- /dev/null
@@ -0,0 +1,21 @@
+<!--\r
+***********************************************************************************************\r
+<Build.Directory.targets>\r
+WARNING:  DO NOT MODIFY this file. Incorrect changes to this file will make it\r
+          impossible to load or build your projects from the IDE.\r
+\r
+***********************************************************************************************\r
+-->\r
+\r
+<Project>    \r
+       <Target Name="BuildDotnet" AfterTargets="TizenPackage" >\r
+        <Message Text="Tizen Build starts here ------------" Importance="high"/>\r
+        <Message Text="$(MSBuildProjectDirectory)" Importance="high"/>\r
+        <PropertyGroup>\r
+            <WorkspaceFolder>$([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))</WorkspaceFolder>\r
+        </PropertyGroup>\r
+        <Message Text="Workspace: '$(WorkspaceFolder)'"  Importance="high" />\r
+\r
+               <Exec Command="C:\tizen-studio\tools\tizen-core\tz.exe pack  -S $(ProjectDir) $(WorkspaceFolder)"> </Exec>\r
+    </Target>\r
+</Project>\r
diff --git a/tests/GC/TizenGCTest/GCTest.cs b/tests/GC/TizenGCTest/GCTest.cs
new file mode 100755 (executable)
index 0000000..f042eea
--- /dev/null
@@ -0,0 +1,1480 @@
+using System;\r
+using System.Collections.Generic;\r
+using System.Diagnostics;\r
+using System.IO;\r
+using System.Security.Claims;\r
+using System.Threading;\r
+using Tizen.Applications;\r
+using Tizen.Content.MediaContent;\r
+using Tizen.Messaging.Messages;\r
+using Tizen;\r
+using Tizen.NUI.Components;\r
+using TizenGCTest;\r
+using Microsoft.VisualBasic;\r
+using System.Linq;\r
+using System.Runtime.InteropServices;\r
+using System.Reflection;\r
+using System.Text;\r
+using Tizen.NUI;\r
+using Tizen.NUI.BaseComponents;\r
+using static System.Net.Mime.MediaTypeNames;\r
+\r
+namespace TizenGCTest\r
+{\r
+    public class TreeNode\r
+    {\r
+        public TreeNode left, right;\r
+        public TreeNode(TreeNode l, TreeNode r)\r
+        {\r
+            left = l;\r
+            right = r;\r
+        }\r
+        public TreeNode() { }\r
+        public int Count()\r
+        {\r
+            int c = 1;\r
+            if (left != null)\r
+                c += left.Count();\r
+            if (right != null)\r
+                c += right.Count();\r
+            return c;\r
+        }\r
+    }\r
+\r
+    class TreeNode32 : TreeNode\r
+    { // object size = 24\r
+        private long payload1;\r
+        public TreeNode32(TreeNode32 l, TreeNode32 r) : base(l, r) { }\r
+        public TreeNode32() { }\r
+    }\r
+\r
+    class TreeNode64 : TreeNode\r
+    { // object size = 40\r
+        private long payload1, payload2, payload3;\r
+        public TreeNode64(TreeNode64 l, TreeNode64 r) : base(l, r) { }\r
+        public TreeNode64() { }\r
+    }\r
+\r
+    class TreeNode128 : TreeNode\r
+    { // object size = 96\r
+        private long payload1, payload2, payload3, payload4, payload5;\r
+        private long payload6, payload7, payload8, payload9, payload10;\r
+        public TreeNode128(TreeNode128 l, TreeNode128 r) : base(l, r) { }\r
+        public TreeNode128() { }\r
+    }\r
+\r
+    class TreeNode256 : TreeNode\r
+    { // object size = 192\r
+        private long payload1, payload2, payload3, payload4, payload5;\r
+        private long payload6, payload7, payload8, payload9, payload10;\r
+        private long payload11, payload12, payload13, payload14, payload15;\r
+        private long payload16, payload17, payload18, payload19, payload20;\r
+        private long payload21, payload22;\r
+        public TreeNode256(TreeNode256 l, TreeNode256 r) : base(l, r) { }\r
+        public TreeNode256() { }\r
+    }\r
+\r
+    class TreeNode512 : TreeNode\r
+    { // object size = 336\r
+        private long payload1, payload2, payload3, payload4, payload5;\r
+        private long payload6, payload7, payload8, payload9, payload10;\r
+        private long payload11, payload12, payload13, payload14, payload15;\r
+        private long payload16, payload17, payload18, payload19, payload20;\r
+        private long payload101, payload102, payload103, payload104, payload105;\r
+        private long payload106, payload107, payload108, payload109, payload100;\r
+        private long payload111, payload112, payload113, payload114, payload115;\r
+        private long payload116, payload117, payload118, payload119, payload120;\r
+        public TreeNode512(TreeNode512 l, TreeNode512 r) : base(l, r) { }\r
+        public TreeNode512() { }\r
+    }\r
+\r
+    public class LinkNode\r
+    {\r
+        public LinkNode Next { get; set; }\r
+        public TreeNode TreeNode { get; set; }\r
+\r
+        public LinkNode(TreeNode n)\r
+        {\r
+            TreeNode = n;\r
+        }\r
+\r
+        public LinkNode() { }\r
+    }\r
+\r
+    class LivedLink\r
+    {\r
+        public LinkNode TreeHead { get; set; }\r
+        public LivedLink() { TreeHead = null; }\r
+        public void insertNode(TreeNode newTree)\r
+        {\r
+            if (TreeHead == null)\r
+            {\r
+                TreeHead = new LinkNode(newTree);\r
+                TreeHead.Next = null;\r
+            }\r
+            else\r
+            {\r
+                LinkNode newNode = new LinkNode(newTree);\r
+                newNode.Next = TreeHead;\r
+                TreeHead = newNode;\r
+            }\r
+        }\r
+    }\r
+\r
+    public class GCTest\r
+    {\r
+        private const String mTag = "TizenGCTest";\r
+\r
+        // size of small objects\r
+        public const int OBJECT_16_BYTE = 0;\r
+        public const int OBJECT_32_BYTE = 1;\r
+        public const int OBJECT_64_BYTE = 2;\r
+        public const int OBJECT_128_BYTE = 3;\r
+        public const int OBJECT_256_BYTE = 4;\r
+        public const int OBJECT_512_BYTE = 5;\r
+        public const int OBJECT_LARGE_BYTE = 6;\r
+        public const int OBJECT_SIZE_TYPE = 7;\r
+        private int[] mObjectSize = new int[] { 16, 24, 40, 96, 192, 336 };\r
+\r
+        // size of large object, default is 12KByte\r
+        private int mLargeObjectSize = 0;\r
+        // array element type distribution for large object\r
+        // {1-byte array, 2-byte array, 4-byte array, 8-byte array}\r
+        private float[] mLargeObjectDistribution = null;\r
+\r
+        // allocation configuration\r
+        // total allocate size\r
+        private int mTotalAllocateSize = 0;\r
+        // total allocate size by one thread\r
+        private int mTotalAllocSizePerThread = 0;\r
+\r
+        // unit for tree allocation/deletion operation.\r
+        // mBucketSize is also the unit to measure object lifetime.\r
+        // Benchmark allocates mBucketSize of data -> deletes some data\r
+        // -> allocates mBucketSize of Data\r
+        private int mBucketSize = 0;\r
+\r
+        // allocated object size distribution\r
+        // {[1-16], [17-32], [33-64], [65, 128], [129, 256], [257, 512], >12K}\r
+        private float[] mSizeDistribution = null;\r
+\r
+        // allocated object lifetime:\r
+        // mLifetime[X][0] is long lived object percentage of object size X,\r
+        // mLifetime[X][1] is percentage of object die immediately,\r
+        // mLifetime[X][2] is percentage of object die in next period after\r
+        // creation period ...\r
+        private float[][] mLifetime = null;\r
+\r
+        private int mLongLiveSmallObjectSize;\r
+\r
+        // a big array to store random values to decide object size of next allocated object\r
+        private byte[][] mObjectSizeRandom = null;\r
+        // a big array to store random values to decide lifetime of next allocated object\r
+        private byte[][] mLifetimeRandom = null;\r
+        private int mShortLiveTreeCount;\r
+        private int mTotalNodeCount;\r
+        private const int mTreeCountParallel = 4;\r
+\r
+        private int[] mLargeArrayLength = null;\r
+        private int[] mLargeArrayNum = null;\r
+        private int[] mLargeArrayInter = null;\r
+        private int mLongLiveLargeObjectSize;\r
+        private int[][] mDieNumLargeObject = null;\r
+\r
+        // thread mode configuration\r
+        private int mThreadNum;\r
+        private bool mSingleThread = false;\r
+\r
+        private long[] mStartTime = null;\r
+        private long[] mEndTime = null;\r
+        private long[] mElapseTime = null;\r
+        private int[] mHeapFootprint = null;\r
+        private long[] mHeapBytesAllocated = null;\r
+\r
+        private long mTotalGcCount;\r
+        private long mTotalGcTime;\r
+        private long mTotalBlockingGcCount;\r
+        private long mTotalBlockingGcTime;\r
+        public String[] GC_CAUSE_ART = new String[]{"Alloc", "Background", "Explicit", "NativeAlloc", "CollectorTransition", "DisableMovingGc", "HomogeneousSpaceCompact", "HeapTrim"};\r
+        public String[] GC_CAUSE_DALVIK = new String[]{"GC_FOR_ALLOC","GC_CONCURRENT", "GC_EXPLICIT", "GC_BEFORE_OOM"};\r
+        private int[] mGcCauseCount = null;\r
+        private float[] mGcPauseTime = null;\r
+        private float[] mGcTotalTime = null;\r
+        private String[] mGcCause = null;\r
+\r
+        private bool isArt;\r
+        private bool mWorkloadComplete;\r
+        private int mIterNum = 100;\r
+\r
+        private StreamWriter fileOutput;\r
+        private BenchThread[] mTestThreads;\r
+        //private Thread[] mThreads;\r
+        private Thread t0, t1, t2, t3;\r
+        private bool mOutOfMemory;\r
+        private bool flag0 = false, flag1 = false, flag2 = false, flag3 = false;\r
+\r
+        private readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);\r
+\r
+        public TextLabel text;\r
+\r
+        private void init()\r
+        {\r
+            // thread number;\r
+            if (mSingleThread)\r
+            {\r
+                mThreadNum = 1;\r
+            }\r
+            else if (mThreadNum == 0)\r
+            {\r
+                //mThreadNum = Runtime.getRuntime().availableProcessors();\r
+                mThreadNum = Environment.ProcessorCount;\r
+            }\r
+            if (mThreadNum == 0)\r
+            {\r
+                mThreadNum = 1;\r
+            }\r
+\r
+            if (mSizeDistribution == null)\r
+            {\r
+                mSizeDistribution = new float[]{0.0436f,0.5465f,0.2103f,0.1499f,\r
+                    0.0275f,0.0125f,0.0097f};\r
+            }\r
+            //if (mLifetime == null)\r
+            {\r
+                mLifetime = new float[][] {\r
+                            new float[] { 0.0865f, 0.5404f, 0.2887f, 0.0865f },\r
+                            new float[] { 0.0469f, 0.7724f, 0.1460f, 0.0346f },\r
+                            new float[] { 0.1154f, 0.5982f, 0.1880f, 0.0984f },\r
+                            new float[] { 0.0662f, 0.7851f, 0.1077f, 0.0411f },\r
+                            new float[] { 0.0520f, 0.8778f, 0.0503f, 0.0198f },\r
+                            new float[] { 0.1628f, 0.7137f, 0.0821f, 0.0414f },\r
+                            new float[] { 0.0923f, 0.7117f, 0.1769f, 0.0192f }// large object lifetime\r
+                            };\r
+           \r
+            }\r
+\r
+            if (mLargeObjectDistribution == null)\r
+            {\r
+                mLargeObjectDistribution = new float[] { 0.9f, 0.07f, 0.02f, 0.01f };\r
+            }\r
+\r
+            if (mTotalAllocateSize == 0)\r
+            {\r
+                mTotalAllocateSize = 100 * 1024 * 1024;\r
+            }\r
+            mTotalAllocSizePerThread = mTotalAllocateSize / mThreadNum;\r
+\r
+            if (mBucketSize == 0)\r
+            {\r
+                mBucketSize = 1 * 1024 * 1024;\r
+            }\r
+\r
+            if (mLargeObjectSize == 0)\r
+            {\r
+                mLargeObjectSize = 12 * 1024;\r
+            }\r
+\r
+            Log.Info(mTag, "Allocate Size: " + (mTotalAllocateSize / 1024) + " kB");\r
+            Log.Info(mTag, "BucketSize: " + (mBucketSize / 1024) + " kB");\r
+            Log.Info(mTag, "Large object size: " + (mLargeObjectSize / 1024) + " kB");\r
+            Log.Info(mTag, "Single Thread: " + mSingleThread);\r
+            Log.Info(mTag, "Thread number: " + mThreadNum);\r
+            Log.Info(mTag, "Stress test part iterates " + mIterNum + " times");\r
+\r
+            string curDate = DateTime.Now.ToString();\r
+            try\r
+            {\r
+                using (StreamWriter fileOutput = new StreamWriter("/tmp/TizenGCTest-result.txt", true))\r
+                {\r
+                    fileOutput.WriteLine();\r
+                    fileOutput.WriteLine(curDate);\r
+\r
+                    fileOutput.WriteLine("Workload configuration:");\r
+                    fileOutput.WriteLine("\tAllocate Size: " + (mTotalAllocateSize / 1024) + " kB");\r
+                    fileOutput.WriteLine("\tBucketSize: " + (mBucketSize / 1024) + " kB");\r
+                    fileOutput.WriteLine("\tLarge object size: " + (mLargeObjectSize / 1024) + " kB");\r
+                    fileOutput.WriteLine("\tThread mode: " + (mSingleThread ? "Single-Thread" : "Multi-Thread"));\r
+                    fileOutput.WriteLine("\t: " + mThreadNum);\r
+                    fileOutput.WriteLine("\tStress test part iterates " + mIterNum + " times");\r
+                }\r
+            }\r
+            catch (IOException e)\r
+            {\r
+                Log.Info(mTag, "Cannot open /tmp/TizenGCTest-result.txt" + e.Message);\r
+            }\r
+\r
+            int smallObjectSize, largeObjectSize;\r
+            largeObjectSize = (int)(mTotalAllocSizePerThread * mSizeDistribution[OBJECT_LARGE_BYTE]);\r
+            smallObjectSize = mTotalAllocSizePerThread - largeObjectSize;\r
+\r
+            float[] countDistr = new float[OBJECT_LARGE_BYTE];\r
+            float nodeSize = 0.0f;\r
+            int[] sizeThreshold = new int[OBJECT_LARGE_BYTE];\r
+            int lifetimeLen = mLifetime[0].Length;\r
+            int[][] lifetimeThreshold = new int[OBJECT_LARGE_BYTE][];\r
+            for (int i = 0; i < OBJECT_LARGE_BYTE; i++)\r
+            {\r
+                lifetimeThreshold[i] = new int[lifetimeLen];\r
+            }\r
+            float sum = 0.0f;\r
+            for (int i = 0; i < OBJECT_LARGE_BYTE; i++)\r
+            {\r
+                countDistr[i] = mSizeDistribution[i]\r
+                        / (1 - mSizeDistribution[OBJECT_LARGE_BYTE]) / mObjectSize[i];\r
+                sum += countDistr[i];\r
+            }\r
+\r
+            mLongLiveSmallObjectSize = 0;\r
+            float sum1 = 0.0f;\r
+            for (int i = 0; i < OBJECT_LARGE_BYTE; i++)\r
+            {\r
+                sum1 += countDistr[i];\r
+                sizeThreshold[i] = (int)(sum1 * 1000 / sum + 0.5);\r
+                nodeSize += mObjectSize[i] * countDistr[i] / sum;\r
+\r
+                float sum2 = 0.0f;\r
+                for (int j = 1; j < lifetimeLen; j++)\r
+                {\r
+                    sum2 += mLifetime[i][j];\r
+                    lifetimeThreshold[i][j - 1] = (int)(sum2 * 1000 + 0.5);\r
+                }\r
+                lifetimeThreshold[i][lifetimeLen - 1] = 1000;\r
+\r
+                mLongLiveSmallObjectSize += (int)(mTotalAllocSizePerThread * mSizeDistribution[i] * mLifetime[i][0]);\r
+            }\r
+            sizeThreshold[OBJECT_512_BYTE] = 1000;\r
+\r
+\r
+            mShortLiveTreeCount = (int)(smallObjectSize / mBucketSize + 0.5);\r
+            mTotalNodeCount = (int)(mBucketSize / nodeSize * 1.11);\r
+\r
+            mObjectSizeRandom = new byte[mThreadNum][];\r
+            mLifetimeRandom = new byte[mThreadNum][];\r
+            for (int i = 0; i < mThreadNum; i++)\r
+            {\r
+                mObjectSizeRandom[i] = new byte[mTotalNodeCount];\r
+                mLifetimeRandom[i] = new byte[mTotalNodeCount];\r
+            }\r
+\r
+            Random r_size = new Random();\r
+            Random r_lifetime = new Random(mThreadNum);\r
+            for (int i = 0; i < mThreadNum; i++)\r
+            {\r
+                r_size = new Random(i);\r
+                r_lifetime = new Random(i + mThreadNum);\r
+                for (int j = 0; j < mTotalNodeCount; j++)\r
+                {\r
+                    int vs = r_size.Next(1000);\r
+                    int vl = r_lifetime.Next(1000);\r
+                    for (int k = 0; k < OBJECT_LARGE_BYTE; k++)\r
+                    {\r
+                        if (vs < sizeThreshold[k])\r
+                        {\r
+                            mObjectSizeRandom[i][j] = (byte)(OBJECT_16_BYTE + k);\r
+                            for (int l = 0; l < lifetimeLen; l++)\r
+                            {\r
+                                if (vl < lifetimeThreshold[k][l])\r
+                                {\r
+                                    mLifetimeRandom[i][j] = (byte)l;\r
+                                    //Log.Info(mTag, "mLifetimeRandom["+i+"]["+j+"] : " + l);\r
+                                    break;\r
+                                }\r
+                            }\r
+                            break;\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+\r
+            mLongLiveLargeObjectSize = (int)(largeObjectSize * mLifetime[OBJECT_LARGE_BYTE][0]);\r
+            mDieNumLargeObject = new int[4][];\r
+            for (int i = 0; i < 4; i++)\r
+            {\r
+                mDieNumLargeObject[i] = new int[lifetimeLen - 1];\r
+            }\r
+            mLargeArrayInter = new int[4];\r
+            mLargeArrayLength = new int[4];\r
+            mLargeArrayNum = new int[4];\r
+            for (int i = 0; i < 4; i++)\r
+            {\r
+                mLargeArrayLength[i] = (int)((largeObjectSize * mLargeObjectDistribution[i]\r
+                        / mLargeObjectSize) + 0.5);\r
+                if (mLargeArrayLength[i] == 0)\r
+                {\r
+                    mLargeArrayInter[i] = mShortLiveTreeCount + 1;\r
+                    mLargeArrayNum[i] = 0;\r
+                    continue;\r
+                }\r
+                if (mShortLiveTreeCount > mLargeArrayLength[i])\r
+                {\r
+                    mLargeArrayInter[i] = mShortLiveTreeCount / mLargeArrayLength[i];\r
+                    mLargeArrayNum[i] = 1;\r
+                    mLargeArrayLength[i] = mShortLiveTreeCount / mLargeArrayInter[i] + 1;\r
+                }\r
+                else\r
+                {\r
+                    mLargeArrayInter[i] = 1;\r
+                    mLargeArrayNum[i] = (int)(mLargeArrayLength[i] / (float)mShortLiveTreeCount + 0.5);\r
+                    mLargeArrayLength[i] = mLargeArrayNum[i] * mShortLiveTreeCount;\r
+                }\r
+\r
+                sum = 0.0f;\r
+                for (int j = 1; j < lifetimeLen; j++)\r
+                {\r
+                    sum += mLifetime[OBJECT_LARGE_BYTE][j];\r
+                    mDieNumLargeObject[i][j - 1] = (int)(mLargeArrayNum[i] * sum);\r
+                }\r
+            }\r
+            text = new TextLabel();\r
+            text.TextColor = Color.White;\r
+            Window.Instance.GetDefaultLayer().Add(text);\r
+            Log.Info(mTag, "init done");\r
+        }\r
+\r
+        private void clearInitData()\r
+        {\r
+            Log.Info(mTag, "clear auxiliary data to run workload");\r
+            mLifetime = null;\r
+            mLargeObjectDistribution = null;\r
+            mSizeDistribution = null;\r
+            mObjectSizeRandom = null;\r
+            mLifetimeRandom = null;\r
+            mLargeArrayInter = null;\r
+            mLargeArrayLength = null;\r
+            mLargeArrayNum = null;\r
+            mDieNumLargeObject = null;\r
+            //Runtime.getRuntime().runFinalization();\r
+            //Runtime.getRuntime().gc();\r
+            GC.Collect();\r
+            GC.WaitForPendingFinalizers();\r
+        }\r
+\r
+        public GCTest()\r
+        {\r
+            init();\r
+        }\r
+        public GCTest(/*MainActivity activity,*/ int heapSize, int bucketSize, int largeObjectSize,\r
+                          float[] sizeDistr, float[][] lifetimeDistr, float[] largeObjectSizeDist,\r
+                          bool singleThread, int thread_num, int exeTime)\r
+        {\r
+            //mActivity = activity;\r
+            mTotalAllocateSize = heapSize * 1024 * 1024;\r
+            mBucketSize = bucketSize * 1024 * 1024;\r
+            mLargeObjectSize = largeObjectSize * 1024;\r
+            mSizeDistribution = sizeDistr;\r
+            mLifetime = lifetimeDistr;\r
+            mLargeObjectDistribution = largeObjectSizeDist;\r
+            mSingleThread = singleThread;\r
+            mThreadNum = mSingleThread ? 1 : thread_num;\r
+            mIterNum = exeTime > 0 ? exeTime : 100;\r
+            init();\r
+        }\r
+\r
+\r
+        private void freeArrays(byte[][] byteArray, char[][] charArray, int[][] intArray,\r
+                            long[][] longArray, int[] arrayIdx, int treeCount)\r
+        {\r
+            int len = mDieNumLargeObject[0].Length;\r
+            int died, release, phase;\r
+\r
+            phase = treeCount % mLargeArrayInter[0];\r
+            if (byteArray != null && phase <= len)\r
+            {\r
+                int curIdx = arrayIdx[0] - mLargeArrayNum[0];\r
+                while (curIdx >= 0 && phase <= len)\r
+                {\r
+                    if (phase == 0)\r
+                        died = 0;\r
+                    else\r
+                        died = mDieNumLargeObject[0][phase - 1];\r
+                    if (phase == len)\r
+                    {\r
+                        if (byteArray[curIdx + died] != null)\r
+                        {\r
+                            for (int i = died; i < mLargeArrayNum[0]; i++)\r
+                                byteArray[curIdx + i] = null;\r
+                        }\r
+                        break;\r
+                    }\r
+                    release = mDieNumLargeObject[0][phase];\r
+                    for (int i = died; i < release; i++)\r
+                    {\r
+                        if (i >= mLargeArrayNum[0])\r
+                            break;\r
+                        byteArray[curIdx + i] = null;\r
+                    }\r
+                    curIdx -= mLargeArrayNum[0];\r
+                    phase += mLargeArrayInter[0];\r
+                }\r
+            }\r
+\r
+            phase = treeCount % mLargeArrayInter[1];\r
+            if (charArray != null && phase < mLargeArrayNum[1])\r
+            {\r
+                int curIdx = arrayIdx[1] - mLargeArrayNum[1];\r
+                while (curIdx >= 0 && phase <= len)\r
+                {\r
+                    if (phase == 0)\r
+                        died = 0;\r
+                    else\r
+                        died = mDieNumLargeObject[1][phase - 1];\r
+                    if (phase == len)\r
+                    {\r
+                        if (charArray[curIdx + died] != null)\r
+                        {\r
+                            for (int i = died; i < mLargeArrayNum[1]; i++)\r
+                                charArray[curIdx + i] = null;\r
+                        }\r
+                        break;\r
+                    }\r
+                    release = mDieNumLargeObject[1][phase];\r
+                    for (int i = died; i < release; i++)\r
+                    {\r
+                        if (i >= mLargeArrayNum[1])\r
+                            break;\r
+                        charArray[curIdx + i] = null;\r
+                    }\r
+                    curIdx -= mLargeArrayNum[1];\r
+                    phase += mLargeArrayInter[1];\r
+                }\r
+            }\r
+\r
+            phase = treeCount % mLargeArrayInter[2];\r
+            if (intArray != null && phase < mLargeArrayNum[2])\r
+            {\r
+                int curIdx = arrayIdx[2] - mLargeArrayNum[2];\r
+                while (curIdx >= 0 && phase <= len)\r
+                {\r
+                    if (phase == 0)\r
+                        died = 0;\r
+                    else\r
+                        died = mDieNumLargeObject[2][phase - 1];\r
+                    if (phase == len)\r
+                    {\r
+                        if (intArray[curIdx + died] != null)\r
+                        {\r
+                            for (int i = died; i < mLargeArrayNum[2]; i++)\r
+                                intArray[curIdx + i] = null;\r
+                        }\r
+                        break;\r
+                    }\r
+                    release = mDieNumLargeObject[2][phase];\r
+                    for (int i = died; i < release; i++)\r
+                    {\r
+                        if (i >= mLargeArrayNum[2])\r
+                            break;\r
+                        intArray[curIdx + i] = null;\r
+                    }\r
+                    curIdx -= mLargeArrayNum[2];\r
+                    phase += mLargeArrayInter[2];\r
+                }\r
+            }\r
+\r
+            phase = treeCount % mLargeArrayInter[3];\r
+            if (longArray != null && phase < mLargeArrayNum[3])\r
+            {\r
+                int curIdx = arrayIdx[3] - mLargeArrayNum[3];\r
+                while (curIdx >= 0 && phase <= len)\r
+                {\r
+                    if (phase == 0)\r
+                        died = 0;\r
+                    else\r
+                        died = mDieNumLargeObject[3][phase - 1];\r
+                    if (phase == len)\r
+                    {\r
+                        if (longArray[curIdx + died] != null)\r
+                        {\r
+                            for (int i = died; i < mLargeArrayNum[3]; i++)\r
+                                longArray[curIdx + i] = null;\r
+                        }\r
+                        break;\r
+                    }\r
+                    release = mDieNumLargeObject[3][phase];\r
+                    for (int i = died; i < release; i++)\r
+                    {\r
+                        if (i >= mLargeArrayNum[3])\r
+                            break;\r
+                        longArray[curIdx + i] = null;\r
+                    }\r
+                    curIdx -= mLargeArrayNum[3];\r
+                    phase += mLargeArrayInter[3];\r
+                }\r
+            }\r
+        }\r
+\r
+        private void makeTreesLongLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount)\r
+        {\r
+            while (true)\r
+            {\r
+                if (allocSize <= 0)\r
+                {\r
+                    trees = null;\r
+                    return;\r
+                }\r
+\r
+                int len = trees.Length;\r
+                TreeNode[] nextTrees = new TreeNode[len * 2];\r
+                byte random;\r
+                for (int i = 0; i < len; i++)\r
+                {\r
+                    TreeNode node = null;\r
+                    random = mObjectSizeRandom[myId][nodeCount[0]];\r
+                    switch (random)\r
+                    {\r
+                        case OBJECT_16_BYTE:\r
+                            node = new TreeNode();\r
+                            break;\r
+                        case OBJECT_32_BYTE:\r
+                            node = new TreeNode32();\r
+                            break;\r
+                        case OBJECT_64_BYTE:\r
+                            node = new TreeNode64();\r
+                            break;\r
+                        case OBJECT_128_BYTE:\r
+                            node = new TreeNode128();\r
+                            break;\r
+                        case OBJECT_256_BYTE:\r
+                            node = new TreeNode256();\r
+                            break;\r
+                        case OBJECT_512_BYTE:\r
+                            node = new TreeNode512();\r
+                            break;\r
+                    }\r
+                    trees[i].left = node;\r
+                    nextTrees[2 * i] = node;\r
+                    allocSize -= mObjectSize[random];\r
+                    nodeCount[0]++;\r
+                    if (nodeCount[0] == mTotalNodeCount)\r
+                        nodeCount[0] = 0;\r
+\r
+                    random = mObjectSizeRandom[myId][nodeCount[0]];\r
+                    switch (random)\r
+                    {\r
+                        case OBJECT_16_BYTE:\r
+                            node = new TreeNode();\r
+                            break;\r
+                        case OBJECT_32_BYTE:\r
+                            node = new TreeNode32();\r
+                            break;\r
+                        case OBJECT_64_BYTE:\r
+                            node = new TreeNode64();\r
+                            break;\r
+                        case OBJECT_128_BYTE:\r
+                            node = new TreeNode128();\r
+                            break;\r
+                        case OBJECT_256_BYTE:\r
+                            node = new TreeNode256();\r
+                            break;\r
+                        case OBJECT_512_BYTE:\r
+                            node = new TreeNode512();\r
+                            break;\r
+                    }\r
+                    trees[i].right = node;\r
+                    nextTrees[2 * i + 1] = node;\r
+                    allocSize -= mObjectSize[random];\r
+                    nodeCount[0]++;\r
+                    if (nodeCount[0] == mTotalNodeCount)\r
+                        nodeCount[0] = 0;\r
+\r
+                    if (allocSize <= 0)\r
+                    {\r
+                        trees = null;\r
+                        break;\r
+                    }\r
+                }\r
+                trees = null;\r
+                trees = nextTrees;\r
+            }\r
+        }\r
+\r
+        private void makeTreesShortLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount)\r
+        {\r
+            int lifetimeLen = mLifetime[0].Length;\r
+            int[] curTreeIdx = new int[lifetimeLen];\r
+            int[] nextTreeIdx = new int[lifetimeLen];\r
+            TreeNode[][] curTrees = new TreeNode[lifetimeLen][];\r
+            TreeNode[][] nextTrees = new TreeNode[lifetimeLen][];\r
+            for (int i = 0; i < lifetimeLen; i++)\r
+            {\r
+                curTrees[i] = new TreeNode[1];\r
+                curTrees[i][0] = trees[i];\r
+                curTreeIdx[i] = 0;\r
+            }\r
+\r
+            while (true)\r
+            {\r
+                if (allocSize <= 0)\r
+                {\r
+                    trees = null;\r
+                    return;\r
+                }\r
+\r
+                byte rs = mObjectSizeRandom[myId][nodeCount[0]];\r
+                TreeNode node = null;\r
+                switch (rs)\r
+                {\r
+                    case OBJECT_16_BYTE:\r
+                        node = new TreeNode();\r
+                        break;\r
+                    case OBJECT_32_BYTE:\r
+                        node = new TreeNode32();\r
+                        break;\r
+                    case OBJECT_64_BYTE:\r
+                        node = new TreeNode64();\r
+                        break;\r
+                    case OBJECT_128_BYTE:\r
+                        node = new TreeNode128();\r
+                        break;\r
+                    case OBJECT_256_BYTE:\r
+                        node = new TreeNode256();\r
+                        break;\r
+                    case OBJECT_512_BYTE:\r
+                        node = new TreeNode512();\r
+                        break;\r
+                }\r
+\r
+                byte rl = mLifetimeRandom[myId][nodeCount[0]];\r
+                if (nextTrees[rl] == null)\r
+                {\r
+                    nextTrees[rl] = new TreeNode[curTrees[rl].Length << 1];\r
+                    nextTreeIdx[rl] = 0;\r
+                    nextTrees[rl][0] = node;\r
+                }\r
+                else\r
+                {\r
+                    nextTrees[rl][++nextTreeIdx[rl]] = node;\r
+                }\r
+                TreeNode parent = curTrees[rl][curTreeIdx[rl]];\r
+                if (parent.left == null)\r
+                {\r
+                    parent.left = node;\r
+                }\r
+                else\r
+                {\r
+                    parent.right = node;\r
+                    curTreeIdx[rl]++;\r
+                    if (curTreeIdx[rl] == curTrees[rl].Length)\r
+                    {\r
+                        curTrees[rl] = nextTrees[rl];\r
+                        nextTrees[rl] = null;\r
+                        curTreeIdx[rl] = 0;\r
+                    }\r
+                }\r
+\r
+                allocSize -= mObjectSize[rs];\r
+                nodeCount[0]++;\r
+                if (nodeCount[0] == mTotalNodeCount) nodeCount[0] = 0;\r
+            }\r
+        }\r
+\r
+        public bool allocTrace(int myId)\r
+        {\r
+            switch(myId) {\r
+                case 0:\r
+                    if (flag0) return false;\r
+                    else flag0 = true;\r
+                    break;\r
+                case 1:\r
+                    if (flag1) return false;\r
+                    else flag1 = true;\r
+                    break;\r
+                case 2:\r
+                    if (flag2) return false;\r
+                    else flag2 = true;\r
+                    break;\r
+                case 3:\r
+                    if (flag3) return false;\r
+                    else flag3 = true;\r
+                    break;\r
+            }\r
+            \r
+            // long-lived data\r
+            Log.Info(mTag, "Thread-" + myId + " ----- Build long lived trees -----");\r
+\r
+            LivedLink longLiveTreeLink = new LivedLink();\r
+            TreeNode[] trees = new TreeNode[mTreeCountParallel];\r
+            int[] nodeCount = new int[] { 0 };\r
+\r
+            for (int i = 0; i < mTreeCountParallel; i++)\r
+            {\r
+                TreeNode node = new TreeNode();\r
+                longLiveTreeLink.insertNode(node);\r
+                trees[i] = node;\r
+            }\r
+\r
+            makeTreesLongLive(trees, mLongLiveSmallObjectSize, myId, nodeCount);\r
+\r
+            trees = null;\r
+\r
+            Log.Info(mTag, "Thread-" + myId + " ----- Build long lived byte array -----");\r
+            int longLiveArrayCount = (int)(mLongLiveLargeObjectSize / mLargeObjectSize + 0.5);\r
+            if (longLiveArrayCount <= 0)\r
+                longLiveArrayCount = 1;\r
+            byte[][] longLiveByteArrays = new byte[longLiveArrayCount][];\r
+            for (int i = 0; i < longLiveArrayCount; i++)\r
+            {\r
+                longLiveByteArrays[i] = new byte[mLargeObjectSize];\r
+                for (int j = 0; j < mLargeObjectSize; j += 100)\r
+                    longLiveByteArrays[i][j] = (byte)0xff;\r
+            }\r
+\r
+            // stress test\r
+            Log.Info(mTag, "Thread-" + myId + " ----- Stress test -----");\r
+            //Debug.MemoryInfo memInfo = new Debug.MemoryInfo();\r
+\r
+            int lifetimeLen = mLifetime[0].Length;\r
+            TreeNode[][] shortLiveTrees = new TreeNode[lifetimeLen][];\r
+            for (int i = 0; i < lifetimeLen; i++)\r
+            {\r
+                shortLiveTrees[i] = new TreeNode[lifetimeLen];\r
+            }\r
+\r
+            byte[][] shortLiveByteArray = null;\r
+            char[][] shortLiveCharArray = null;\r
+            int[][] shortLiveIntArray = null;\r
+            long[][] shortLiveLongArray = null;\r
+\r
+            nodeCount[0] = 0;\r
+            int round = 0;\r
+\r
+            for (int iter = 0; iter < mIterNum; iter++)\r
+            {\r
+                //Log.Info(mTag, "Run " + myId + " - iter : " + iter);\r
+                if (mOutOfMemory)\r
+                    break;\r
+                int[] allocIdx = new int[] { 0, 0, 0, 0 };\r
+\r
+                if (mLargeArrayLength[0] != 0)\r
+                    shortLiveByteArray = new byte[mLargeArrayLength[0]][];\r
+                if (mLargeArrayLength[1] != 0)\r
+                    shortLiveCharArray = new char[mLargeArrayLength[1]][];\r
+                if (mLargeArrayLength[2] != 0)\r
+                    shortLiveIntArray = new int[mLargeArrayLength[2]][];\r
+                if (mLargeArrayLength[3] != 0)\r
+                    shortLiveLongArray = new long[mLargeArrayLength[3]][];\r
+\r
+                int treeCount = 0;\r
+                while (treeCount < mShortLiveTreeCount)\r
+                {\r
+                    int treesIdx = round % lifetimeLen;\r
+                    round++;\r
+                    for (int i = 0; i < lifetimeLen; i++)\r
+                    {\r
+                        TreeNode node = new TreeNode();\r
+                        shortLiveTrees[treesIdx][i] = node;\r
+                    }\r
+                    makeTreesShortLive(shortLiveTrees[treesIdx], mBucketSize, myId, nodeCount);\r
+\r
+                    for (int i = 0; i < lifetimeLen; i++)\r
+                    {\r
+                        int idx = (treesIdx - i + lifetimeLen) % lifetimeLen;\r
+                        shortLiveTrees[idx][i] = null;\r
+                    }\r
+\r
+                    if ((mLargeArrayLength[0] > 0) && ((treeCount % mLargeArrayInter[0]) == 0))\r
+                    {\r
+                        for (int n = 0; n < mLargeArrayNum[0]; n++)\r
+                            shortLiveByteArray[allocIdx[0] + n] = new byte[mLargeObjectSize];\r
+                        allocIdx[0] += mLargeArrayNum[0];\r
+                    }\r
+\r
+                    if ((mLargeArrayLength[1] > 0) && ((treeCount % mLargeArrayInter[1]) == 0))\r
+                    {\r
+                        for (int n = 0; n < mLargeArrayNum[1]; n++)\r
+                            shortLiveCharArray[allocIdx[1] + n] = new char[mLargeObjectSize / 2];\r
+                        allocIdx[1] += mLargeArrayNum[1];\r
+                    }\r
+\r
+                    if ((mLargeArrayLength[2] > 0) && ((treeCount % mLargeArrayInter[2]) == 0))\r
+                    {\r
+                        for (int n = 0; n < mLargeArrayNum[2]; n++)\r
+                            shortLiveIntArray[allocIdx[2] + n] = new int[mLargeObjectSize / 4];\r
+                        allocIdx[2] += mLargeArrayNum[2];\r
+                    }\r
+\r
+                    if ((mLargeArrayLength[3] > 0) && ((treeCount % mLargeArrayInter[3]) == 0))\r
+                    {\r
+                        for (int n = 0; n < mLargeArrayNum[3]; n++)\r
+                            shortLiveLongArray[allocIdx[3] + n] = new long[mLargeObjectSize / 8];\r
+                        allocIdx[3] += mLargeArrayNum[3];\r
+                    }\r
+\r
+                    freeArrays(shortLiveByteArray, shortLiveCharArray, shortLiveIntArray,\r
+                            shortLiveLongArray, allocIdx, treeCount);\r
+\r
+                    treeCount++;\r
+                }\r
+\r
+                if (myId == 0)\r
+                {\r
+                    //Debug.getMemoryInfo(memInfo);\r
+                    //mHeapFootprint[iter] = memInfo.dalvikPss;\r
+                    mHeapFootprint[iter] = (int)GC.GetGCMemoryInfo().HeapSizeBytes;\r
+                    //if (getRuntimeStatMethod != null)\r
+                    //mHeapBytesAllocated[iter] = (GetRuntimeStat("gc.bytes-allocated") - GetRuntimeStat("gc.bytes-freed")) / 1024;\r
+                    //else\r
+                    mHeapBytesAllocated[iter] = (GC.GetTotalMemory(false) / 1024);\r
+\r
+                    //Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkProgress);\r
+                    //m.arg1 = iter + 1;\r
+                    //mActivity.getHandler().sendMessage(m);\r
+\r
+                    text.Text = (((iter + 1) *100) / mIterNum) + "%";\r
+                    Log.Info(mTag, text.Text);\r
+                    \r
+                }\r
+            }\r
+\r
+            if (longLiveTreeLink.TreeHead.TreeNode != null\r
+             && longLiveByteArrays[0][100] == (byte)0xff\r
+             && longLiveByteArrays[longLiveArrayCount - 1][200] == (byte)0xff)\r
+            {\r
+                mEndTime[myId] = (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;\r
+                mElapseTime[myId] = mEndTime[myId] - mStartTime[myId];\r
+                return true;\r
+            }\r
+\r
+            return false;\r
+        }\r
+\r
+        public class BenchThread\r
+        {\r
+            private static int myId;\r
+            private static GCTest gcParent;\r
+            public ThreadStart thread;\r
+\r
+            public BenchThread(int id, GCTest parent)\r
+            {\r
+                myId = id;\r
+                gcParent = parent;\r
+                thread += Run;\r
+            }\r
+\r
+            private void Run()\r
+            {\r
+                gcParent.mElapseTime[myId] = 0;\r
+                gcParent.mStartTime[myId] = (long)(DateTime.UtcNow - gcParent.Jan1st1970).TotalMilliseconds;\r
+                try\r
+                {\r
+                    if (!gcParent.allocTrace(myId))\r
+                    {\r
+                        Log.Info(mTag, "Error in thread-" + myId);\r
+                    }\r
+                }\r
+                catch (OutOfMemoryException e)\r
+                {\r
+                    gcParent.mOutOfMemory = true;\r
+                    Log.Info(mTag, "Thread-" + myId + " meets OutOfMemory");\r
+                    //Message m = mActivity.GetHandler().ObtainMessage(MainActivity.BenchmarkOutOfMemoryError);\r
+                    //m.Arg1 = myId;\r
+                    //mActivity.GetHandler().SendMessage(m);\r
+                }\r
+            }\r
+        }\r
+\r
+        public void start()\r
+        {\r
+            /*if (getRuntimeStatMethod == null)\r
+            {\r
+                try\r
+                {\r
+                    Type c = Type.GetType("Android.OS.Debug");\r
+                    if (c != null)\r
+                        getRuntimeStatMethod = c.GetMethod("GetRuntimeStat", new Type[] { typeof(string) });\r
+                }\r
+                catch (TypeLoadException e)\r
+                {\r
+                    Log.Warn(mTag, "Cannot find Android.OS.Debug class");\r
+                }\r
+                catch (MissingMethodException e)\r
+                {\r
+                    Log.Warn(mTag, "No GetRuntimeStat method in Android.OS.Debug");\r
+                }\r
+            }*/\r
+\r
+            var info1_1 = GC.GetGCMemoryInfo(GCKind.Ephemeral);\r
+            Log.Info(mTag, "Generation: " + info1_1.Generation);\r
+\r
+            var info2_1 = GC.GetGCMemoryInfo();\r
+            Log.Info(mTag, "Generation: " + info2_1.Generation);\r
+\r
+            mElapseTime = new long[mThreadNum];\r
+            mStartTime = new long[mThreadNum];\r
+            mEndTime = new long[mThreadNum];\r
+            mHeapFootprint = new int[mIterNum];\r
+            mHeapBytesAllocated = new long[mIterNum];\r
+            isArt = false;\r
+            //string vmVersion = System.getProperty("java.vm.version");\r
+            //isArt = !string.IsNullOrEmpty(vmVersion) && vmVersion.StartsWith("2");\r
+            //string androidVersion = Build.VERSION.RELEASE;\r
+            //string deviceName = Build.MODEL;\r
+            //string deviceDesc = deviceName + "/" + "android-" + androidVersion + ", runtime: " + (isArt ? "ART" : "Dalvik");\r
+            //mTotalGcCount = info2_1.Index; //GetRuntimeStat("gc.gc-count");\r
+            //mTotalGcTime = (long)info2_1.PauseDurations[0].TotalMilliseconds; //GetRuntimeStat("gc.gc-time");\r
+            //mTotalBlockingGcCount = info1.Index; //GetRuntimeStat("gc.blocking-count");\r
+            //mTotalBlockingGcTime = info1.PauseDurations[0].Milliseconds; //GetRuntimeStat("gc.blocking-gc-time");\r
+            if (isArt)\r
+            {\r
+                mGcCauseCount = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };\r
+            }\r
+            else\r
+            {\r
+                mGcCauseCount = new int[] { 0, 0, 0, 0 };\r
+            }\r
+\r
+            mWorkloadComplete = false;\r
+            //ClearLogcat();\r
+            //Thread logcat = new Thread(new ThreadStart(readLogcat));\r
+            //logcat.Start();\r
+\r
+            mOutOfMemory = false;\r
+            mTestThreads = new BenchThread[mThreadNum];\r
+            for (int i = 1; i < mThreadNum; i++)\r
+            {\r
+                mTestThreads[i] = new BenchThread(i, this);\r
+                //mThreads[i] = new Thread(mTestThreads[i].thread);\r
+                if (i == 1)\r
+                {\r
+                    t1 = new Thread(mTestThreads[i].thread);\r
+                    t1.Start();\r
+                }\r
+                else if (i == 2)\r
+                {\r
+                    t2 = new Thread(mTestThreads[i].thread);\r
+                    t2.Start();\r
+                }\r
+                else if (i == 3)\r
+                {\r
+                    t3 = new Thread(mTestThreads[i].thread);\r
+                    t3.Start();\r
+                }\r
+                Thread.Sleep(100);\r
+            }\r
+\r
+            mElapseTime[0] = 0;\r
+            mStartTime[0] = (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;\r
+            try\r
+            {\r
+                if (!allocTrace(0))\r
+                {\r
+                    Log.Info(mTag, "Error in thread-0");\r
+                }\r
+            }\r
+            catch (OutOfMemoryException e)\r
+            {\r
+                mOutOfMemory = true;\r
+                Log.Info(mTag, "Thread-0 meets OutOfMemory");\r
+\r
+                //Message m = mActivity.GetHandler().ObtainMessage(MainActivity.BenchmarkOutOfMemoryError);\r
+                //m.Arg1 = 0;\r
+                //mActivity.GetHandler().SendMessage(m);\r
+            }\r
+            mEndTime[0] = (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;\r
+            mElapseTime[0] = mEndTime[0] - mStartTime[0];\r
+\r
+            for (int i = 1; i < mThreadNum; i++)\r
+            {\r
+                try\r
+                {\r
+                    //mThreads[i].Join();\r
+                    if (i == 1)\r
+                    {\r
+                        t1.Join();\r
+                    }\r
+                    else if (i == 2)\r
+                    {\r
+                        t2.Join();\r
+                    }\r
+                    else if (i == 3)\r
+                    {\r
+                        t3.Join();\r
+                    }\r
+                    Thread.Sleep(100);\r
+                }\r
+                catch (ThreadInterruptedException e)\r
+                {\r
+                    Log.Info(mTag, "Waiting thread " + i + " finish interrupted by " + e.Message);\r
+                }\r
+            }\r
+            Thread.Sleep(1000);\r
+            mWorkloadComplete = true;\r
+            GC.Collect();\r
+            GC.WaitForPendingFinalizers();\r
+\r
+            try\r
+            {\r
+                //logcat.Join();\r
+            }\r
+            catch (ThreadInterruptedException e)\r
+            {\r
+                Log.Info(mTag, "Waiting logcat finish interrupted by " + e.Message);\r
+            }\r
+            if (mOutOfMemory)\r
+            {\r
+                try\r
+                {\r
+                    if (fileOutput != null)\r
+                    {\r
+                        fileOutput.WriteLine("\nOutOfMemory! Please config profile or " + "Java Runtime and run again!\n");\r
+                        fileOutput.Flush();\r
+                        fileOutput.Close();\r
+                    }\r
+                }\r
+                catch (IOException e)\r
+                {\r
+                    Log.Info(mTag, "Cannot write to /tmp/TizenGCTest-result.txt" + e.Message);\r
+                }\r
+            }\r
+            else\r
+            {\r
+                var info1_2 = GC.GetGCMemoryInfo(GCKind.Ephemeral);\r
+                print1(info1_2);\r
+\r
+                var info2_2 = GC.GetGCMemoryInfo();\r
+                print2(info2_2, info2_1);\r
+\r
+                String pauseDesc = "";\r
+                /*String[] causes;\r
+                if (isArt)\r
+                    causes = GC_CAUSE_ART;\r
+                else\r
+                    causes = GC_CAUSE_DALVIK;\r
+                for (int i = 0; i < causes.Length; i++)\r
+                {\r
+                    Log.Info(mTag, mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat");\r
+                    gcDesc += "\n" + mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat";\r
+                }*/\r
+                /*for (int i = 0; i < mGcPauseTime.Length; i++)\r
+                {\r
+                    String gc_time = "GC-" + i + ": " + mGcCause[i] + ", pause "\r
+                            + mGcPauseTime[i] + "ms, total " + mGcTotalTime[i] + "ms";\r
+                    pauseDesc += "\n" + gc_time;\r
+                    Log.Info(mTag, gc_time);\r
+                }*/\r
+                try\r
+                {\r
+                    if (fileOutput != null)\r
+                    {\r
+                        //fileOutput.WriteLine("\nDevice config:\n\t" + deviceDesc);\r
+                        fileOutput.WriteLine("\nDevice config:\n\t");\r
+                        //fileOutput.WriteLine(completionTime);\r
+                        fileOutput.WriteLine("Heap status after each iteration (footprint, bytes allocated):\n");\r
+                        for (int j = 0; j < mIterNum; j++)\r
+                        {\r
+                            fileOutput.WriteLine("\t" + mHeapFootprint[j] + " kB, " + mHeapBytesAllocated[j] + " kB");\r
+                        }\r
+                        //fileOutput.WriteLine(gcDesc);\r
+                        fileOutput.WriteLine(pauseDesc);\r
+                        fileOutput.Flush();\r
+                        fileOutput.Close();\r
+                    }\r
+                }\r
+                catch (IOException e)\r
+                {\r
+                    Log.Info(mTag, "Cannot write to /tmp/TizenGCTest-result.txt " + e.Message);\r
+                }\r
+                /*if (mActivity != null)\r
+                {\r
+                    Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkDone);\r
+                    Bundle b = new Bundle();\r
+                    b.putBoolean(ResultActivity.KEY_VM_TYPE, isArt);\r
+                    b.putString("device", deviceDesc);\r
+                    b.putLongArray(ResultActivity.KEY_THREAD_COMPLETE_TIME, mElapseTime);\r
+                    b.putLong(ResultActivity.KEY_WORKLOAD_COMPLETE_TIME, maxTime);\r
+                    b.putLongArray(ResultActivity.KEY_BYTES_LIVING, mHeapBytesAllocated);\r
+                    b.putIntArray(ResultActivity.KEY_HEAP_FOOTPRINT, mHeapFootprint);\r
+                    b.putFloatArray(ResultActivity.KEY_GC_PAUSE_TIME, mGcPauseTime);\r
+                    b.putFloatArray(ResultActivity.KEY_GC_COMPLETION_TIME, mGcTotalTime);\r
+                    b.putStringArray(ResultActivity.KEY_GC_CAUSE, mGcCause);\r
+                    m.setData(b);\r
+                    mActivity.getHandler().sendMessage(m);\r
+                }*/\r
+            }\r
+            mElapseTime = null;\r
+            mHeapFootprint = null;\r
+            mHeapBytesAllocated = null;\r
+            mGcPauseTime = null;\r
+            mGcTotalTime = null;\r
+            mGcCause = null;\r
+\r
+            clearInitData();\r
+        }\r
+\r
+        private void print1(GCMemoryInfo info2)\r
+        {\r
+            mTotalGcCount = info2.Index; //GetRuntimeStat("gc.gc-count") - mTotalGcCount;\r
+            mTotalGcTime = (long)info2.PauseDurations[0].TotalMilliseconds; //GetRuntimeStat("gc.gc-time") - mTotalGcTime;\r
+                                                                            //mTotalBlockingGcCount = GetRuntimeStat("gc.blocking-gc-count") - mTotalBlockingGcCount;\r
+                                                                            //mTotalBlockingGcTime = info2.PauseDurations[0].Milliseconds - info1.PauseDurations[0].Milliseconds; //GetRuntimeStat("gc.blocking-gc-time") - mTotalBlockingGcTime;\r
+            print(info2);\r
+        }\r
+        private void print2(GCMemoryInfo info2, GCMemoryInfo info1)\r
+        {\r
+            mTotalGcCount = info2.Index - info1.Index; //GetRuntimeStat("gc.gc-count") - mTotalGcCount;\r
+            mTotalGcTime = (long)info2.PauseDurations[0].TotalMilliseconds - (long)info1.PauseDurations[0].TotalMilliseconds; //GetRuntimeStat("gc.gc-time") - mTotalGcTime;\r
+                                                                                                                              //mTotalBlockingGcCount = GetRuntimeStat("gc.blocking-gc-count") - mTotalBlockingGcCount;\r
+                                                                                                                              //mTotalBlockingGcTime = info2.PauseDurations[0].Milliseconds - info1.PauseDurations[0].Milliseconds; //GetRuntimeStat("gc.blocking-gc-time") - mTotalBlockingGcTime;\r
+            print(info2);\r
+        }\r
+\r
+        private void print(GCMemoryInfo info2)\r
+        {\r
+            long maxTime = 0;\r
+            //string completionTime = "";\r
+            for (int i = 0; i < mThreadNum; i++)\r
+            {\r
+                if (maxTime < mElapseTime[i])\r
+                {\r
+                    maxTime = mElapseTime[i];\r
+                }\r
+                Log.Info(mTag, "Thread-" + i + " completion time: " + mElapseTime[i].ToString() + "ms");\r
+                //completionTime += "Thread-" + i + " completion time: " + mElapseTime[i].ToString() + "ms\n";\r
+            }\r
+\r
+            String totalTime = "TizenGCTest is done by " + mThreadNum\r
+                    + " threads. Completion time is " + maxTime + "ms";\r
+            Log.Info(mTag, totalTime);\r
+            //completionTime += totalTime + "\n";\r
+            //String gcDesc = "Total GC count: " + mTotalGcCount;\r
+            //gcDesc += "\nTotal GC time: " + mTotalGcTime + "ms";\r
+            //gcDesc += "\nTotal Blocking GC count: " + mTotalBlockingGcCount;\r
+            //gcDesc += "\nTotal Blocking GC time: " + mTotalBlockingGcTime + "ms";\r
+            Log.Info(mTag, "Total GC count: " + mTotalGcCount);\r
+            Log.Info(mTag, "Total GC time: " + mTotalGcTime + "ms");\r
+            //Log.Info(mTag, "Total Blocking GC count: " + mTotalBlockingGcCount);\r
+            //Log.Info(mTag, "Total Blocking GC time: " + mTotalBlockingGcTime + "ms");\r
+\r
+            long totalAfter = 0;\r
+            long totalBefore = 0;\r
+            foreach (var ginfo in info2.GenerationInfo)\r
+            {\r
+                totalAfter += ginfo.SizeAfterBytes;\r
+                totalBefore += ginfo.SizeBeforeBytes;\r
+            }\r
+            Log.Info(mTag, "HeapSizeBytes: " + info2.HeapSizeBytes + ", " + GC.GetTotalMemory(false) + " / GenInfo After : " + totalAfter + ", Before : " + totalBefore);\r
+            Log.Info(mTag, "TotalCommittedBytes: " + info2.TotalCommittedBytes);\r
+            Log.Info(mTag, "Generation: " + info2.Generation);\r
+            Log.Info(mTag, "TotalAvailableMemoryBytes: " + info2.TotalAvailableMemoryBytes);\r
+            Log.Info(mTag, "FinalizationPendingCount: " + info2.FinalizationPendingCount);\r
+            Log.Info(mTag, "Concurrent: " + info2.Concurrent);\r
+            Log.Info(mTag, "Compacted: " + info2.Compacted);\r
+            Log.Info(mTag, "Index: " + info2.Index);\r
+            Log.Info(mTag, "FragmentedBytes: " + info2.FragmentedBytes);\r
+            Log.Info(mTag, "HighMemoryLoadThresholdBytes: " + info2.HighMemoryLoadThresholdBytes);\r
+            Log.Info(mTag, "MemoryLoadBytes: " + info2.MemoryLoadBytes);\r
+        }\r
+\r
+        public void stop()\r
+        {\r
+        }\r
+\r
+        private void ClearLogcat()\r
+        {\r
+            try\r
+            {\r
+                Process process = Process.Start(new ProcessStartInfo("dlogutil", "-c"));\r
+                try\r
+                {\r
+                    process.WaitForExit();\r
+                }\r
+                catch (ThreadInterruptedException e)\r
+                {\r
+                    Log.Error(mTag, "Clear logcat fails, interrupted by " + e.Message);\r
+                }\r
+                Log.Info(mTag, "Clear logcat before workload running");\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                Log.Error(mTag, "Clear logcat fails, " + e.Message);\r
+            }\r
+        }\r
+\r
+        private void readLogcat()\r
+        {\r
+            string cmd = "dlogutil TizenGCTest STDOUT STDERR";\r
+            List<float> gcPauseTimeList = new List<float>();\r
+            List<float> gcTotalTimeList = new List<float>();\r
+            List<string> gcCauseList = new List<string>();\r
+            int loggerGcCount = 0;\r
+            try\r
+            {\r
+                Process process = Process.Start(new ProcessStartInfo("cmd", "/c " + cmd) { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false });\r
+                Stream inStream = process.StandardOutput.BaseStream;\r
+                Stream errorStream = process.StandardError.BaseStream;\r
+                int error = errorStream.ReadByte();\r
+                if (error > 0)\r
+                {\r
+                    byte[] errorMsg = new byte[error];\r
+                    errorStream.Read(errorMsg, 0, error);\r
+                    Log.Info(mTag, "executing logcat return error message: " + Encoding.UTF8.GetString(errorMsg));\r
+                }\r
+                StreamReader inReader = new StreamReader(inStream);\r
+                string line;\r
+                while (!mWorkloadComplete && (line = inReader.ReadLine()) != null)\r
+                {\r
+                    if (mWorkloadComplete)\r
+                        break;\r
+\r
+                    int idx = line.IndexOf(": ");\r
+                    if (idx == -1)\r
+                        continue;\r
+                    line = line.Substring(idx + 2);\r
+                    bool isGCLog = false;\r
+                    String gcCause = "";\r
+                    if (isArt)\r
+                    {\r
+                        for (int i = 0; i < GC_CAUSE_ART.Length; i++)\r
+                        {\r
+                            if ((line.Contains("mark sweep") || line.Contains("marksweep")\r
+                                    || line.Contains("mark compact"))\r
+                                    && line.StartsWith(GC_CAUSE_ART[i]))\r
+                            {\r
+                                isGCLog = true;\r
+                                mGcCauseCount[i]++;\r
+                                idx = line.IndexOf(" GC ");\r
+                                if (idx > 0)\r
+                                    gcCause = line.Substring(0, idx);\r
+                                else\r
+                                {\r
+                                    Log.Info(mTag, "Error: cannot find ' GC ' from this log, " + line);\r
+                                    continue;\r
+                                }\r
+                                break;\r
+                            }\r
+                        }\r
+                    }\r
+                    else\r
+                    {\r
+                        for (int i = 0; i < GC_CAUSE_DALVIK.Length; i++)\r
+                        {\r
+                            if (line.StartsWith(GC_CAUSE_DALVIK[i]))\r
+                            {\r
+                                isGCLog = true;\r
+                                mGcCauseCount[i]++;\r
+                                gcCause = GC_CAUSE_DALVIK[i];\r
+                                break;\r
+                            }\r
+                        }\r
+                    }\r
+                    if (!isGCLog)\r
+                        continue;\r
+                    loggerGcCount++;\r
+\r
+                    int idx0 = line.IndexOf("paused ");\r
+                    int idx1 = line.IndexOf(" total ");\r
+                    if (idx0 == -1 || idx1 == -1)\r
+                    {\r
+                        Log.Info(mTag, "Cannot find pause or total completion time from the GC log "\r
+                                + line);\r
+                        continue;\r
+                    }\r
+\r
+                    String pauseTimeStr = line.Substring(idx0 + 7, idx1);\r
+                    String totalTimeStr = line.Substring(idx1 + 7);\r
+                    float completeTime = 0.0f;\r
+                    float pauseTime = 0.0f;\r
+                    idx = totalTimeStr.IndexOf("ms");\r
+                    int timeToSec = 1000;\r
+                    if (idx == -1)\r
+                    {\r
+                        idx = totalTimeStr.IndexOf("us");\r
+                        timeToSec = 1000000;\r
+                    }\r
+                    if (idx == -1)\r
+                    {\r
+                        idx = totalTimeStr.IndexOf("s");\r
+                        timeToSec = 1;\r
+                    }\r
+                    if (idx == -1)\r
+                    {\r
+                        Log.Info(mTag, "Cannot identify total complete time format, " + line);\r
+                        continue;\r
+                    }\r
+                    completeTime = float.Parse(totalTimeStr.Substring(0, idx)) * 1000 / timeToSec;\r
+                    string[] pauseTimes = pauseTimeStr.Split(new string[] { "+ ", ", " }, StringSplitOptions.RemoveEmptyEntries);\r
+                    for (int i = 0; i < pauseTimes.Length; i++)\r
+                    {\r
+                        string tmp = pauseTimes[i];\r
+                        idx = tmp.IndexOf("ms");\r
+                        if (idx > 0)\r
+                        {\r
+                            pauseTime += float.Parse(tmp.Substring(0, idx));\r
+                        }\r
+                        else\r
+                        {\r
+                            idx = tmp.IndexOf("us");\r
+                            if (idx > 0)\r
+                            {\r
+                                pauseTime += float.Parse(tmp.Substring(0, idx)) / 1000;\r
+                            }\r
+                            else\r
+                            {\r
+                                Log.Info(mTag, "Cannot identify pause time format, " + line);\r
+                                continue;\r
+                            }\r
+                        }\r
+                    }\r
+                    gcPauseTimeList.Add(pauseTime);\r
+                    gcTotalTimeList.Add(completeTime);\r
+                    gcCauseList.Add(gcCause);\r
+                }\r
+                errorStream.Close();\r
+                inReader.Close();\r
+                process.Kill();\r
+                Log.Info(mTag, "workload complete, stop reading logcat");\r
+                mGcTotalTime = new float[loggerGcCount];\r
+                mGcPauseTime = new float[loggerGcCount];\r
+                mGcCause = new String[loggerGcCount];\r
+                for (int i = 0; i < gcPauseTimeList.Count; i++)\r
+                {\r
+                    mGcTotalTime[i] = gcTotalTimeList[i];\r
+                    mGcPauseTime[i] = gcPauseTimeList[i];\r
+                    mGcCause[i] = gcCauseList[i];\r
+                }\r
+            }\r
+            catch (OutOfMemoryException e)\r
+            {\r
+                mOutOfMemory = true;\r
+                Log.Info(mTag, "logcat thread meets OutOfMemory");\r
+                //Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkOutOfMemoryError);\r
+                //m.arg1 = -1;\r
+                //mActivity.getHandler().sendMessage(m);\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                Log.Info(mTag, "Cannot run logcat " + e.Message);\r
+            }\r
+            gcPauseTimeList.Clear();\r
+            gcPauseTimeList = null;\r
+            gcTotalTimeList.Clear();\r
+            gcTotalTimeList = null;\r
+            gcCauseList.Clear();\r
+            gcCauseList = null;\r
+            Log.Info(mTag, "logcat done");\r
+        }\r
+\r
+        //private static MethodInfo getRuntimeStatMethod = null;\r
+        /*private long GetRuntimeStat(string statName)\r
+        {\r
+            if (getRuntimeStatMethod == null)\r
+            {\r
+                return 0;\r
+            }\r
+            string valueStr;\r
+            try\r
+            {\r
+                valueStr = (string)getRuntimeStatMethod.Invoke(null, new object[] { statName });\r
+            }\r
+            catch (Exception e)\r
+            {\r
+                Log.Warn(mTag, "Failed to invoke GetRuntimeStat");\r
+                return 0;\r
+            }\r
+            if (valueStr != null)\r
+            {\r
+                return long.Parse(valueStr);\r
+            }\r
+            return 0;\r
+        }*/\r
+    }\r
+}\r
diff --git a/tests/GC/TizenGCTest/Profile.cs b/tests/GC/TizenGCTest/Profile.cs
new file mode 100755 (executable)
index 0000000..70b4746
--- /dev/null
@@ -0,0 +1,383 @@
+using System;\r
+using System.Collections;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Xml;\r
+using Tizen.Content.MediaContent;\r
+using Tizen;\r
+using static Tizen.NUI.Shader;\r
+using static TizenGCTest.Profile;\r
+using System.Xml.Linq;\r
+using System.Text.RegularExpressions;\r
+using Tizen.Pims.Contacts.ContactsViews;\r
+using static Tizen.Applications.ApplicationInfoFilter;\r
+\r
+namespace TizenGCTest\r
+{\r
+    public class Profile\r
+    {\r
+        private const String mTag = "TizenGCTest";\r
+        public class ProfileData\r
+        {\r
+            private int mId;\r
+            private string mName;\r
+            private int mTotalSize;\r
+            private int mBucketSize;\r
+            private int mLosThreshold;\r
+            private float[] mSizeDist;\r
+            private float[] mLosElementDist;\r
+            private float[][] mLifetime;\r
+            private float[] mLifetime2;\r
+            private bool mThreadMode;\r
+            private int mThreadNum;\r
+            private int mIterationNum;\r
+\r
+            public ProfileData(int id, string name)\r
+            {\r
+                mId = id;\r
+                mName = name;\r
+            }\r
+\r
+            public int GetId()\r
+            {\r
+                return mId;\r
+            }\r
+\r
+            public string GetName()\r
+            {\r
+                return mName;\r
+            }\r
+\r
+            public int GetTotalSize()\r
+            {\r
+                return mTotalSize;\r
+            }\r
+\r
+            public int GetBucketSize()\r
+            {\r
+                return mBucketSize;\r
+            }\r
+\r
+            public int GetLosThreshold()\r
+            {\r
+                return mLosThreshold;\r
+            }\r
+\r
+            public float[] GetSizeDistribution()\r
+            {\r
+                return mSizeDist;\r
+            }\r
+\r
+            public float[] GetLosElementDist()\r
+            {\r
+                return mLosElementDist;\r
+            }\r
+\r
+            public float[][] GetLifetime()\r
+            {\r
+                return mLifetime;\r
+            }\r
+\r
+            public float[] GetLifetime2()\r
+            {\r
+                return mLifetime2;\r
+            }\r
+\r
+            public bool GetThreadMode()\r
+            {\r
+                return mThreadMode;\r
+            }\r
+\r
+            public int GetThreadNum()\r
+            {\r
+                return mThreadMode ? 1 : mThreadNum;\r
+            }\r
+\r
+            public int GetIterationNum()\r
+            {\r
+                return mIterationNum;\r
+            }\r
+\r
+            public void SetName(string name)\r
+            {\r
+                mName = name;\r
+            }\r
+\r
+            public void SetTotalSize(int totalSize)\r
+            {\r
+                mTotalSize = totalSize;\r
+            }\r
+\r
+            public void SetBucketSize(int bucketSize)\r
+            {\r
+                mBucketSize = bucketSize;\r
+            }\r
+\r
+            public void SetLosThreshold(int losThreshold)\r
+            {\r
+                mLosThreshold = losThreshold;\r
+            }\r
+\r
+            public void SetSizeDistribution(float[] sizeDist)\r
+            {\r
+                mSizeDist = sizeDist;\r
+            }\r
+\r
+            public void SetLosElementDist(float[] losElementDist)\r
+            {\r
+                mLosElementDist = losElementDist;\r
+            }\r
+\r
+            public void SetLifetime(float[][] lifetime)\r
+            {\r
+                mLifetime = lifetime;\r
+            }\r
+\r
+            public void SetLifetime2(float[] lifetime)\r
+            {\r
+                mLifetime2 = lifetime;\r
+            }\r
+\r
+            public void SetThreadMode(bool singleThread)\r
+            {\r
+                mThreadMode = singleThread;\r
+            }\r
+\r
+            public void SetThreadNum(int threadNum)\r
+            {\r
+                mThreadNum = mThreadMode ? 1 : threadNum;\r
+            }\r
+\r
+            public void SetIterationNum(int iterationNum)\r
+            {\r
+                mIterationNum = iterationNum;\r
+            }\r
+        }\r
+\r
+        private static Profile instance_ = null;\r
+        public bool mInit = false;\r
+        int mCurrentProfileId = -1;\r
+        public List<ProfileData> mData = null;\r
+\r
+        private Profile()\r
+        {\r
+            mCurrentProfileId = -1;\r
+            mInit = false;\r
+        }\r
+\r
+        public static Profile getInstance()\r
+        {\r
+            if (instance_ == null)\r
+            {\r
+                instance_ = new Profile();\r
+            }\r
+            return instance_;\r
+        }\r
+\r
+        private bool InitProfileData(String input)\r
+        {\r
+            ProfileData newProfile = null;\r
+            XmlReaderSettings settings = new XmlReaderSettings();\r
+            settings.DtdProcessing = DtdProcessing.Parse;\r
+            XmlReader parser = XmlReader.Create(input, settings);\r
+\r
+            try\r
+            {\r
+                float[] floatValues = null;\r
+                string itemName, name;\r
+                int idx0 = -1, idx1 = 0;\r
+                while (parser.Read())\r
+                {\r
+                    switch (parser.NodeType)\r
+                    {\r
+                        case XmlNodeType.Element:\r
+\r
+                            name = parser.Name;\r
+                            if (name.Equals("profile"))\r
+                            {\r
+                                newProfile = new ProfileData(int.Parse(parser.GetAttribute(0)), parser.GetAttribute(1));\r
+                                //Log.Info(mTag, "profile : " + parser.GetAttribute(0) + " " + parser.GetAttribute(1));\r
+                            }\r
+                            else if (name.Equals("item"))\r
+                            {\r
+                                itemName = parser.GetAttribute(0);\r
+                                if (itemName.Equals("total_size"))\r
+                                {\r
+                                    newProfile.SetTotalSize(int.Parse(parser.ReadElementContentAsString()));\r
+                                    //Log.Info(mTag, "item - total_size : " + newProfile.GetTotalSize());\r
+                                }\r
+                                else if (itemName.Equals("bucket_size"))\r
+                                {\r
+                                    newProfile.SetBucketSize(int.Parse(parser.ReadElementContentAsString()));\r
+                                    //Log.Info(mTag, "item - bucket_size : " + newProfile.GetBucketSize());\r
+                                }\r
+                                else if (itemName.Equals("los_threshold"))\r
+                                {\r
+                                    newProfile.SetLosThreshold(int.Parse(parser.ReadElementContentAsString()));\r
+                                    //Log.Info(mTag, "item - los_threshold : " + newProfile.GetLosThreshold());\r
+                                }\r
+                                else if (itemName.Equals("thread-mode"))\r
+                                {\r
+                                    newProfile.SetThreadMode(int.Parse(parser.ReadElementContentAsString()) == 1);\r
+                                    //Log.Info(mTag, "item - thread-mode : " + newProfile.GetThreadMode());\r
+                                }\r
+                                else if (itemName.Equals("thread-num"))\r
+                                {\r
+                                    newProfile.SetThreadNum(int.Parse(parser.ReadElementContentAsString()));\r
+                                    //Log.Info(mTag, "item - thread-num : " + newProfile.GetThreadNum());\r
+                                }\r
+                                else if (itemName.Equals("iteration-times"))\r
+                                {\r
+                                    newProfile.SetIterationNum(int.Parse(parser.ReadElementContentAsString()));\r
+                                    //Log.Info(mTag, "item - iteration-times : " + newProfile.GetIterationNum());\r
+                                }\r
+                            }\r
+                            else if (name.Equals("float-array-2d"))\r
+                            {\r
+                                if (parser.GetAttribute(0).Equals("lifetime"))\r
+                                {\r
+                                    newProfile.SetLifetime(new float[int.Parse(parser.GetAttribute(1))][]);\r
+                                    idx0 = 0;\r
+                                    //Log.Info(mTag, "float-array-2d - lifetime : " + parser.GetAttribute(1));\r
+                                }\r
+                            }\r
+                            else if (name.Equals("float-array"))\r
+                            {\r
+                                itemName = parser.GetAttribute(0);\r
+                                if (itemName.Equals("size_dist"))\r
+                                {\r
+                                    newProfile.SetSizeDistribution(new float[int.Parse(parser.GetAttribute(1))]);\r
+                                    floatValues = newProfile.GetSizeDistribution();\r
+                                    //Log.Info(mTag, "float-array - size_dist : " + floatValues.Length);\r
+                                }\r
+                                else if (itemName.Equals("los_element_dist"))\r
+                                {\r
+                                    newProfile.SetLosElementDist(new float[int.Parse(parser.GetAttribute(1))]);\r
+                                    floatValues = newProfile.GetLosElementDist();\r
+                                    //Log.Info(mTag, "float-array - los_element_dist : " + floatValues.Length);\r
+                                }\r
+                                else if (idx0 >= 0)\r
+                                {\r
+                                    float[][] lifetime = null;\r
+                                    lifetime = new float[int.Parse(parser.GetAttribute(1))][];\r
+                                    newProfile.SetLifetime(lifetime);\r
+                                    //floatValues = newProfile.GetLifetime()[idx0];\r
+                                    //Log.Info(mTag, "float-array - size_dist : " + floatValues.Length);\r
+\r
+                                    float[] lifetime2 = null;\r
+                                    lifetime2 = new float[int.Parse(parser.GetAttribute(1))];\r
+                                    newProfile.SetLifetime2(lifetime2);\r
+                                    floatValues = newProfile.GetLifetime2();\r
+                                    idx0++;\r
+                                }\r
+                                idx1 = 0;\r
+                            }\r
+                            else if (name.Equals("value"))\r
+                            {\r
+                                if (floatValues == null)\r
+                                {\r
+                                    Log.Info(mTag, "error in parsing profile.xml");\r
+                                    return false;\r
+                                }\r
+                                floatValues[idx1++] = float.Parse(parser.ReadElementContentAsString());\r
+                                //foreach (var value in floatValues)\r
+                                    //if (value != 0)\r
+                                        //Log.Info(mTag, "value : " + value);\r
+                            }\r
+                            break;\r
+                        case XmlNodeType.EndElement:\r
+                            name = parser.Name;\r
+                            if (name.Equals("profile"))\r
+                            {\r
+                                mData = new List<ProfileData>\r
+                                {\r
+                                    newProfile\r
+                                };\r
+                            }\r
+                            else if (name.Equals("float-array-2d"))\r
+                            {\r
+                                idx0 = -1;\r
+                            }\r
+                            break;\r
+                        default:\r
+                            break;\r
+                    }\r
+                }\r
+            }\r
+            catch (XmlException e)\r
+            {\r
+                Log.Error(mTag, e.StackTrace);\r
+                return false;\r
+            }\r
+            catch (FormatException e)\r
+            {\r
+                Log.Error(mTag, e.StackTrace);\r
+                return false;\r
+            }\r
+            catch (IOException e)\r
+            {\r
+                Log.Error(mTag, e.StackTrace);\r
+                return false;\r
+            }\r
+\r
+            return true;\r
+        }\r
+\r
+        public ProfileData GetProfile(string name)\r
+        {\r
+            if (!mInit)\r
+                return null;\r
+            for (int i = 0; i < mData.Count; i++)\r
+            {\r
+                ProfileData data = mData[i];\r
+                if (data.GetName() == name)\r
+                {\r
+                    mCurrentProfileId = data.GetId();\r
+                    return data;\r
+                }\r
+            }\r
+            return null;\r
+        }\r
+\r
+        public bool ParseProfileData(String rawProfileFile)\r
+        {\r
+            mInit = InitProfileData(rawProfileFile);\r
+            return mInit;\r
+        }\r
+\r
+        public bool Initialized()\r
+        {\r
+            return mInit;\r
+        }\r
+\r
+        public void SetCurrentProfileData(string name)\r
+        {\r
+            if (!mInit)\r
+                return;\r
+            for (int i = 0; i < mData.Count; i++)\r
+            {\r
+                ProfileData data = mData[i];\r
+                if (data.GetName() == name)\r
+                {\r
+                    mCurrentProfileId = data.GetId();\r
+                    break;\r
+                }\r
+            }\r
+        }\r
+\r
+        public ProfileData GetCurrentProfileData()\r
+        {\r
+            if (!mInit)\r
+                return null;\r
+            for (int i = 0; i < mData.Count; i++) {\r
+                ProfileData data = mData[i];\r
+                if (mData[i].GetId() == mCurrentProfileId)\r
+                    return data;\r
+            }\r
+            return null;\r
+        }\r
+    }\r
+}\r
diff --git a/tests/GC/TizenGCTest/TizenGCTest.cs b/tests/GC/TizenGCTest/TizenGCTest.cs
new file mode 100755 (executable)
index 0000000..be17056
--- /dev/null
@@ -0,0 +1,100 @@
+using System;\r
+using System.Threading;\r
+using Tizen;\r
+using Tizen.NUI;\r
+using Tizen.NUI.Components;\r
+using Tizen.NUI.BaseComponents;\r
+using static TizenGCTest.Profile;\r
+\r
+namespace TizenGCTest\r
+{\r
+    class Program : NUIApplication\r
+    {\r
+        private const String mTag = "TizenGCTest";\r
+        private Profile mProfile = null;\r
+\r
+        protected override void OnCreate()\r
+        {\r
+            base.OnCreate();\r
+            Initialize();\r
+\r
+            mProfile = Profile.getInstance();\r
+\r
+            mProfile.ParseProfileData("/opt/usr/globalapps/org.tizen.example.TizenGCTest/res/profile.xml");\r
+\r
+            if (mProfile.Initialized())\r
+            {\r
+                string[] names = new string[mProfile.mData.Count];\r
+                for (int i = 0; i < mProfile.mData.Count; i++)\r
+                {\r
+                    ProfileData d = mProfile.mData[i];\r
+                    names[i] = d.GetName();\r
+                }\r
+                mProfile.SetCurrentProfileData("default");\r
+            }\r
+            else\r
+            {\r
+                Log.Info(mTag, "Cannot get profile data");\r
+            }\r
+\r
+            Log.Info(mTag, "TizenGCTest Start!!");\r
+            StartGC();\r
+        }\r
+\r
+\r
+        public void StartGC()\r
+        {\r
+            ProfileData profileData = mProfile.GetCurrentProfileData();\r
+            if (profileData == null)\r
+            {\r
+                Log.Error(mTag, "no profile data?!");\r
+                return;\r
+            }\r
+            GCTest gctest = new GCTest(profileData.GetTotalSize(), profileData.GetBucketSize(),\r
+                                       profileData.GetLosThreshold(), profileData.GetSizeDistribution(),\r
+                                       profileData.GetLifetime(), profileData.GetLosElementDist(),\r
+                                       profileData.GetThreadMode(), profileData.GetThreadNum(),\r
+                                       profileData.GetIterationNum());\r
+\r
+            GC.Collect();\r
+            GC.WaitForPendingFinalizers();\r
+\r
+            //var mRunning = true;\r
+            var worker = new Thread(() =>\r
+            {\r
+                gctest.start();\r
+            });\r
+            worker.Start();\r
+\r
+        }\r
+\r
+        void Initialize()\r
+        {\r
+            Window.Instance.KeyEvent += OnKeyEvent;\r
+\r
+            TextLabel text = new TextLabel("Hello Tizen NUI World");\r
+            text.HorizontalAlignment = HorizontalAlignment.Center;\r
+            text.VerticalAlignment = VerticalAlignment.Center;\r
+            text.TextColor = Color.Blue;\r
+            text.PointSize = 12.0f;\r
+            text.HeightResizePolicy = ResizePolicyType.FillToParent;\r
+            text.WidthResizePolicy = ResizePolicyType.FillToParent;\r
+            Window.Instance.GetDefaultLayer().Add(text);\r
+            \r
+        }\r
+\r
+        public void OnKeyEvent(object sender, Window.KeyEventArgs e)\r
+        {\r
+            if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))\r
+            {\r
+                Exit();\r
+            }\r
+        }\r
+\r
+        static void Main(string[] args)\r
+        {\r
+            var app = new Program();\r
+            app.Run(args);\r
+        }\r
+    }\r
+}\r
diff --git a/tests/GC/TizenGCTest/TizenGCTest.csproj b/tests/GC/TizenGCTest/TizenGCTest.csproj
new file mode 100755 (executable)
index 0000000..afab7fc
--- /dev/null
@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+  <PropertyGroup>\r
+    <OutputType>Exe</OutputType>\r
+    <TargetFramework>net6.0-tizen</TargetFramework>\r
+  </PropertyGroup>\r
+\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+    <DebugType>portable</DebugType>\r
+  </PropertyGroup>\r
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+    <DebugType>None</DebugType>\r
+  </PropertyGroup>\r
+  <ItemGroup>\r
+    <Content Include="res\profile.xml" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Folder Include="lib\" />\r
+  </ItemGroup>\r
+\r
+</Project>\r
diff --git a/tests/GC/TizenGCTest/res/profile.xml b/tests/GC/TizenGCTest/res/profile.xml
new file mode 100755 (executable)
index 0000000..9effe2c
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<profile id="0" name="default">\r
+  <item name="total_size">100</item>\r
+  <item name="bucket_size">1</item>\r
+  <item name="los_threshold">12</item>\r
+  <float-array name="size_dist" count="7">\r
+    <value>0.0436</value>\r
+    <value>0.5465</value>\r
+    <value>0.2103</value>\r
+    <value>0.1499</value>\r
+    <value>0.0275</value>\r
+    <value>0.0125</value>\r
+    <value>0.0097</value>\r
+  </float-array>\r
+  <float-array-2d name="lifetime" count="7">\r
+    <float-array name="16b" count="4">\r
+      <value>0.0865</value>\r
+      <value>0.5404</value>\r
+      <value>0.2887</value>\r
+      <value>0.0865</value>\r
+    </float-array>\r
+    <float-array name="32b" count="4">\r
+      <value>0.0469</value>\r
+      <value>0.7724</value>\r
+      <value>0.1460</value>\r
+      <value>0.0346</value>\r
+    </float-array>\r
+    <float-array name="64b" count="4">\r
+      <value>0.1154</value>\r
+      <value>0.5982</value>\r
+      <value>0.1880</value>\r
+      <value>0.0984</value>\r
+    </float-array>\r
+    <float-array name="128b" count="4">\r
+      <value>0.0662</value>\r
+      <value>0.7851</value>\r
+      <value>0.1077</value>\r
+      <value>0.0411</value>\r
+    </float-array>\r
+    <float-array name="256b" count="4">\r
+      <value>0.0520</value>\r
+      <value>0.8778</value>\r
+      <value>0.0503</value>\r
+      <value>0.0198</value>\r
+    </float-array>\r
+    <float-array name="512b" count="4">\r
+      <value>0.1628</value>\r
+      <value>0.7137</value>\r
+      <value>0.0821</value>\r
+      <value>0.0414</value>\r
+    </float-array>\r
+    <float-array name="los" count="4">\r
+      <value>0.0923</value>\r
+      <value>0.7117</value>\r
+      <value>0.1769</value>\r
+      <value>0.0192</value>\r
+    </float-array>\r
+  </float-array-2d>\r
+  <float-array name="los_element_dist" count="4">\r
+    <value>0.90</value>\r
+    <value>0.07</value>\r
+    <value>0.02</value>\r
+    <value>0.01</value>\r
+  </float-array>\r
+  <item name="thread-mode">0</item>\r
+  <item name="thread-num">0</item>\r
+  <item name="iteration-times">10</item>\r
+</profile>\r
diff --git a/tests/GC/TizenGCTest/shared/res/TizenGCTest.png b/tests/GC/TizenGCTest/shared/res/TizenGCTest.png
new file mode 100755 (executable)
index 0000000..9f3cb98
Binary files /dev/null and b/tests/GC/TizenGCTest/shared/res/TizenGCTest.png differ
diff --git a/tests/GC/TizenGCTest/tizen-manifest.xml b/tests/GC/TizenGCTest/tizen-manifest.xml
new file mode 100755 (executable)
index 0000000..beed128
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="9.0" package="org.tizen.example.TizenGCTest" version="1.0.0">
+  <profile name="common" />
+  <ui-application appid="org.tizen.example.TizenGCTest"
+                                       exec="TizenGCTest.dll"
+                                       type="dotnet-nui"
+                                       multiple="false"
+                                       taskmanage="true"
+                                       nodisplay="false"
+                                       launch_mode="single"
+                    api-version="12">
+    <label>TizenGCTest</label>
+    <icon>TizenGCTest.png</icon>
+    <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+  </ui-application>
+</manifest>
diff --git a/tests/GC/TizenGCTest/tizen_dotnet_project.yaml b/tests/GC/TizenGCTest/tizen_dotnet_project.yaml
new file mode 100755 (executable)
index 0000000..556e0f2
--- /dev/null
@@ -0,0 +1,9 @@
+# csproj file path
+csproj_file: TizenGCTest.csproj
+
+# files monitored for dirty/modified status
+files:
+  - TizenGCTest.csproj
+  - TizenGCTest.cs
+  - tizen-manifest.xml
+  - shared/res/TizenGCTest.png
\ No newline at end of file