@@ -1587,12 +1587,33 @@ const std::vector<internal::EmbeddedFile>& CacheEmbeddedFiles(
1587
1587
file::GetClass (), file::GetMethodId (file::kConstructorFilePath ),
1588
1588
cache_dir, filename);
1589
1589
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
+ }
1590
1605
jobject output_stream = env->NewObject (
1591
1606
file_output_stream::GetClass (),
1592
1607
file_output_stream::GetMethodId (file_output_stream::kConstructorFile ),
1593
1608
output_file);
1594
1609
bool failed = CheckAndClearJniExceptions (env);
1595
1610
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;
1596
1617
jobject output_array = env->NewByteArray (it->size );
1597
1618
env->SetByteArrayRegion (static_cast <jbyteArray>(output_array), 0 ,
1598
1619
it->size ,
@@ -1605,6 +1626,11 @@ const std::vector<internal::EmbeddedFile>& CacheEmbeddedFiles(
1605
1626
env->CallVoidMethod (output_stream, file_output_stream::GetMethodId (
1606
1627
file_output_stream::kClose ));
1607
1628
failed |= CheckAndClearJniExceptions (env);
1629
+ if (!did_set_readonly) {
1630
+ env->CallBooleanMethod (output_file,
1631
+ file::GetMethodId (file::kSetReadOnly ));
1632
+ util::CheckAndClearJniExceptions (env);
1633
+ }
1608
1634
env->DeleteLocalRef (output_array);
1609
1635
env->DeleteLocalRef (output_stream);
1610
1636
}
0 commit comments