Encryption unsuccessful, need to factory reset or crash after android restarts several times

This reality has been seen in previous projects that did not have batteries, but the one that did not have a battery power outage and had data being written to EMMC, whereas reboot was supposed to shut down or pause all threads to make sure that no EMMC operation was written. Depressing.
There is no way to appear, it appears, take a look at what Android Reboot does, baidu, there are a lot of, post the process out:

framework 
./base/core/java/com/android/internal/app/ShutdownThread.java
/**
     * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
     * or {@link #shutdown(Context, boolean)} instead.
     *
     * @param reboot true to reboot or false to shutdown
     * @param reason reason for reboot
     */
    public static void rebootOrShutdown(boolean reboot, String reason) {
        if (reboot) {
            Log.i(TAG, "Rebooting, reason: " + reason);
            try {
                Power.reboot(reason);
            } catch (Exception e) {
                Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);
            }
        } else if (SHUTDOWN_VIBRATE_MS > 0) {
            // vibrate before shutting down
            Vibrator vibrator = new Vibrator();
            try {
                vibrator.vibrate(SHUTDOWN_VIBRATE_MS);
            } catch (Exception e) {
                // Failure to vibrate shouldn't interrupt shutdown.  Just log it.
                Log.w(TAG, "Failed to vibrate during shutdown.", e);
            }

            // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
            try {
                Thread.sleep(SHUTDOWN_VIBRATE_MS);
            } catch (InterruptedException unused) {
            }
        }

        // Shutdown power
        Log.i(TAG, "Performing low-level shutdown...");
        Power.shutdown();
    }




./base/core/jni/android_os_Power.cpp 
static void android_os_Power_shutdown(JNIEnv *env, jobject clazz)
{
    android_reboot(ANDROID_RB_POWEROFF, 0, 0);
}

extern int go_recovery(void);

static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason)
{
    if (reason == NULL) {
        android_reboot(ANDROID_RB_RESTART, 0, 0);
    } else {
        const char *chars = env->GetStringUTFChars(reason, NULL);
        //android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
        go_recovery();
        android_reboot(ANDROID_RB_RESTART, 0, 0);
        env->ReleaseStringUTFChars(reason, chars);  // In case it fails.
    }
    jniThrowIOException(env, errno);
}

ANDOID_ROOT\system\core\libcutils\android_reboot.c
int android_reboot(int cmd, int flags, char *arg)
{
    int ret;

    if (!(flags & ANDROID_RB_FLAG_NO_SYNC))
        sync();

    if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO))
        remount_ro();

    switch (cmd) {
        case ANDROID_RB_RESTART:
            ret = reboot(RB_AUTOBOOT);
            break;

        case ANDROID_RB_POWEROFF:
            ret = reboot(RB_POWER_OFF);
            break;

        case ANDROID_RB_RESTART2:
            ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
                           LINUX_REBOOT_CMD_RESTART2, arg);
            break;

        default:
            ret = -1;
    }

    return ret;
}

android4.0/frameworks/base/core/jni/misc_rw.cpp
/* force the next boot to recovery */
int go_recovery(void){
	
	LOGE("go_recovery  =================\n");
	struct bootloader_message boot, temp;

	memset(&boot, 0, sizeof(boot));
	strcpy(boot.command, "boot-recovery");
	if (set_bootloader_message_block(&boot, MISC_DEVICE) )
		return -1;

	//read for compare
	memset(&temp, 0, sizeof(temp));
	if (get_bootloader_message_block(&temp, MISC_DEVICE))
		return -1;

	if( memcmp(&boot, &temp, sizeof(boot)) )
		return -1;
	LOGE("go_recovery  ++++++++++++++++++++++\n");
	return 0;

}

as you can see from above, the system is mount readonly before reboot:

  remount_ro();

So why is there a problem?The problem seems to be remount_ro(); The inside. Look at the code inside

static void remount_ro(void)
{
    int fd, cnt = 0;

    /* Trigger the remount of the filesystems as read-only,
     * which also marks them clean.
     */
    fd = open("/proc/sysrq-trigger", O_WRONLY);
    if (fd < 0) {
        return;
    }
    write(fd, "u", 1);
    close(fd);


    /* Now poll /proc/mounts till it's done */
    while (!remount_ro_done() && (cnt < 50)) {
        usleep(100000);
        cnt++;
    }

    return;
}

 

/proc/sysrq-trigger

This is a read-only node that can restart the system, remount, and so on, but it’s asynchronous, so there’s a check and wait, it’s probably not long enough to wait (5S), let’s try it out for a minute.


Read More: