@@ -1587,12 +1587,33 @@ const std::vector<internal::EmbeddedFile>& CacheEmbeddedFiles(
15871587 file::GetClass (), file::GetMethodId (file::kConstructorFilePath ),
15881588 cache_dir, filename);
15891589 env->DeleteLocalRef (filename);
1590+ CheckAndClearJniExceptions (env);
1591+ // Below, we would have set the file read only on a previous run. Here, set
1592+ // it to writable and then delete it before creating it again.
1593+ //
1594+ // if output_file.exists() {
1595+ if (env->CallBooleanMethod (output_file, file::GetMethodId (file::kExists ))) {
1596+ CheckAndClearJniExceptions (env);
1597+ // output_file.setWritable(true);
1598+ env->CallBooleanMethod (output_file, file::GetMethodId (file::kSetWritable ),
1599+ JNI_TRUE);
1600+ CheckAndClearJniExceptions (env);
1601+ // output_file.delete();
1602+ env->CallBooleanMethod (output_file, file::GetMethodId (file::kDelete ));
1603+ CheckAndClearJniExceptions (env);
1604+ }
15901605 jobject output_stream = env->NewObject (
15911606 file_output_stream::GetClass (),
15921607 file_output_stream::GetMethodId (file_output_stream::kConstructorFile ),
15931608 output_file);
15941609 bool failed = CheckAndClearJniExceptions (env);
15951610 if (!failed) {
1611+ // Android 14 requires that we set the open dex file to readonly BEFORE
1612+ // writing code to it.
1613+ jboolean did_set_readonly = env->CallBooleanMethod (
1614+ output_file, file::GetMethodId (file::kSetReadOnly ));
1615+ // If it failed, move on and try again later after closing the file.
1616+ if (CheckAndClearJniExceptions (env)) did_set_readonly = JNI_FALSE;
15961617 jobject output_array = env->NewByteArray (it->size );
15971618 env->SetByteArrayRegion (static_cast <jbyteArray>(output_array), 0 ,
15981619 it->size ,
@@ -1605,6 +1626,11 @@ const std::vector<internal::EmbeddedFile>& CacheEmbeddedFiles(
16051626 env->CallVoidMethod (output_stream, file_output_stream::GetMethodId (
16061627 file_output_stream::kClose ));
16071628 failed |= CheckAndClearJniExceptions (env);
1629+ if (!did_set_readonly) {
1630+ env->CallBooleanMethod (output_file,
1631+ file::GetMethodId (file::kSetReadOnly ));
1632+ util::CheckAndClearJniExceptions (env);
1633+ }
16081634 env->DeleteLocalRef (output_array);
16091635 env->DeleteLocalRef (output_stream);
16101636 }
0 commit comments