Watch for changes to the log file so we can reopen it

If the log fragment is shown while the daemon starts (which is not the
case at the moment, but maybe later on tablets) the file reader would not
notice that the file got truncated.  The same applies if the file is deleted
directly on the file system e.g. with adb shell.
This commit is contained in:
Tobias Brunner 2012-08-10 10:05:38 +02:00
parent bad119c55a
commit ae10e8c458
1 changed files with 86 additions and 5 deletions

View File

@ -26,6 +26,7 @@ import org.strongswan.android.logic.CharonVpnService;
import android.app.Fragment;
import android.os.Bundle;
import android.os.FileObserver;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
@ -41,6 +42,7 @@ public class LogFragment extends Fragment implements Runnable
private BufferedReader mReader;
private Thread mThread;
private volatile boolean mRunning;
private FileObserver mDirectoryObserver;
@Override
public void onCreate(Bundle savedInstanceState)
@ -50,6 +52,8 @@ public class LogFragment extends Fragment implements Runnable
mLogFilePath = getActivity().getFilesDir() + File.separator + CharonVpnService.LOG_FILE;
/* use a handler to update the log view */
mLogHandler = new Handler();
mDirectoryObserver = new LogDirectoryObserver(getActivity().getFilesDir().getAbsolutePath());
}
@Override
@ -65,7 +69,23 @@ public class LogFragment extends Fragment implements Runnable
public void onStart()
{
super.onStart();
mLogView.setText("");
startLogReader();
mDirectoryObserver.startWatching();
}
@Override
public void onStop()
{
super.onStop();
mDirectoryObserver.stopWatching();
stopLogReader();
}
/**
* Start reading from the log file
*/
private void startLogReader()
{
try
{
mReader = new BufferedReader(new FileReader(mLogFilePath));
@ -74,15 +94,18 @@ public class LogFragment extends Fragment implements Runnable
{
mReader = new BufferedReader(new StringReader(""));
}
mLogView.setText("");
mRunning = true;
mThread = new Thread(this);
mThread.start();
}
@Override
public void onStop()
/**
* Stop reading from the log file
*/
private void stopLogReader()
{
super.onStop();
try
{
mRunning = false;
@ -97,6 +120,7 @@ public class LogFragment extends Fragment implements Runnable
/**
* Write the given log line to the TextView. We strip the prefix off to save
* some space (it is not that helpful for regular users anyway).
*
* @param line log line to log
*/
public void logLine(final String line)
@ -126,7 +150,7 @@ public class LogFragment extends Fragment implements Runnable
while (mRunning)
{
try
{
{ /* this works as long as the file is not truncated */
String line = mReader.readLine();
if (line == null)
{ /* wait until there is more to log */
@ -143,4 +167,61 @@ public class LogFragment extends Fragment implements Runnable
}
}
}
/**
* FileObserver that checks for changes regarding the log file. Since charon
* truncates it (for which there is no explicit event) we check for any modification
* to the file, keep track of the file size and reopen it if it got smaller.
*/
private class LogDirectoryObserver extends FileObserver
{
private final File mFile;
private long mSize;
public LogDirectoryObserver(String path)
{
super(path, FileObserver.CREATE | FileObserver.MODIFY | FileObserver.DELETE);
mFile = new File(mLogFilePath);
mSize = mFile.length();
}
@Override
public void onEvent(int event, String path)
{
if (path == null || !path.equals(CharonVpnService.LOG_FILE))
{
return;
}
switch (event)
{ /* even though we only subscribed for these we check them,
* as strange events are sometimes received */
case FileObserver.CREATE:
case FileObserver.DELETE:
restartLogReader();
break;
case FileObserver.MODIFY:
/* if the size got smaller reopen the log file, as it was probably truncated */
long size = mFile.length();
if (size < mSize)
{
restartLogReader();
}
mSize = size;
break;
}
}
private void restartLogReader()
{
/* we are called from a separate thread, so we use the handler */
mLogHandler.post(new Runnable() {
@Override
public void run()
{
stopLogReader();
startLogReader();
}
});
}
}
}