2 * Copyright (C) 2012-2017 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 package org
.strongswan
.android
.ui
;
18 import android
.os
.Bundle
;
19 import android
.os
.FileObserver
;
20 import android
.os
.Handler
;
21 import android
.support
.v4
.app
.Fragment
;
22 import android
.view
.LayoutInflater
;
23 import android
.view
.View
;
24 import android
.view
.ViewGroup
;
25 import android
.widget
.TextView
;
27 import org
.strongswan
.android
.R
;
28 import org
.strongswan
.android
.logic
.CharonVpnService
;
30 import java
.io
.BufferedReader
;
32 import java
.io
.FileNotFoundException
;
33 import java
.io
.FileReader
;
34 import java
.io
.StringReader
;
35 import java
.util
.ArrayList
;
37 public class LogFragment
extends Fragment
implements Runnable
39 private String mLogFilePath
;
40 private Handler mLogHandler
;
41 private TextView mLogView
;
42 private LogScrollView mScrollView
;
43 private BufferedReader mReader
;
44 private Thread mThread
;
45 private volatile boolean mRunning
;
46 private FileObserver mDirectoryObserver
;
49 public void onCreate(Bundle savedInstanceState
)
51 super.onCreate(savedInstanceState
);
53 mLogFilePath
= getActivity().getFilesDir() + File
.separator
+ CharonVpnService
.LOG_FILE
;
54 /* use a handler to update the log view */
55 mLogHandler
= new Handler();
57 mDirectoryObserver
= new LogDirectoryObserver(getActivity().getFilesDir().getAbsolutePath());
61 public View
onCreateView(LayoutInflater inflater
, ViewGroup container
, Bundle savedInstanceState
)
63 View view
= inflater
.inflate(R
.layout
.log_fragment
, null);
64 mLogView
= (TextView
)view
.findViewById(R
.id
.log_view
);
65 mScrollView
= (LogScrollView
)view
.findViewById(R
.id
.scroll_view
);
74 mDirectoryObserver
.startWatching();
81 mDirectoryObserver
.stopWatching();
86 * Start reading from the log file
88 private void startLogReader()
92 mReader
= new BufferedReader(new FileReader(mLogFilePath
));
94 catch (FileNotFoundException e
)
96 mReader
= new BufferedReader(new StringReader(""));
101 mThread
= new Thread(this);
106 * Stop reading from the log file
108 private void stopLogReader()
116 catch (InterruptedException e
)
122 * Write the given log line to the TextView. We strip the prefix off to save
123 * some space (it is not that helpful for regular users anyway).
125 * @param lines log lines to log
127 public void logLines(final ArrayList
<String
> lines
)
129 mLogHandler
.post(new Runnable() {
133 mLogView
.beginBatchEdit();
134 for (String line
: lines
)
135 { /* strip off prefix (month=3, day=2, time=8, thread=2, spaces=3) */
136 mLogView
.append((line
.length() > 18 ? line
.substring(18) : line
) + '\n');
138 mLogView
.endBatchEdit();
139 /* calling autoScroll() directly does not work, probably because content
140 * is not yet updated, so we post this to be done later */
141 mScrollView
.post(new Runnable() {
145 mScrollView
.autoScroll();
155 ArrayList
<String
> lines
= null;
160 { /* this works as long as the file is not truncated */
161 String line
= mReader
.readLine();
169 /* wait until there is more to log */
176 lines
= new ArrayList
<>();
193 * FileObserver that checks for changes regarding the log file. Since charon
194 * truncates it (for which there is no explicit event) we check for any modification
195 * to the file, keep track of the file size and reopen it if it got smaller.
197 private class LogDirectoryObserver
extends FileObserver
199 private final File mFile
;
202 public LogDirectoryObserver(String path
)
204 super(path
, FileObserver
.CREATE
| FileObserver
.MODIFY
| FileObserver
.DELETE
);
205 mFile
= new File(mLogFilePath
);
206 mSize
= mFile
.length();
210 public void onEvent(int event
, String path
)
212 if (path
== null || !path
.equals(CharonVpnService
.LOG_FILE
))
217 { /* even though we only subscribed for these we check them,
218 * as strange events are sometimes received */
219 case FileObserver
.CREATE
:
220 case FileObserver
.DELETE
:
223 case FileObserver
.MODIFY
:
224 /* if the size got smaller reopen the log file, as it was probably truncated */
225 long size
= mFile
.length();
235 private void restartLogReader()
237 /* we are called from a separate thread, so we use the handler */
238 mLogHandler
.post(new Runnable() {