diff --git a/native/jni/Android.mk b/native/jni/Android.mk
index c99f291d0b244362f751df91184b755d365234b0..75f85b1205a1ef3fe8947e27c2d71eef42c98bae 100644
--- a/native/jni/Android.mk
+++ b/native/jni/Android.mk
@@ -66,11 +66,15 @@ LOCAL_SRC_FILES := \
 
 ifeq ($(FLAG_DO_PROFILE), true)
     $(warning Making profiling version of native library)
-    LOCAL_CFLAGS += -DFLAG_DO_PROFILE
+    LOCAL_CFLAGS += -DFLAG_DO_PROFILE -funwind-tables
 else # FLAG_DO_PROFILE
 ifeq ($(FLAG_DBG), true)
     $(warning Making debug version of native library)
-    LOCAL_CFLAGS += -DFLAG_DBG
+    LOCAL_CFLAGS += -DFLAG_DBG -funwind-tables
+ifeq ($(FLAG_FULL_DBG), true)
+    $(warning Making full debug version of native library)
+    LOCAL_CFLAGS += -DFLAG_FULL_DBG
+endif # FLAG_FULL_DBG
 endif # FLAG_DBG
 endif # FLAG_DO_PROFILE
 
diff --git a/native/jni/jni_common.cpp b/native/jni/jni_common.cpp
index 7b97cf4db0d729ea986ce35a6795ab8cd4dd996a..1ea204102a8a3acef4358d738e2be2358acfef12 100644
--- a/native/jni/jni_common.cpp
+++ b/native/jni/jni_common.cpp
@@ -16,8 +16,6 @@
 
 #define LOG_TAG "LatinIME: jni"
 
-#include <cassert>
-
 #include "com_android_inputmethod_keyboard_ProximityInfo.h"
 #include "com_android_inputmethod_latin_BinaryDictionary.h"
 #include "com_android_inputmethod_latin_DicTraverseSession.h"
@@ -35,7 +33,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
         AKLOGE("ERROR: GetEnv failed");
         return -1;
     }
