int property_set_sync(const char *key, const char *value)
{
    return __system_property_set(key, value);
}
/* Initializes memory allocation framework once per process. */
static void malloc_init_impl(void)
{
    const char* so_name = NULL;
    MallocDebugInit malloc_debug_initialize = NULL;
    unsigned int qemu_running = 0;
    unsigned int debug_level = 0;


    unsigned int memcheck_enabled = 0;
    char env[PROP_VALUE_MAX];
    char memcheck_tracing[PROP_VALUE_MAX];

    // added by zmj
    mspace_malloc_stat = NULL;
    mspace_free_stat = NULL;

#ifdef _MTK_ENG_
    debug_level = 15;
#else
    debug_level = 0;
#endif
	
    /* Get custom malloc debug level. Note that emulator started with
     * memory checking option will have priority over debug level set in
     * libc.debug.malloc system property. */
    if (__system_property_get("ro.kernel.qemu", env) && atoi(env)) {
        qemu_running = 1;
        if (__system_property_get("ro.kernel.memcheck", memcheck_tracing)) {
            if (memcheck_tracing[0] != '0') {
                // Emulator has started with memory tracing enabled. Enforce it.
                debug_level = 20;
                memcheck_enabled = 1;
            }
        }
    }

    /* If debug level has not been set by memcheck option in the emulator,
     * lets grab it from libc.debug.malloc system property. */
    if ((debug_level !=  20) && __system_property_get("libc.debug.malloc", env)) {
        debug_level = atoi(env);
    }

    if ((debug_level != 20) && __system_property_get("persist.libc.debug.malloc", env)) {
        debug_level = atoi(env);
    }

    if (__system_property_get("ro.build.type", env)) {
        if(strncmp(env, "eng", 3))
			debug_level = 0;
    }
		
    /* Debug level 0 means that we should use dlxxx allocation
     * routines (default). */
    if (!debug_level) {
        return;
    }

    // Lets see which .so must be loaded for the requested debug level
    switch (debug_level) {
        case 1:
        case 5:
        case 10:
            so_name = "/system/lib/libc_malloc_debug_leak.so";
            break;
	case 15:
	case 16:
		so_name = "/system/lib/libc_malloc_debug_mtk.so";
		break;
        case 20:
            // Quick check: debug level 20 can only be handled in emulator.
            if (!qemu_running) {
                error_log("%s: Debug level %d can only be set in emulator\n",
                          __progname, debug_level);
                return;
            }
            // Make sure that memory checking has been enabled in emulator.
            if (!memcheck_enabled) {
                error_log("%s: Memory checking is not enabled in the emulator\n",
                          __progname);
                return;
            }
            so_name = "/system/lib/libc_malloc_debug_qemu.so";
            break;
        default:
            error_log("%s: Debug level %d is unknown\n",
                      __progname, debug_level);
            return;
    }

    // Load .so that implements the required malloc debugging functionality.
    libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
    if (libc_malloc_impl_handle == NULL) {
        error_log("%s: Missing module %s required for malloc debug level %d\n",
                 __progname, so_name, debug_level);
        return;
    }

    // Initialize malloc debugging in the loaded module.
    malloc_debug_initialize =
            dlsym(libc_malloc_impl_handle, "malloc_debug_initialize");
    if (malloc_debug_initialize == NULL) {
        error_log("%s: Initialization routine is not found in %s\n",
                  __progname, so_name);
        dlclose(libc_malloc_impl_handle);
        return;
    }
    if (malloc_debug_initialize()) {
        dlclose(libc_malloc_impl_handle);
        return;
    }

    if (debug_level == 20) {
        // For memory checker we need to do extra initialization.
        int (*memcheck_initialize)(int, const char*) =
                dlsym(libc_malloc_impl_handle, "memcheck_initialize");
        if (memcheck_initialize == NULL) {
            error_log("%s: memcheck_initialize routine is not found in %s\n",
                      __progname, so_name);
            dlclose(libc_malloc_impl_handle);
            return;
        }
        if (memcheck_initialize(MALLOC_ALIGNMENT, memcheck_tracing)) {
            dlclose(libc_malloc_impl_handle);
            return;
        }
    }

    if (debug_level == 15) {
		int sig = 0;
        // For debug 15 we need to do extra initialization.
        int (*debug15_extra_initialize)(int) =
                dlsym(libc_malloc_impl_handle, "debug15_extra_initialize");
        if (debug15_extra_initialize == NULL) {
            error_log("%s: malloc_debug_extra_initialize routine is not found in %s\n",
                      __progname, so_name);
            dlclose(libc_malloc_impl_handle);
			 return;
        }
				
	    if (__system_property_get("persist.debug15.sig", env)) {
	        sig = atoi(env);
	    }
		
        if (debug15_extra_initialize(sig)) {
            dlclose(libc_malloc_impl_handle);
            return;
        }
		
		// to indicate that debug 15 is on.
		__system_property_set("libc.debug15.status", "on");
    }
		
    // Initialize malloc dispatch table with appropriate routines.
    switch (debug_level) {
        case 1:
            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
                    "%s using MALLOC_DEBUG = %d (leak checker)\n",
                    __progname, debug_level);
            gMallocUse.malloc =
                dlsym(libc_malloc_impl_handle, "leak_malloc");
            gMallocUse.free =
                dlsym(libc_malloc_impl_handle, "leak_free");
            gMallocUse.calloc =
                dlsym(libc_malloc_impl_handle, "leak_calloc");
            gMallocUse.realloc =
                dlsym(libc_malloc_impl_handle, "leak_realloc");
            gMallocUse.memalign =
                dlsym(libc_malloc_impl_handle, "leak_memalign");
            break;
        case 5:
            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
                    "%s using MALLOC_DEBUG = %d (fill)\n",
                    __progname, debug_level);
            gMallocUse.malloc =
                dlsym(libc_malloc_impl_handle, "fill_malloc");
            gMallocUse.free =
                dlsym(libc_malloc_impl_handle, "fill_free");
            gMallocUse.calloc = dlcalloc;
            gMallocUse.realloc =
                dlsym(libc_malloc_impl_handle, "fill_realloc");
            gMallocUse.memalign =
                dlsym(libc_malloc_impl_handle, "fill_memalign");
            break;
        case 10:
            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
                    "%s using MALLOC_DEBUG = %d (sentinels, fill)\n",
                    __progname, debug_level);
            gMallocUse.malloc =
                dlsym(libc_malloc_impl_handle, "chk_malloc");
            gMallocUse.free =
                dlsym(libc_malloc_impl_handle, "chk_free");
            gMallocUse.calloc =
                dlsym(libc_malloc_impl_handle, "chk_calloc");
            gMallocUse.realloc =
                dlsym(libc_malloc_impl_handle, "chk_realloc");
            gMallocUse.memalign =
                dlsym(libc_malloc_impl_handle, "chk_memalign");
            break;

	case 15:
		__libc_android_log_print(ANDROID_LOG_INFO, "libc",
								"%s using MALLOC_DEBUG = %d(dlmalloc, BT)\n",
								__progname, debug_level);
		gMallocUse.malloc =
			dlsym(libc_malloc_impl_handle, "mtk_malloc");
		gMallocUse.free =
			dlsym(libc_malloc_impl_handle, "mtk_free");
		gMallocUse.calloc =
			dlsym(libc_malloc_impl_handle, "mtk_calloc");
		gMallocUse.realloc =
			dlsym(libc_malloc_impl_handle, "mtk_realloc");
		gMallocUse.memalign =
			dlsym(libc_malloc_impl_handle, "mtk_memalign");
        gpMallocFullBacktrace = 
            dlsym(libc_malloc_impl_handle, "mtk_malloc_full_backtrace");
        gpFreeFullBacktrace = 
            dlsym(libc_malloc_impl_handle, "mtk_free_full_backtrace");
		break;
	case 16:
		__libc_android_log_print(ANDROID_LOG_INFO, "libc",
					"%s using MALLOC_DEBUG = %d (dlmalloc, mspace, BT)\n",
					__progname, debug_level);
		gMallocUse.malloc =
			dlsym(libc_malloc_impl_handle, "mtk_malloc");
		gMallocUse.free =
			dlsym(libc_malloc_impl_handle, "mtk_free");
		gMallocUse.calloc =
			dlsym(libc_malloc_impl_handle, "mtk_calloc");
		gMallocUse.realloc =
			dlsym(libc_malloc_impl_handle, "mtk_realloc");
		gMallocUse.memalign =
			dlsym(libc_malloc_impl_handle, "mtk_memalign");
		mspace_malloc_stat = 
			dlsym(libc_malloc_impl_handle, "mtk_mspace_malloc_stat");
        	mspace_free_stat = 
			dlsym(libc_malloc_impl_handle, "mtk_mspace_free_stat");
		break;

        case 20:
            __libc_android_log_print(ANDROID_LOG_INFO, "libc",
                "%s[%u] using MALLOC_DEBUG = %d (instrumented for emulator)\n",
                __progname, getpid(), debug_level);
            gMallocUse.malloc =
                dlsym(libc_malloc_impl_handle, "qemu_instrumented_malloc");
            gMallocUse.free =
                dlsym(libc_malloc_impl_handle, "qemu_instrumented_free");
            gMallocUse.calloc =
                dlsym(libc_malloc_impl_handle, "qemu_instrumented_calloc");
            gMallocUse.realloc =
                dlsym(libc_malloc_impl_handle, "qemu_instrumented_realloc");
            gMallocUse.memalign =
                dlsym(libc_malloc_impl_handle, "qemu_instrumented_memalign");
            break;
        default:
            break;
    }

    // Make sure dispatch table is initialized
    if ((gMallocUse.malloc == NULL) ||
        (gMallocUse.free == NULL) ||
        (gMallocUse.calloc == NULL) ||
        (gMallocUse.realloc == NULL) ||
        (gMallocUse.memalign == NULL)) {
        error_log("%s: Cannot initialize malloc dispatch table for debug level"
                  " %d: %p, %p, %p, %p, %p\n",
                  __progname, debug_level,
                  gMallocUse.malloc, gMallocUse.free,
                  gMallocUse.calloc, gMallocUse.realloc,
                  gMallocUse.memalign);
        dlclose(libc_malloc_impl_handle);
        libc_malloc_impl_handle = NULL;
    } else {
        __libc_malloc_dispatch = &gMallocUse;
    }
}
/* Initializes memory allocation framework once per process. */
static void malloc_init_impl() {
    const char* so_name = NULL;
    MallocDebugInit malloc_debug_initialize = NULL;
    unsigned int qemu_running = 0;
    unsigned int debug_level = 0;
    unsigned int memcheck_enabled = 0;
    char env[PROP_VALUE_MAX];
    char memcheck_tracing[PROP_VALUE_MAX];
    char debug_program[PROP_VALUE_MAX];

/*
  BEGIN mtk-added: 
*/
     /* 
       * since there are NO libc_malloc_debug_leak.so, libc_malloc_debug_qemu.so and 
       * libc_malloc_debug_xxx.so on user load,
       * speed up the malloc initialization.
       */
#ifdef IS_USER_BUILD
     /* Debug level 0 means that we should use dlxxx allocation
     * routines (default). */
    if (debug_level == 0) {
        return;
    }
#endif

    /*
      * debug 15 is enable by default ONLY when:
      * 1. MTK ENG load -> frame pointer, apcs, arm
      * 2. malloc debug feature is on.
      */
#if defined(HAVE_MALLOC_DEBUG_FEATURE) && defined(_MTK_ENG_)
    debug_level = 15;
#else
    debug_level = 0;
#endif
    
    // TODO: temp solution. need optimize.
#if defined(DISABLE_MALLOC_DEBUG)
    debug_level = 0;
#endif

#ifdef HAVE_MALLOC_DEBUG_FEATURE
    /* debug level priority
      * 0 < (15, 16) < (1, 5, 10) < 20
      */
    if (__system_property_get("persist.libc.debug.malloc", env)) {
        debug_level = atoi(env); // overwrite initial value(0, or 15)
    }
#endif
/*
  END mtk-added.
*/

    /* Get custom malloc debug level. Note that emulator started with
     * memory checking option will have priority over debug level set in
     * libc.debug.malloc system property. */
    if (__system_property_get("ro.kernel.qemu", env) && atoi(env)) {
        qemu_running = 1;
        if (__system_property_get("ro.kernel.memcheck", memcheck_tracing)) {
            if (memcheck_tracing[0] != '0') {
                // Emulator has started with memory tracing enabled. Enforce it.
                debug_level = 20;
                memcheck_enabled = 1;
            }
        }
    }


/*
  BEGIN mtk-modified: libc.debug.malloc will overwrite persist.libc.debug.malloc
*/
    /* If debug level has not been set by memcheck option in the emulator,
     * lets grab it from libc.debug.malloc system property. */
    if ((debug_level == 0 || debug_level == 15 || debug_level == 16)
		&& __system_property_get("libc.debug.malloc", env)) {
        debug_level = atoi(env); // overwrite previous value(0, 15 or 16)
    }
/*
  END mtk-modified: 
*/
    /* Debug level 0 means that we should use dlxxx allocation
     * routines (default). */
    if (debug_level == 0) {
        return;
    }

    /* If libc.debug.malloc.program is set and is not a substring of progname,
     * then exit.
     */
    if (__system_property_get("libc.debug.malloc.program", debug_program)) {
        if (!strstr(__progname, debug_program)) {
            return;
        }
    }

    // Lets see which .so must be loaded for the requested debug level
    switch (debug_level) {
        case 1:
        case 5:
        case 10: {
            char debug_backlog[PROP_VALUE_MAX];
            if (__system_property_get("libc.debug.malloc.backlog", debug_backlog)) {
                malloc_double_free_backlog = atoi(debug_backlog);
                info_log("%s: setting backlog length to %d\n",
                         __progname, malloc_double_free_backlog);
            }

            so_name = "/system/lib/libc_malloc_debug_leak.so";
            break;
        }
/*
  BEGIN mtk-added: 
*/
#if defined(HAVE_MALLOC_DEBUG_FEATURE) || defined(HAVE_MSPACE_DEBUG_FEATURE)
        case 15:
        case 16:
            so_name = "/system/lib/libc_malloc_debug_mtk.so";
            break;
#endif
/*
 END mtk-added.
*/
        case 20:
            // Quick check: debug level 20 can only be handled in emulator.
            if (!qemu_running) {
                error_log("%s: Debug level %d can only be set in emulator\n",
                          __progname, debug_level);
                return;
            }
            // Make sure that memory checking has been enabled in emulator.
            if (!memcheck_enabled) {
                error_log("%s: Memory checking is not enabled in the emulator\n",
                          __progname);
                return;
            }
            so_name = "/system/lib/libc_malloc_debug_qemu.so";
            break;
        default:
            error_log("%s: Debug level %d is unknown\n",
                      __progname, debug_level);
            return;
    }

    // Load .so that implements the required malloc debugging functionality.
    libc_malloc_impl_handle = dlopen(so_name, RTLD_LAZY);
    if (libc_malloc_impl_handle == NULL) {
        error_log("%s: Missing module %s required for malloc debug level %d: %s",
                  __progname, so_name, debug_level, dlerror());
        return;
    }

    // Initialize malloc debugging in the loaded module.
    malloc_debug_initialize = reinterpret_cast<MallocDebugInit>(dlsym(libc_malloc_impl_handle,
                                                                      "malloc_debug_initialize"));
    if (malloc_debug_initialize == NULL) {
        error_log("%s: Initialization routine is not found in %s\n",
                  __progname, so_name);
        dlclose(libc_malloc_impl_handle);
        return;
    }
    if (malloc_debug_initialize()) {
        dlclose(libc_malloc_impl_handle);
        return;
    }

    if (debug_level == 20) {
        // For memory checker we need to do extra initialization.
        typedef int (*MemCheckInit)(int, const char*);
        MemCheckInit memcheck_initialize =
            reinterpret_cast<MemCheckInit>(dlsym(libc_malloc_impl_handle,
                                                 "memcheck_initialize"));
        if (memcheck_initialize == NULL) {
            error_log("%s: memcheck_initialize routine is not found in %s\n",
                      __progname, so_name);
            dlclose(libc_malloc_impl_handle);
            return;
        }
        if (memcheck_initialize(MALLOC_ALIGNMENT, memcheck_tracing)) {
            dlclose(libc_malloc_impl_handle);
            return;
        }
    }

/*
  BEGIN mtk-added: 
*/
#if defined(HAVE_MALLOC_DEBUG_FEATURE) || defined(HAVE_MSPACE_DEBUG_FEATURE)
    if (debug_level == 15) {
	int sig = 0;
	int backtrace_method = -1, backtrace_size = -1;

	
        // For debug 15 we need to do extra initialization.
        Debug15ExtraInitialize debug15_extra_initialize =
                reinterpret_cast<Debug15ExtraInitialize>(dlsym(libc_malloc_impl_handle, "debug15_extra_initialize"));
        if (debug15_extra_initialize == NULL) {
            error_log("%s: malloc_debug_extra_initialize routine is not found in %s\n",
                      __progname, so_name);
            dlclose(libc_malloc_impl_handle);
	     return;
        }

		// NOTICE:
		// have to read property in this stage.
		// reading in debug15_extra_initialize does not work, while reson is unclear.
	    if (__system_property_get("persist.debug15.sig", env)) {
	        sig = atoi(env);
	    }

	    if (__system_property_get("persist.debug15.prog", env)) {		
			if (strncmp("ALL", env, sizeof("ALL")) == 0 || strstr(__progname, env)) {
				error_log("gcc 20 bt for: %s\n", __progname);
				backtrace_method = 1; // gcc unwind
				backtrace_size = 20; // back trace depth: 20
	        	}
			
	    } 
				
        if (debug15_extra_initialize(sig, backtrace_method, backtrace_size)) {
            dlclose(libc_malloc_impl_handle);
            return;
        }

		// to indicate that debug 15 is on.
		// NOTICE: This function does not exist on GB.
	    if (__system_property_get("libc.debug15.status", env)) {
	       if (strncmp("off", env, sizeof("off")) == 0)
		   __system_property_set("libc.debug15.status", "on");
	    } else
	      __system_property_set("libc.debug15.status", "on");
    }
#endif
/*
 END mtk-added.
*/

    // Initialize malloc dispatch table with appropriate routines.
    switch (debug_level) {
        case 1:
            InitMalloc(&gMallocUse, debug_level, "leak");
            break;
        case 5:
            InitMalloc(&gMallocUse, debug_level, "fill");
            break;
        case 10:
            InitMalloc(&gMallocUse, debug_level, "chk");
            break;
/*
  BEGIN mtk-added: 
*/
#if defined(HAVE_MALLOC_DEBUG_FEATURE)
        case 15:
            InitMalloc(&gMallocUse, debug_level, "mtk");
            break;
#if defined(HAVE_MSPACE_DEBUG_FEATURE)
        case 16:
            if(mspace_stat_init() == 0)
            	InitMalloc(&gMallocUse, debug_level, "mtk");
            break;
#endif //#if defined(HAVE_MSPACE_DEBUG_FEATURE)
#endif // #if defined(HAVE_MALLOC_DEBUG_FEATURE)
/*
 END mtk-added.
*/
        case 20:
            InitMalloc(&gMallocUse, debug_level, "qemu_instrumented");
            break;
        default:
            break;
    }

    // Make sure dispatch table is initialized
    if ((gMallocUse.malloc == NULL) ||
        (gMallocUse.free == NULL) ||
        (gMallocUse.calloc == NULL) ||
        (gMallocUse.realloc == NULL) ||
        (gMallocUse.memalign == NULL)) {
        error_log("%s: some symbols for libc.debug.malloc level %d were not found (see above)",
                  __progname, debug_level);
        dlclose(libc_malloc_impl_handle);
        libc_malloc_impl_handle = NULL;
    } else {
        __libc_malloc_dispatch = &gMallocUse;
    }
}