The undocumented Android change that led to aCropalypse was reported during beta
Mentioned in the link.<p>This seems to be the original PR for the API in question, ParcelFileDescriptor#parseMode():<p><a href="https:&#x2F;&#x2F;android.googlesource.com&#x2F;platform&#x2F;frameworks&#x2F;base&#x2F;+&#x2F;eb8c3f93edc826413ff4143284dec01c1061d5cc^!&#x2F;#F3" rel="nofollow">https:&#x2F;&#x2F;android.googlesource.com&#x2F;platform&#x2F;frameworks&#x2F;base&#x2F;+&#x2F;...</a><p><pre><code>    +    public static int parseMode(String mode) {
    +        final int modeBits;
    +        if (&quot;r&quot;.equals(mode)) {
    +            modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
    +        } else if (&quot;w&quot;.equals(mode) || &quot;wt&quot;.equals(mode)) {
    +            modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
    +                    | ParcelFileDescriptor.MODE_CREATE
    +                    | ParcelFileDescriptor.MODE_TRUNCATE;
    +        } else if (&quot;wa&quot;.equals(mode)) {
    ...
</code></pre>
You can see that &quot;w&quot; and &quot;wt&quot; map to the same mode for file operations, including the MODE_TRUNCATE flag.<p>But we jump ahead a few years and the code is reworked.<p>from <a href="https:&#x2F;&#x2F;android.googlesource.com&#x2F;platform&#x2F;frameworks&#x2F;base&#x2F;+&#x2F;63280e06fc64672ab36d14f852b13df2274cc328^!&#x2F;core&#x2F;java&#x2F;android&#x2F;os&#x2F;ParcelFileDescriptor.java" rel="nofollow">https:&#x2F;&#x2F;android.googlesource.com&#x2F;platform&#x2F;frameworks&#x2F;base&#x2F;+&#x2F;...</a>:<p><pre><code>         public static int parseMode(String mode) {
    -        final int modeBits;
    -        if (&quot;r&quot;.equals(mode)) {
    -            modeBits = ParcelFileDescriptor.MODE_READ_ONLY;
    -        } else if (&quot;w&quot;.equals(mode) || &quot;wt&quot;.equals(mode)) {
    -            modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY
    -                    | ParcelFileDescriptor.MODE_CREATE
    -                    | ParcelFileDescriptor.MODE_TRUNCATE;
    -        } else if (&quot;wa&quot;.equals(mode)) {
    ...
    -        return modeBits;
    +        return FileUtils.translateModePosixToPfd(FileUtils.translateModeStringToPosix(mode));
         }
</code></pre>
So what does FileUtils.translateModePosixToPfd(FileUtils.translateModeStringToPosix(mode)) do?<p>from <a href="https:&#x2F;&#x2F;android.googlesource.com&#x2F;platform&#x2F;frameworks&#x2F;base&#x2F;+&#x2F;63280e06fc64672ab36d14f852b13df2274cc328^!&#x2F;#F2" rel="nofollow">https:&#x2F;&#x2F;android.googlesource.com&#x2F;platform&#x2F;frameworks&#x2F;base&#x2F;+&#x2F;...</a>:<p><pre><code>    +    public static int translateModeStringToPosix(String mode) {
    +        int res = 0;
    +        if (mode.startsWith(&quot;rw&quot;)) {
    +            res |= O_RDWR | O_CREAT;
    +        } else if (mode.startsWith(&quot;w&quot;)) {
    +            res |= O_WRONLY | O_CREAT;
    +        } else if (mode.startsWith(&quot;r&quot;)) {
    +            res |= O_RDONLY;
    +        } else {
    +            throw new IllegalArgumentException(&quot;Bad mode: &quot; + mode);
    +        }
    +        if (mode.indexOf(&#x27;t&#x27;) != -1) {
    +            res |= O_TRUNC;
    +        }
    +        if (mode.indexOf(&#x27;a&#x27;) != -1) {
    +            res |= O_APPEND;
    +        }
    +        return res;
    +    }
</code></pre>
Now &quot;w&quot; and &quot;wt&quot; map to different Posix open mode flags since one has to explicitly pass in &quot;t&quot; to get file truncation.<p>A dev was careless, plain and simple.<p>Having code in a monorepo doesn&#x27;t help if you don&#x27;t check how your code changes affects consumers&#x2F;clients of the code.<p>If they couldn&#x27;t change translateModeStringToPosix() behaviour, then the dev could&#x27;ve amended parseMode() to map &quot;w&#x27; to &quot;wt&quot; to keep the old behaviour (ugly and non-orthogonal, yes, but that&#x27;s the way the API was designed).