2024年5月7日发(作者:)

// later).

return;

}

// If we already called lock() but didn't succeed in getting the lock, it's possible the

// app caught the exception and tried again later. As above, there's no real advantage

// to failing here, so only open the lock file if we didn't already open it before.

if (sLockFile == null) {

String dataPath = aDirectory();

File lockFile = new File(dataPath, EXCLUSIVE_LOCK_FILE);

try {

// Note that the file is kept open intentionally.

sLockFile = new RandomAccessFile(lockFile, "rw");

} catch (IOException e) {

// Failing to create the lock file is always fatal; even if multiple processes

// are using the same data directory we should always be able to access the file

// itself.

throw new RuntimeException("Failed to create lock file " + lockFile, e);

}

}

// Android versions before 11 have edge cases where a new instance of an app process can

// be started while an existing one is still in the process of being killed. This can

// still happen on Android 11+ because the platform has a timeout for waiting, but it's

// much less likely. Retry the lock a few times to give the old process time to fully go

// away.

for (int attempts = 1; attempts <= LOCK_RETRIES; ++attempts) {

try {

sExclusiveFileLock = nnel().tryLock();

} catch (IOException e) {

// Older versions of Android incorrectly throw IOException when the flock()

// call fails with EAGAIN, instead of returning null. Just ignore it.

}

if (sExclusiveFileLock != null) {

// We got the lock; write out info for debugging.

writeCurrentProcessInfo(sLockFile);

return;

}

// If we're not out of retries, sleep and try again.

if (attempts == LOCK_RETRIES) break;

try {

(LOCK_SLEEP_MS);

} catch (InterruptedException e) {

}

}

// We failed to get the lock even after retrying.

// Many existing apps rely on this even though it's known to be unsafe.

// Make it fatal when on P for apps that target P or higher

String error = getLockFailureReason(sLockFile);

boolean dieOnFailure = _INT >= N_CODES.P

&& licationInfo().targetSdkVersion >= N_CODES.P;

if (dieOnFailure) {

throw new RuntimeException(error);

} else {

Log.w(TAG, error);

}

}

}

private static void writeCurrentProcessInfo(final RandomAccessFile file) {

try {

// Truncate the file first to get rid of old data.

gth(0);

nt(());

TF(cessName());

} catch (IOException e) {

// Don't crash just because something failed here, as it's only for debugging.

Log.w(TAG, "Failed to write info to lock file", e);

}

}

private static String getLockFailureReason(final RandomAccessFile file) {

final StringBuilder error = new StringBuilder("Using WebView from more than one process at "

+ "once with the same data directory is not supported. /558377 "

+ ": Current process ");

(cessName());

(" (pid ").append(()).append("), lock owner ");

try {