Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / build / android / incremental_install / java / org / chromium / incrementalinstall / LockFile.java
blob39256a61314aa63919648258058d4e9e983428f1
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.incrementalinstall;
7 import android.util.Log;
9 import java.io.File;
10 import java.io.FileOutputStream;
11 import java.io.IOException;
12 import java.nio.channels.FileLock;
13 import java.util.concurrent.Callable;
15 /**
16 * Helpers for dealing with .lock files used during install / first run.
18 final class LockFile {
19 private static final String TAG = "cr.incrementalinstall";
21 private final File mFile;
22 private final FileOutputStream mOutputStream;
23 private final FileLock mFileLock;
25 private LockFile(File file, FileOutputStream outputStream, FileLock fileLock) {
26 mFile = file;
27 mOutputStream = outputStream;
28 mFileLock = fileLock;
31 /**
32 * Clears the lock file by writing to it (making it non-zero in length);
34 static void clearInstallerLock(File lockFile) throws IOException {
35 Log.i(TAG, "Clearing " + lockFile);
36 // On Android M+, we can't delete files in /data/local/tmp, so we write to it instead.
37 FileOutputStream os = new FileOutputStream(lockFile);
38 os.write(1);
39 os.close();
42 /**
43 * Waits for the given file to be non-zero in length.
45 static void waitForInstallerLock(final File file, long timeoutMs) {
46 pollingWait(new Callable<Boolean>() {
47 @Override public Boolean call() {
48 return !installerLockExists(file);
50 }, file, timeoutMs);
53 /**
54 * Waits for the given file to be non-zero in length.
56 private static void pollingWait(Callable<Boolean> func, File file, long timeoutMs) {
57 long pollIntervalMs = 200;
58 for (int i = 0; i < timeoutMs / pollIntervalMs; i++) {
59 try {
60 if (func.call()) {
61 if (i > 0) {
62 Log.i(TAG, "Finished waiting on lock file: " + file);
64 return;
65 } else if (i == 0) {
66 Log.i(TAG, "Waiting on lock file: " + file);
68 } catch (Exception e) {
69 throw new RuntimeException(e);
71 try {
72 Thread.sleep(pollIntervalMs);
73 } catch (InterruptedException e) {
74 // Should never happen.
77 throw new RuntimeException("Timed out waiting for lock file: " + file);
80 /**
81 * Returns whether the given lock file is missing or is in the locked state.
83 static boolean installerLockExists(File file) {
84 return !file.exists() || file.length() == 0;
87 /**
88 * Attempts to acquire a lock for the given file.
89 * @return Returns the FileLock if it was acquired, or null otherwise.
91 static LockFile acquireRuntimeLock(File file) {
92 try {
93 FileOutputStream outputStream = new FileOutputStream(file);
94 FileLock lock = outputStream.getChannel().tryLock();
95 if (lock != null) {
96 Log.i(TAG, "Created lock file: " + file);
97 return new LockFile(file, outputStream, lock);
99 outputStream.close();
100 } catch (IOException e) {
101 // Do nothing. We didn't get the lock.
103 return null;
107 * Waits for the given file to not exist.
109 static void waitForRuntimeLock(final File file, long timeoutMs) {
110 pollingWait(new Callable<Boolean>() {
111 @Override public Boolean call() {
112 return !file.exists();
114 }, file, timeoutMs);
118 * Releases and deletes the lock file.
120 void release() throws IOException {
121 Log.i(TAG, "Deleting lock file: " + mFile);
122 mFileLock.release();
123 mOutputStream.close();
124 if (!mFile.delete()) {
125 throw new IOException("Failed to delete lock file: " + mFile);