I encountered this error while trying to use the RecoverySystem.installPackage API to apply an OTA update. This post shows what causes the error and how to walk around it. The error occurs for AOSP release android-6.0.1_r24 in my case.

The Cause

By looking at the source code at $AOSP/frameworks/base/core/java/android/os/RecoverySystem.java (Link RecoverySystem.java). The exception was thrown from this line:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public static void installPackage(Context context, File packageFile)
        throws IOException {
        String filename = packageFile.getCanonicalPath();
        FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE); // <-- THIS LINE
        try {
            uncryptFile.write(filename + "\n");
        } finally {
            uncryptFile.close();
        }
        Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
        // If the package is on the /data partition, write the block map file
        // into COMMAND_FILE instead.
        if (filename.startsWith("/data/")) {
            filename = "@/cache/recovery/block.map";
        }
        final String filenameArg = "--update_package=" + filename;
        final String localeArg = "--locale=" + Locale.getDefault().toString();
        bootCommand(context, filenameArg, localeArg);
    }

Earlier, UNCRYPT_FILE was defined as this:

1
2
3
private static File RECOVERY_DIR = new File("/cache/recovery");
private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");
private static File UNCRYPT_FILE = new File(RECOVERY_DIR, "uncrypt_file");

So its value is /cache/recovery/uncrypt_file. However, at this point, its parent directory /cache/recovery/ does not exists yet! And FileWriter will not create it automatically, therefore the FileNotFound exception.

The Fix

If you are a app developer and do not have access to the AOSP framework on your target system, simple create that folder before calling installPackage.

1
2
(new File("/cache/recovery/")).mkdirs();
RecoverySystem.installPackage(otaPackage);

The real fix from the platform side is this:

1
2
3
4
5
6
7
public static void installPackage(Context context, File packageFile)
       throws IOException {
       String filename = packageFile.getCanonicalPath();
       RECOVERY_DIR.mkdirs();
       FileWriter uncryptFile = new FileWriter(UNCRYPT_FILE); // <-- THIS LINE
       //...
       }