-    assert(env);
+    ASSERT(env);
     if (!env) {
         AKLOGE("ERROR: JNIEnv is invalid");
         return -1;
diff --git a/native/jni/src/correction.cpp b/native/jni/src/correction.cpp
index 24221c98ce52ef76ad30643ce74e26461fdc0b72..a0256ee406de5c47f27aa6a97314cfc16e0bc426 100644
--- a/native/jni/src/correction.cpp
+++ b/native/jni/src/correction.cpp
@@ -247,7 +247,7 @@ Correction::CorrectionType Correction::processCharAndCalcState(const int c, cons
         if (mSkippedCount == 0 && mSkipPos < mOutputIndex) {
             if (DEBUG_DICT) {
                 // TODO: Enable this assertion.
-                //assert(mSkipPos == mOutputIndex - 1);
+                //ASSERT(mSkipPos == mOutputIndex - 1);
             }
             mSkipPos = mOutputIndex;
         }
diff --git a/native/jni/src/correction.h b/native/jni/src/correction.h
index 046935579dc0351e9ecd3be33f5bbc4a147976f9..8c477716ae2592116e9d20d84fe4f028cd1e1499 100644
--- a/native/jni/src/correction.h
+++ b/native/jni/src/correction.h
@@ -17,7 +17,6 @@
 #ifndef LATINIME_CORRECTION_H
 #define LATINIME_CORRECTION_H
 
-#include <cassert>
 #include <cstring> // for memset()
 
 #include "correction_state.h"
@@ -150,7 +149,7 @@ class Correction {
             // Branch if multiplier == 2 for the optimization
             if (multiplier < 0) {
                 if (DEBUG_DICT) {
-                    assert(false);
+                    ASSERT(false);
                 }
                 AKLOGI("--- Invalid multiplier: %d", multiplier);
             } else if (multiplier == 0) {
diff --git a/native/jni/src/proximity_info.cpp b/native/jni/src/proximity_info.cpp
index ffe12ce490f3a2b60111401f4abe86736d96dfb1..8ad9c77dc9ca996adaa17e05210d4f6d2e19f17f 100644
--- a/native/jni/src/proximity_info.cpp
+++ b/native/jni/src/proximity_info.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <cassert>
 #include <cstring>
 
 #define LOG_TAG "LatinIME: proximity_info.cpp"
@@ -75,7 +74,7 @@ ProximityInfo::ProximityInfo(JNIEnv *env, const jstring localeJStr, const int ma
     const jsize localeCStrUtf8Length = env->GetStringUTFLength(localeJStr);
     if (localeCStrUtf8Length >= MAX_LOCALE_STRING_LENGTH) {
         AKLOGI("Locale string length too long: length=%d", localeCStrUtf8Length);
-        assert(false);
+        ASSERT(false);
     }
     memset(mLocaleStr, 0, sizeof(mLocaleStr));
     env->GetStringUTFRegion(localeJStr, 0, env->GetStringLength(localeJStr), mLocaleStr);
@@ -105,7 +104,7 @@ bool ProximityInfo::hasSpaceProximity(const int x, const int y) const {
         if (DEBUG_DICT) {
             AKLOGI("HasSpaceProximity: Illegal coordinates (%d, %d)", x, y);
             // TODO: Enable this assertion.
-            //assert(false);
+            //ASSERT(false);
         }
         return false;
     }
@@ -180,7 +179,7 @@ void ProximityInfo::calculateNearbyKeyCodes(
                 inputCodes[insertPos++] = c;
                 if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
                     if (DEBUG_DICT) {
-                        assert(false);
+                        ASSERT(false);
                     }
                     return;
                 }
@@ -192,7 +191,7 @@ void ProximityInfo::calculateNearbyKeyCodes(
             inputCodes[insertPos++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
             if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
                 if (DEBUG_DICT) {
-                    assert(false);
+                    ASSERT(false);
                 }
                 return;
             }
@@ -213,7 +212,7 @@ void ProximityInfo::calculateNearbyKeyCodes(
                 inputCodes[insertPos++] = ac;
                 if (insertPos >= MAX_PROXIMITY_CHARS_SIZE) {
                     if (DEBUG_DICT) {
-                        assert(false);
+                        ASSERT(false);
                     }
                     return;
                 }
diff --git a/native/jni/src/unigram_dictionary.cpp b/native/jni/src/unigram_dictionary.cpp
index ebeef13b9846f0b8cf27b151f155fed86c69d792..0a144253a2b87577236635e77555e229b3bcc04f 100644
--- a/native/jni/src/unigram_dictionary.cpp
+++ b/native/jni/src/unigram_dictionary.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <cassert>
 #include <cstring>
 
 #define LOG_TAG "LatinIME: unigram_dictionary.cpp"
@@ -100,9 +99,9 @@ void UnigramDictionary::getWordWithDigraphSuggestionsRec(ProximityInfo *proximit
         const int codesRemain, const int currentDepth, int *codesDest, Correction *correction,
         WordsPriorityQueuePool *queuePool,
         const digraph_t *const digraphs, const unsigned int digraphsSize) const {
-    assert(sizeof(codesDest[0]) == sizeof(codesSrc[0]));
-    assert(sizeof(xCoordinatesBuffer[0]) == sizeof(xcoordinates[0]));
-    assert(sizeof(yCoordinatesBuffer[0]) == sizeof(ycoordinates[0]));
+    ASSERT(sizeof(codesDest[0]) == sizeof(codesSrc[0]));
+    ASSERT(sizeof(xCoordinatesBuffer[0]) == sizeof(xcoordinates[0]));
+    ASSERT(sizeof(yCoordinatesBuffer[0]) == sizeof(ycoordinates[0]));
 
     const int startIndex = static_cast<int>(codesDest - codesBuffer);
     if (currentDepth < MAX_DIGRAPH_SEARCH_DEPTH) {
@@ -894,7 +893,7 @@ bool UnigramDictionary::processCurrentNode(const int initialPos,
     // else if MASK_GROUP_ADDRESS_TYPE is not NONE: the children address
     // Note that you can't have a node that both is not a terminal and has no children.
     int c = BinaryFormat::getCodePointAndForwardPointer(DICT_ROOT, &pos);
-    assert(NOT_A_CODE_POINT != c);
+    ASSERT(NOT_A_CODE_POINT != c);
 
     // We are going to loop through each character and make it look like it's a different
     // node each time. To do that, we will process characters in this node in order until
@@ -987,7 +986,7 @@ bool UnigramDictionary::processCurrentNode(const int initialPos,
 
     // Now we finished processing this node, and we want to traverse children. If there are no
     // children, we can't come here.
-    assert(BinaryFormat::hasChildrenInFlags(flags));
+    ASSERT(BinaryFormat::hasChildrenInFlags(flags));
 
     // If this node was a terminal it still has the frequency under the pointer (it may have been
     // read, but not skipped - see readFrequencyWithoutMovingPointer).
diff --git a/native/jni/src/words_priority_queue_pool.h b/native/jni/src/words_priority_queue_pool.h
index c14afa07b749eddeef52b95b0c27e671358cdad9..f7c08fb5265c41e8af49da49584f9a7073f56c3a 100644
--- a/native/jni/src/words_priority_queue_pool.h
+++ b/native/jni/src/words_priority_queue_pool.h
@@ -17,7 +17,7 @@
 #ifndef LATINIME_WORDS_PRIORITY_QUEUE_POOL_H
 #define LATINIME_WORDS_PRIORITY_QUEUE_POOL_H
 
-#include <cassert>
+#include "defines.h"
 #include "words_priority_queue.h"
 
 namespace latinime {
@@ -55,7 +55,7 @@ class WordsPriorityQueuePool {
         }
         if (inputWordLength < 0 || inputWordLength >= SUB_QUEUE_MAX_COUNT) {
             if (DEBUG_WORDS_PRIORITY_QUEUE) {
-                assert(false);
+                ASSERT(false);
             }
             return 0;
         }