Formatting an SD card as Internal (Adoptable) Storage on Fire OS appears to change filename lookup behavior, causing native fopen() calls to fail when the requested filename differs only by letter case

:warning: Before you continue


Before submitting a bug report, please review our troubleshooting documentation at Troubleshoot Issues | Vega Troubleshooting

If you still want to file a bug report, please make sure to fill in all the details below and provide the necessary information.

NOTE: PLEASE ONLY REPORT A SINGLE BUG USING THIS TEMPLATE.
If you’re experiencing multiple issues, please file a separate report for each.


:backhand_index_pointing_right: 1. Summary

Bug Description

After formatting an SD card as Internal (Adoptable) Storage on a Fire tablet, native applications using standard C library file I/O (fopen()) experience case-sensitive filename resolution for files stored under /sdcard.

Applications that previously functioned before storage migration may fail to locate existing files if the filename requested differs only by letter case.

This behavior is reproducible using a minimal native test application and does not depend on any third-party SDK.

Impact

Applications that download resources using one filename capitalization but later open the same resource using different capitalization receive ENOENT, even though the file exists.

App Name

N/A (Reproduced using a standalone native test application.)

Bug Severity

:check_box_with_check: Impacts operation of app


2. Steps to Reproduce

  1. Insert an SD card into a Fire tablet.
  2. Format the SD card as Internal (Adoptable) Storage.
  3. Copy or create a file on adopted storage named:

CFGLIB_010000.BIN
  1. Execute:

FILE *fp =
fopen("/sdcard/.../cfglib_010000.bin","rb");
  1. Observe the return value.
  2. Execute:

FILE *fp =
fopen("/sdcard/.../CFGLIB_010000.BIN","rb");
  1. Compare the result.

3. Observed Behavior

The first call returns


NULL
errno = ENOENT (2)
"No such file or directory"

although the file exists.

Changing only the filename capitalization causes the identical fopen() call to succeed.

Example:


Stored filename:
CFGLIB_010000.BIN

Requested filename:
cfglib_010000.bin

No other changes are required.

The same application behavior worked correctly before the SD card was formatted as Internal (Adoptable) Storage.


4. Expected Behavior

I would like clarification whether this is expected Fire OS behavior.

If Adoptable Storage intentionally exposes case-sensitive pathname resolution through /sdcard, this behavior should be documented because native Android applications may rely on case-insensitive filename lookup after storage migration.

If this is not intentional, it appears to be a compatibility issue introduced after formatting the SD card as Internal Storage.


4.a Possible Root Cause

Investigation performed:

  • Filesystem verified as F2FS
  • external_storage.casefold.enabled is unset
  • Current AOSP vold formats adopted F2FS volumes without the casefold feature when this property is not enabled.
  • Native fopen() succeeds only when the pathname exactly matches the on-disk filename.

Temporary workaround:

Rename files so the stored filename exactly matches the filename passed to fopen().


Native test output:


fopen("/sdcard/.../cfglib_010000.bin")

NULL
errno=2
No such file or directory

--------------------------------

fopen("/sdcard/.../CFGLIB_010000.BIN")

SUCCESS

Additional Context

This issue was reproduced using a standalone native test program calling the standard libc fopen() API.

The behavior is independent of any third-party application and appears to depend solely on filename case after the SD card has been formatted as Internal (Adoptable) Storage.

Question:

Is case-sensitive filename lookup through /sdcard expected behavior on Fire OS after Adoptable Storage is enabled, or is this an unintended compatibility change?

Hi @tonykhar,

Welcome to Amazon Developer Community!!

Thank you for the thorough investigation and well-documented bug report.

This is expected behavior. When an SD card is formatted as Internal (Adoptable) Storage on Fire OS, the filesystem is reformatted from FAT/exFAT to F2FS. Unlike FAT/exFAT, F2FS is case-sensitive by default - this means filename lookups via fopen() require an exact case match.

Before adoption, the SD card uses FAT/exFAT, which is case-insensitive, so cfglib_010000.bin would successfully resolve to CFGLIB_010000.BIN. After adoption, the F2FS filesystem treats these as different filenames.

This behavior is consistent with AOSP’s implementation of adoptable storage and is not specific to Fire OS.

Recommendation:

Applications should always use consistent filename casing when writing and reading files to ensure portability across different filesystem types (FAT, F2FS, ext4). Relying on case-insensitive filename resolution is not safe on Linux-based filesystems.

Your workaround of matching the stored filename exactly in fopen() calls is the correct approach.

Reference: Fire OS 6 - Adoptable Storage ( Fire OS 6 for Fire Tablets | Fire Tablets )

Best regards,
Aishwarya M.

Hi @amen

Thank you for the clarification. I understand now that this is expected behavior and that Fire OS is following AOSP’s implementation for Adoptable Storage.

One observation I’d like to make is that, from both a developer’s and a user’s perspective, Fire OS provides a case-insensitive storage experience out of the box. Applications that use the tablet’s built-in storage operate without encountering this behavior. The change in filename semantics only becomes visible after an SD card is added and configured as Internal (Adoptable) Storage, where filename lookups transition from effectively case-insensitive to case-sensitive.

While this is technically consistent with the underlying F2FS filesystem, it introduces a compatibility boundary that is largely invisible to end users. Existing native applications that have functioned correctly for years can suddenly stop locating resources after enabling expanded storage, without any changes to the application itself. I also wonder whether some of the reports from users describing applications or downloaded content no longer working after enabling Internal Storage are actually manifestations of this change in filename semantics rather than unrelated application issues.

Since AOSP already includes optional F2FS casefold support through the external_storage.casefold.enabled property, would it be possible to expose this as an optional setting during the “Format as Internal Storage” process? For example:

Compatibility Mode (case-insensitive filename lookup)

This would provide a migration path for legacy applications while preserving the current default behavior for users who prefer standard Linux filesystem semantics. It would not alter the default Fire OS configuration or affect modern applications that already use consistent filename casing, but it could significantly improve compatibility for existing software that was developed under the assumption of case-insensitive storage behavior.

Thanks You,
Tony.