2016-01-05 12:40:02 +00:00
|
|
|
package eu.faircode.netguard;
|
|
|
|
|
2016-01-30 13:26:30 +00:00
|
|
|
/*
|
|
|
|
This file is part of NetGuard.
|
|
|
|
|
|
|
|
NetGuard is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
NetGuard is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with NetGuard. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2017-12-24 09:12:10 +00:00
|
|
|
Copyright 2015-2018 by Marcel Bokhorst (M66B)
|
2016-01-30 13:26:30 +00:00
|
|
|
*/
|
|
|
|
|
2016-01-05 12:40:02 +00:00
|
|
|
import android.content.ContentValues;
|
|
|
|
import android.content.Context;
|
2016-12-23 09:25:18 +00:00
|
|
|
import android.content.SharedPreferences;
|
2016-01-05 12:40:02 +00:00
|
|
|
import android.database.Cursor;
|
|
|
|
import android.database.sqlite.SQLiteDatabase;
|
2016-02-03 16:59:24 +00:00
|
|
|
import android.database.sqlite.SQLiteDoneException;
|
2016-01-05 12:40:02 +00:00
|
|
|
import android.database.sqlite.SQLiteOpenHelper;
|
2016-02-04 10:49:43 +00:00
|
|
|
import android.os.Handler;
|
|
|
|
import android.os.HandlerThread;
|
|
|
|
import android.os.Message;
|
2016-12-23 09:25:18 +00:00
|
|
|
import android.preference.PreferenceManager;
|
2016-01-05 12:40:02 +00:00
|
|
|
import android.util.Log;
|
|
|
|
|
2016-01-27 10:59:16 +00:00
|
|
|
import java.io.File;
|
2016-02-03 19:38:38 +00:00
|
|
|
import java.text.SimpleDateFormat;
|
2016-01-05 12:40:02 +00:00
|
|
|
import java.util.ArrayList;
|
2016-02-03 19:38:38 +00:00
|
|
|
import java.util.Date;
|
2017-03-26 11:59:43 +00:00
|
|
|
import java.util.HashMap;
|
2016-01-05 12:40:02 +00:00
|
|
|
import java.util.List;
|
2017-03-26 11:59:43 +00:00
|
|
|
import java.util.Map;
|
2016-02-10 12:24:15 +00:00
|
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
2016-01-05 12:40:02 +00:00
|
|
|
|
|
|
|
public class DatabaseHelper extends SQLiteOpenHelper {
|
|
|
|
private static final String TAG = "NetGuard.Database";
|
|
|
|
|
|
|
|
private static final String DB_NAME = "Netguard";
|
2017-11-05 15:43:51 +00:00
|
|
|
private static final int DB_VERSION = 21;
|
2016-01-05 12:40:02 +00:00
|
|
|
|
2016-01-27 10:59:16 +00:00
|
|
|
private static boolean once = true;
|
2016-01-30 13:26:30 +00:00
|
|
|
private static List<LogChangedListener> logChangedListeners = new ArrayList<>();
|
|
|
|
private static List<AccessChangedListener> accessChangedListeners = new ArrayList<>();
|
2016-02-13 11:42:26 +00:00
|
|
|
private static List<ForwardChangedListener> forwardChangedListeners = new ArrayList<>();
|
2016-01-05 12:40:02 +00:00
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
private static HandlerThread hthread = null;
|
|
|
|
private static Handler handler = null;
|
|
|
|
|
2017-08-05 08:27:27 +00:00
|
|
|
private static final Map<Integer, Long> mapUidHosts = new HashMap<>();
|
2017-03-26 14:43:26 +00:00
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
private final static int MSG_LOG = 1;
|
|
|
|
private final static int MSG_ACCESS = 2;
|
2016-02-13 11:42:26 +00:00
|
|
|
private final static int MSG_FORWARD = 3;
|
2016-01-05 12:40:02 +00:00
|
|
|
|
2016-12-23 09:25:18 +00:00
|
|
|
private SharedPreferences prefs;
|
|
|
|
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
|
2016-02-10 12:24:15 +00:00
|
|
|
|
2016-02-09 14:29:28 +00:00
|
|
|
static {
|
|
|
|
hthread = new HandlerThread("DatabaseHelper");
|
|
|
|
hthread.start();
|
|
|
|
handler = new Handler(hthread.getLooper()) {
|
|
|
|
@Override
|
|
|
|
public void handleMessage(Message msg) {
|
|
|
|
handleChangedNotification(msg);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2016-02-10 11:50:51 +00:00
|
|
|
private static DatabaseHelper dh = null;
|
|
|
|
|
|
|
|
public static DatabaseHelper getInstance(Context context) {
|
|
|
|
if (dh == null)
|
|
|
|
dh = new DatabaseHelper(context.getApplicationContext());
|
|
|
|
return dh;
|
|
|
|
}
|
|
|
|
|
2017-03-26 14:43:26 +00:00
|
|
|
public static void clearCache() {
|
|
|
|
synchronized (mapUidHosts) {
|
|
|
|
mapUidHosts.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-10 11:50:51 +00:00
|
|
|
@Override
|
|
|
|
public void close() {
|
|
|
|
Log.w(TAG, "Database is being closed");
|
|
|
|
}
|
|
|
|
|
|
|
|
private DatabaseHelper(Context context) {
|
2016-01-05 12:40:02 +00:00
|
|
|
super(context, DB_NAME, null, DB_VERSION);
|
2016-12-23 09:25:18 +00:00
|
|
|
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
2016-01-27 10:59:16 +00:00
|
|
|
|
|
|
|
if (!once) {
|
|
|
|
once = true;
|
|
|
|
|
|
|
|
File dbfile = context.getDatabasePath(DB_NAME);
|
|
|
|
if (dbfile.exists()) {
|
|
|
|
Log.w(TAG, "Deleting " + dbfile);
|
|
|
|
dbfile.delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
File dbjournal = context.getDatabasePath(DB_NAME + "-journal");
|
|
|
|
if (dbjournal.exists()) {
|
|
|
|
Log.w(TAG, "Deleting " + dbjournal);
|
|
|
|
dbjournal.delete();
|
|
|
|
}
|
|
|
|
}
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onCreate(SQLiteDatabase db) {
|
2016-01-27 10:59:16 +00:00
|
|
|
Log.i(TAG, "Creating database " + DB_NAME + " version " + DB_VERSION);
|
2016-01-05 12:40:02 +00:00
|
|
|
createTableLog(db);
|
2016-01-27 10:59:16 +00:00
|
|
|
createTableAccess(db);
|
2016-02-03 17:58:15 +00:00
|
|
|
createTableDns(db);
|
2016-02-08 20:14:13 +00:00
|
|
|
createTableForward(db);
|
2017-11-05 15:43:51 +00:00
|
|
|
createTableApp(db);
|
2016-01-27 10:59:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onConfigure(SQLiteDatabase db) {
|
2016-02-13 12:09:23 +00:00
|
|
|
db.enableWriteAheadLogging();
|
2016-01-27 10:59:16 +00:00
|
|
|
super.onConfigure(db);
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void createTableLog(SQLiteDatabase db) {
|
2016-01-27 10:59:16 +00:00
|
|
|
Log.i(TAG, "Creating log table");
|
2016-01-05 12:40:02 +00:00
|
|
|
db.execSQL("CREATE TABLE log (" +
|
|
|
|
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
|
|
|
", time INTEGER NOT NULL" +
|
2016-01-07 06:47:00 +00:00
|
|
|
", version INTEGER NULL" +
|
|
|
|
", protocol INTEGER NULL" +
|
2016-01-08 07:03:04 +00:00
|
|
|
", flags TEXT" +
|
2016-01-22 09:37:57 +00:00
|
|
|
", saddr TEXT" +
|
|
|
|
", sport INTEGER NULL" +
|
|
|
|
", daddr TEXT" +
|
|
|
|
", dport INTEGER NULL" +
|
2016-01-30 09:59:19 +00:00
|
|
|
", dname TEXT NULL" +
|
2016-01-07 06:47:00 +00:00
|
|
|
", uid INTEGER NULL" +
|
2016-01-26 10:41:03 +00:00
|
|
|
", data TEXT" +
|
2016-01-22 09:37:57 +00:00
|
|
|
", allowed INTEGER NULL" +
|
2016-01-08 16:08:11 +00:00
|
|
|
", connection INTEGER NULL" +
|
2016-01-09 07:36:17 +00:00
|
|
|
", interactive INTEGER NULL" +
|
2016-01-05 12:40:02 +00:00
|
|
|
");");
|
|
|
|
db.execSQL("CREATE INDEX idx_log_time ON log(time)");
|
2016-01-26 10:41:03 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_log_dest ON log(daddr)");
|
2016-02-03 15:51:01 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_log_dname ON log(dname)");
|
2016-02-17 14:47:53 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_log_dport ON log(dport)");
|
2016-01-26 10:41:03 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_log_uid ON log(uid)");
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
|
|
|
|
2016-01-27 10:59:16 +00:00
|
|
|
private void createTableAccess(SQLiteDatabase db) {
|
|
|
|
Log.i(TAG, "Creating access table");
|
|
|
|
db.execSQL("CREATE TABLE access (" +
|
|
|
|
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
|
|
|
", uid INTEGER NOT NULL" +
|
2016-02-05 19:44:12 +00:00
|
|
|
", version INTEGER NOT NULL" +
|
|
|
|
", protocol INTEGER NOT NULL" +
|
2016-01-27 10:59:16 +00:00
|
|
|
", daddr TEXT NOT NULL" +
|
2016-02-05 19:44:12 +00:00
|
|
|
", dport INTEGER NOT NULL" +
|
2016-01-27 10:59:16 +00:00
|
|
|
", time INTEGER NOT NULL" +
|
2016-01-31 08:04:54 +00:00
|
|
|
", allowed INTEGER NULL" +
|
2016-01-30 11:46:00 +00:00
|
|
|
", block INTEGER NOT NULL" +
|
2016-02-15 16:48:53 +00:00
|
|
|
", sent INTEGER NULL" +
|
|
|
|
", received INTEGER NULL" +
|
2016-02-19 19:58:11 +00:00
|
|
|
", connections INTEGER NULL" +
|
2016-01-27 10:59:16 +00:00
|
|
|
");");
|
2016-02-05 19:44:12 +00:00
|
|
|
db.execSQL("CREATE UNIQUE INDEX idx_access ON access(uid, version, protocol, daddr, dport)");
|
2016-03-09 16:51:49 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_access_daddr ON access(daddr)");
|
2016-02-19 07:03:41 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_access_block ON access(block)");
|
2016-01-27 10:59:16 +00:00
|
|
|
}
|
|
|
|
|
2016-02-03 16:09:12 +00:00
|
|
|
private void createTableDns(SQLiteDatabase db) {
|
|
|
|
Log.i(TAG, "Creating dns table");
|
|
|
|
db.execSQL("CREATE TABLE dns (" +
|
|
|
|
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
|
|
|
", time INTEGER NOT NULL" +
|
|
|
|
", qname TEXT NOT NULL" +
|
|
|
|
", aname TEXT NOT NULL" +
|
|
|
|
", resource TEXT NOT NULL" +
|
|
|
|
", ttl INTEGER NULL" +
|
|
|
|
");");
|
2016-02-19 07:03:41 +00:00
|
|
|
db.execSQL("CREATE UNIQUE INDEX idx_dns ON dns(qname, aname, resource)");
|
|
|
|
db.execSQL("CREATE INDEX idx_dns_resource ON dns(resource)");
|
2016-02-03 16:09:12 +00:00
|
|
|
}
|
|
|
|
|
2016-02-08 15:34:54 +00:00
|
|
|
private void createTableForward(SQLiteDatabase db) {
|
|
|
|
Log.i(TAG, "Creating forward table");
|
|
|
|
db.execSQL("CREATE TABLE forward (" +
|
|
|
|
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
|
|
|
", protocol INTEGER NOT NULL" +
|
|
|
|
", dport INTEGER NOT NULL" +
|
|
|
|
", raddr TEXT NOT NULL" +
|
|
|
|
", rport INTEGER NOT NULL" +
|
|
|
|
", ruid INTEGER NOT NULL" +
|
|
|
|
");");
|
|
|
|
db.execSQL("CREATE UNIQUE INDEX idx_forward ON forward(protocol, dport)");
|
|
|
|
}
|
|
|
|
|
2017-11-05 15:43:51 +00:00
|
|
|
private void createTableApp(SQLiteDatabase db) {
|
|
|
|
Log.i(TAG, "Creating app table");
|
|
|
|
db.execSQL("CREATE TABLE app (" +
|
|
|
|
" ID INTEGER PRIMARY KEY AUTOINCREMENT" +
|
|
|
|
", package TEXT" +
|
|
|
|
", label TEXT" +
|
|
|
|
", system INTEGER NOT NULL" +
|
|
|
|
", internet INTEGER NOT NULL" +
|
|
|
|
", enabled INTEGER NOT NULL" +
|
|
|
|
");");
|
|
|
|
db.execSQL("CREATE UNIQUE INDEX idx_package ON app(package)");
|
|
|
|
}
|
|
|
|
|
2016-02-04 14:09:26 +00:00
|
|
|
private boolean columnExists(SQLiteDatabase db, String table, String column) {
|
|
|
|
Cursor cursor = null;
|
|
|
|
try {
|
|
|
|
cursor = db.rawQuery("SELECT * FROM " + table + " LIMIT 0", null);
|
|
|
|
return (cursor.getColumnIndex(column) >= 0);
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
return false;
|
|
|
|
} finally {
|
|
|
|
if (cursor != null)
|
|
|
|
cursor.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-05 12:40:02 +00:00
|
|
|
@Override
|
|
|
|
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
2016-01-27 10:59:16 +00:00
|
|
|
Log.i(TAG, DB_NAME + " upgrading from version " + oldVersion + " to " + newVersion);
|
2016-01-05 12:40:02 +00:00
|
|
|
|
|
|
|
db.beginTransaction();
|
|
|
|
try {
|
2016-01-07 06:47:00 +00:00
|
|
|
if (oldVersion < 2) {
|
2016-02-04 14:09:26 +00:00
|
|
|
if (!columnExists(db, "log", "version"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN version INTEGER NULL");
|
|
|
|
if (!columnExists(db, "log", "protocol"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN protocol INTEGER NULL");
|
|
|
|
if (!columnExists(db, "log", "uid"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN uid INTEGER NULL");
|
2016-01-07 06:47:00 +00:00
|
|
|
oldVersion = 2;
|
|
|
|
}
|
2016-01-08 07:03:04 +00:00
|
|
|
if (oldVersion < 3) {
|
2016-02-04 14:09:26 +00:00
|
|
|
if (!columnExists(db, "log", "port"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN port INTEGER NULL");
|
|
|
|
if (!columnExists(db, "log", "flags"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN flags TEXT");
|
2016-01-08 07:03:04 +00:00
|
|
|
oldVersion = 3;
|
|
|
|
}
|
2016-01-08 16:08:11 +00:00
|
|
|
if (oldVersion < 4) {
|
2016-02-04 14:09:26 +00:00
|
|
|
if (!columnExists(db, "log", "connection"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN connection INTEGER NULL");
|
2016-01-08 16:08:11 +00:00
|
|
|
oldVersion = 4;
|
|
|
|
}
|
2016-01-09 07:36:17 +00:00
|
|
|
if (oldVersion < 5) {
|
2016-02-04 14:09:26 +00:00
|
|
|
if (!columnExists(db, "log", "interactive"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN interactive INTEGER NULL");
|
2016-01-09 07:36:17 +00:00
|
|
|
oldVersion = 5;
|
|
|
|
}
|
2016-01-19 19:58:51 +00:00
|
|
|
if (oldVersion < 6) {
|
2016-02-04 14:09:26 +00:00
|
|
|
if (!columnExists(db, "log", "allowed"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN allowed INTEGER NULL");
|
2016-01-19 19:58:51 +00:00
|
|
|
oldVersion = 6;
|
|
|
|
}
|
2016-01-22 09:37:57 +00:00
|
|
|
if (oldVersion < 7) {
|
|
|
|
db.execSQL("DROP TABLE log");
|
|
|
|
createTableLog(db);
|
2016-02-04 14:09:26 +00:00
|
|
|
oldVersion = 8;
|
2016-01-22 09:37:57 +00:00
|
|
|
}
|
2016-01-26 10:41:03 +00:00
|
|
|
if (oldVersion < 8) {
|
2016-02-04 14:09:26 +00:00
|
|
|
if (!columnExists(db, "log", "data"))
|
|
|
|
db.execSQL("ALTER TABLE log ADD COLUMN data TEXT");
|
2016-01-26 10:41:03 +00:00
|
|
|
db.execSQL("DROP INDEX idx_log_source");
|
|
|
|
db.execSQL("DROP INDEX idx_log_dest");
|
2016-02-04 14:09:26 +00:00
|
|
|
db.execSQL("CREATE INDEX idx_log_source ON log(saddr)");
|
|
|
|
db.execSQL("CREATE INDEX idx_log_dest ON log(daddr)");
|
2016-02-04 06:40:18 +00:00
|
|
|
db.execSQL("CREATE INDEX IF NOT EXISTS idx_log_uid ON log(uid)");
|
2016-01-26 10:41:03 +00:00
|
|
|
oldVersion = 8;
|
|
|
|
}
|
2016-01-27 10:59:16 +00:00
|
|
|
if (oldVersion < 9) {
|
|
|
|
createTableAccess(db);
|
|
|
|
oldVersion = 9;
|
|
|
|
}
|
2016-01-30 09:59:19 +00:00
|
|
|
if (oldVersion < 10) {
|
|
|
|
db.execSQL("DROP TABLE log");
|
|
|
|
db.execSQL("DROP TABLE access");
|
|
|
|
createTableLog(db);
|
|
|
|
createTableAccess(db);
|
|
|
|
oldVersion = 10;
|
|
|
|
}
|
2016-01-31 08:04:54 +00:00
|
|
|
if (oldVersion < 12) {
|
2016-01-30 11:46:00 +00:00
|
|
|
db.execSQL("DROP TABLE access");
|
|
|
|
createTableAccess(db);
|
2016-01-31 08:04:54 +00:00
|
|
|
oldVersion = 12;
|
2016-01-30 11:46:00 +00:00
|
|
|
}
|
2016-02-03 15:51:01 +00:00
|
|
|
if (oldVersion < 13) {
|
2016-02-04 06:40:18 +00:00
|
|
|
db.execSQL("CREATE INDEX IF NOT EXISTS idx_log_dport ON log(dport)");
|
|
|
|
db.execSQL("CREATE INDEX IF NOT EXISTS idx_log_dname ON log(dname)");
|
2016-02-03 15:51:01 +00:00
|
|
|
oldVersion = 13;
|
|
|
|
}
|
2016-02-03 16:09:12 +00:00
|
|
|
if (oldVersion < 14) {
|
|
|
|
createTableDns(db);
|
|
|
|
oldVersion = 14;
|
|
|
|
}
|
2016-02-05 19:44:12 +00:00
|
|
|
if (oldVersion < 15) {
|
|
|
|
db.execSQL("DROP TABLE access");
|
|
|
|
createTableAccess(db);
|
|
|
|
oldVersion = 15;
|
|
|
|
}
|
2016-02-08 15:34:54 +00:00
|
|
|
if (oldVersion < 16) {
|
|
|
|
createTableForward(db);
|
|
|
|
oldVersion = 16;
|
|
|
|
}
|
2016-02-15 16:48:53 +00:00
|
|
|
if (oldVersion < 17) {
|
|
|
|
if (!columnExists(db, "access", "sent"))
|
|
|
|
db.execSQL("ALTER TABLE access ADD COLUMN sent INTEGER NULL");
|
|
|
|
if (!columnExists(db, "access", "received"))
|
|
|
|
db.execSQL("ALTER TABLE access ADD COLUMN received INTEGER NULL");
|
|
|
|
oldVersion = 17;
|
|
|
|
}
|
2016-02-19 07:03:41 +00:00
|
|
|
if (oldVersion < 18) {
|
|
|
|
db.execSQL("CREATE INDEX IF NOT EXISTS idx_access_block ON access(block)");
|
|
|
|
db.execSQL("DROP INDEX idx_dns");
|
|
|
|
db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS idx_dns ON dns(qname, aname, resource)");
|
|
|
|
db.execSQL("CREATE INDEX IF NOT EXISTS idx_dns_resource ON dns(resource)");
|
|
|
|
oldVersion = 18;
|
|
|
|
}
|
2016-02-19 19:58:11 +00:00
|
|
|
if (oldVersion < 19) {
|
|
|
|
if (!columnExists(db, "access", "connections"))
|
|
|
|
db.execSQL("ALTER TABLE access ADD COLUMN connections INTEGER NULL");
|
|
|
|
oldVersion = 19;
|
|
|
|
}
|
2016-03-09 16:51:49 +00:00
|
|
|
if (oldVersion < 20) {
|
|
|
|
db.execSQL("CREATE INDEX IF NOT EXISTS idx_access_daddr ON access(daddr)");
|
|
|
|
oldVersion = 20;
|
|
|
|
}
|
2017-11-05 15:43:51 +00:00
|
|
|
if (oldVersion < 21) {
|
|
|
|
createTableApp(db);
|
|
|
|
oldVersion = 21;
|
|
|
|
}
|
2016-01-07 06:47:00 +00:00
|
|
|
|
2016-01-27 10:59:16 +00:00
|
|
|
if (oldVersion == DB_VERSION) {
|
|
|
|
db.setVersion(oldVersion);
|
|
|
|
db.setTransactionSuccessful();
|
2016-02-22 15:39:49 +00:00
|
|
|
Log.i(TAG, DB_NAME + " upgraded to " + DB_VERSION);
|
2016-01-27 10:59:16 +00:00
|
|
|
} else
|
|
|
|
throw new IllegalArgumentException(DB_NAME + " upgraded to " + oldVersion + " but required " + DB_VERSION);
|
2016-01-05 12:40:02 +00:00
|
|
|
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-27 10:59:16 +00:00
|
|
|
// Log
|
2016-01-05 12:40:02 +00:00
|
|
|
|
2016-02-10 12:24:15 +00:00
|
|
|
public void insertLog(Packet packet, String dname, int connection, boolean interactive) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-01-05 12:40:02 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("time", packet.time);
|
|
|
|
cv.put("version", packet.version);
|
2016-01-05 12:40:02 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (packet.protocol < 0)
|
|
|
|
cv.putNull("protocol");
|
|
|
|
else
|
|
|
|
cv.put("protocol", packet.protocol);
|
2016-01-05 12:40:02 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
cv.put("flags", packet.flags);
|
2016-01-07 06:47:00 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
cv.put("saddr", packet.saddr);
|
|
|
|
if (packet.sport < 0)
|
|
|
|
cv.putNull("sport");
|
|
|
|
else
|
|
|
|
cv.put("sport", packet.sport);
|
2016-01-22 09:37:57 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
cv.put("daddr", packet.daddr);
|
|
|
|
if (packet.dport < 0)
|
|
|
|
cv.putNull("dport");
|
|
|
|
else
|
|
|
|
cv.put("dport", packet.dport);
|
2016-01-08 07:03:04 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (dname == null)
|
|
|
|
cv.putNull("dname");
|
|
|
|
else
|
|
|
|
cv.put("dname", dname);
|
2016-01-08 07:03:04 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
cv.put("data", packet.data);
|
2016-01-30 09:59:19 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (packet.uid < 0)
|
|
|
|
cv.putNull("uid");
|
|
|
|
else
|
|
|
|
cv.put("uid", packet.uid);
|
2016-01-26 10:41:03 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
cv.put("allowed", packet.allowed ? 1 : 0);
|
2016-01-22 09:37:57 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
cv.put("connection", connection);
|
|
|
|
cv.put("interactive", interactive ? 1 : 0);
|
2016-01-07 06:47:00 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (db.insert("log", null, cv) == -1)
|
|
|
|
Log.e(TAG, "Insert log failed");
|
2016-01-08 16:08:11 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
notifyLogChanged();
|
2016-01-05 21:53:22 +00:00
|
|
|
}
|
|
|
|
|
2017-03-26 09:17:35 +00:00
|
|
|
public void clearLog(int uid) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-13 12:09:23 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
2017-03-26 09:17:35 +00:00
|
|
|
if (uid < 0)
|
|
|
|
db.delete("log", null, new String[]{});
|
|
|
|
else
|
|
|
|
db.delete("log", "uid = ?", new String[]{Integer.toString(uid)});
|
2016-02-13 12:09:23 +00:00
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-13 12:15:43 +00:00
|
|
|
|
|
|
|
db.execSQL("VACUUM");
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-01-07 05:41:12 +00:00
|
|
|
}
|
2016-01-05 21:53:22 +00:00
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
notifyLogChanged();
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
|
|
|
|
2016-02-29 09:20:17 +00:00
|
|
|
public void cleanupLog(long time) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-29 09:20:17 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
// There an index on time
|
|
|
|
int rows = db.delete("log", "time < ?", new String[]{Long.toString(time)});
|
|
|
|
Log.i(TAG, "Cleanup log" +
|
|
|
|
" before=" + SimpleDateFormat.getDateTimeInstance().format(new Date(time)) +
|
|
|
|
" rows=" + rows);
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-29 09:20:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-04 10:07:48 +00:00
|
|
|
public Cursor getLog(boolean udp, boolean tcp, boolean other, boolean allowed, boolean blocked) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is an index on time
|
|
|
|
// There is no index on protocol/allowed for write performance
|
2016-02-10 12:24:15 +00:00
|
|
|
String query = "SELECT ID AS _id, *";
|
|
|
|
query += " FROM log";
|
|
|
|
query += " WHERE (0 = 1";
|
|
|
|
if (udp)
|
|
|
|
query += " OR protocol = 17";
|
|
|
|
if (tcp)
|
|
|
|
query += " OR protocol = 6";
|
|
|
|
if (other)
|
|
|
|
query += " OR (protocol <> 6 AND protocol <> 17)";
|
|
|
|
query += ") AND (0 = 1";
|
|
|
|
if (allowed)
|
|
|
|
query += " OR allowed = 1";
|
|
|
|
if (blocked)
|
|
|
|
query += " OR allowed = 0";
|
|
|
|
query += ")";
|
|
|
|
query += " ORDER BY time DESC";
|
|
|
|
return db.rawQuery(query, new String[]{});
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
|
|
|
|
2016-01-26 20:20:16 +00:00
|
|
|
public Cursor searchLog(String find) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-19 07:03:41 +00:00
|
|
|
// There is an index on daddr, dname, dport and uid
|
2016-02-10 12:24:15 +00:00
|
|
|
String query = "SELECT ID AS _id, *";
|
|
|
|
query += " FROM log";
|
2016-02-14 09:03:43 +00:00
|
|
|
query += " WHERE daddr LIKE ? OR dname LIKE ? OR dport = ? OR uid = ?";
|
2016-02-10 12:24:15 +00:00
|
|
|
query += " ORDER BY time DESC";
|
2016-02-14 09:03:43 +00:00
|
|
|
return db.rawQuery(query, new String[]{"%" + find + "%", "%" + find + "%", find, find});
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-01-26 20:20:16 +00:00
|
|
|
}
|
|
|
|
|
2016-01-27 10:59:16 +00:00
|
|
|
// Access
|
|
|
|
|
2016-02-01 08:55:49 +00:00
|
|
|
public boolean updateAccess(Packet packet, String dname, int block) {
|
2016-01-30 18:52:31 +00:00
|
|
|
int rows;
|
2016-02-10 12:24:15 +00:00
|
|
|
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-01-27 10:59:16 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("time", packet.time);
|
|
|
|
cv.put("allowed", packet.allowed ? 1 : 0);
|
|
|
|
if (block >= 0)
|
2016-02-01 08:55:49 +00:00
|
|
|
cv.put("block", block);
|
2016-01-30 09:59:19 +00:00
|
|
|
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid, version, protocol, daddr and dport
|
2016-02-13 12:09:23 +00:00
|
|
|
rows = db.update("access", cv, "uid = ? AND version = ? AND protocol = ? AND daddr = ? AND dport = ?",
|
|
|
|
new String[]{
|
|
|
|
Integer.toString(packet.uid),
|
|
|
|
Integer.toString(packet.version),
|
|
|
|
Integer.toString(packet.protocol),
|
|
|
|
dname == null ? packet.daddr : dname,
|
|
|
|
Integer.toString(packet.dport)});
|
|
|
|
|
|
|
|
if (rows == 0) {
|
|
|
|
cv.put("uid", packet.uid);
|
|
|
|
cv.put("version", packet.version);
|
|
|
|
cv.put("protocol", packet.protocol);
|
|
|
|
cv.put("daddr", dname == null ? packet.daddr : dname);
|
|
|
|
cv.put("dport", packet.dport);
|
2017-04-03 07:33:18 +00:00
|
|
|
if (block < 0)
|
|
|
|
cv.put("block", block);
|
2016-02-13 12:09:23 +00:00
|
|
|
|
|
|
|
if (db.insert("access", null, cv) == -1)
|
|
|
|
Log.e(TAG, "Insert access failed");
|
|
|
|
} else if (rows != 1)
|
|
|
|
Log.e(TAG, "Update access failed rows=" + rows);
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-01-27 10:59:16 +00:00
|
|
|
}
|
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
notifyAccessChanged();
|
2016-01-30 18:52:31 +00:00
|
|
|
return (rows == 0);
|
2016-01-27 10:59:16 +00:00
|
|
|
}
|
|
|
|
|
2016-02-15 16:48:53 +00:00
|
|
|
public void updateUsage(Usage usage, String dname) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-15 16:48:53 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid, version, protocol, daddr and dport
|
2016-02-15 16:48:53 +00:00
|
|
|
String selection = "uid = ? AND version = ? AND protocol = ? AND daddr = ? AND dport = ?";
|
|
|
|
String[] selectionArgs = new String[]{
|
|
|
|
Integer.toString(usage.Uid),
|
|
|
|
Integer.toString(usage.Version),
|
|
|
|
Integer.toString(usage.Protocol),
|
|
|
|
dname == null ? usage.DAddr : dname,
|
|
|
|
Integer.toString(usage.DPort)
|
|
|
|
};
|
|
|
|
|
2016-02-19 19:58:11 +00:00
|
|
|
Cursor cursor = db.query("access", new String[]{"sent", "received", "connections"}, selection, selectionArgs, null, null, null);
|
2016-02-15 16:48:53 +00:00
|
|
|
long sent = 0;
|
|
|
|
long received = 0;
|
2016-02-19 19:58:11 +00:00
|
|
|
int connections = 0;
|
2016-02-15 16:48:53 +00:00
|
|
|
int colSent = cursor.getColumnIndex("sent");
|
|
|
|
int colReceived = cursor.getColumnIndex("received");
|
2016-02-19 19:58:11 +00:00
|
|
|
int colConnections = cursor.getColumnIndex("connections");
|
2016-02-15 16:48:53 +00:00
|
|
|
if (cursor.moveToNext()) {
|
|
|
|
sent = cursor.isNull(colSent) ? 0 : cursor.getLong(colSent);
|
|
|
|
received = cursor.isNull(colReceived) ? 0 : cursor.getLong(colReceived);
|
2016-02-19 19:58:11 +00:00
|
|
|
connections = cursor.isNull(colConnections) ? 0 : cursor.getInt(colConnections);
|
2016-02-15 16:48:53 +00:00
|
|
|
}
|
|
|
|
cursor.close();
|
|
|
|
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("sent", sent + usage.Sent);
|
|
|
|
cv.put("received", received + usage.Received);
|
2016-02-19 19:58:11 +00:00
|
|
|
cv.put("connections", connections + 1);
|
2016-02-15 16:48:53 +00:00
|
|
|
|
|
|
|
int rows = db.update("access", cv, selection, selectionArgs);
|
|
|
|
if (rows != 1)
|
|
|
|
Log.e(TAG, "Update usage failed rows=" + rows);
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-15 16:48:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
notifyAccessChanged();
|
|
|
|
}
|
|
|
|
|
2016-02-10 12:24:15 +00:00
|
|
|
public void setAccess(long id, int block) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-01-30 13:26:30 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("block", block);
|
|
|
|
cv.put("allowed", -1);
|
2016-01-30 13:26:30 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (db.update("access", cv, "ID = ?", new String[]{Long.toString(id)}) != 1)
|
|
|
|
Log.e(TAG, "Set access failed");
|
2016-01-30 13:26:30 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-05 19:44:12 +00:00
|
|
|
}
|
2016-01-30 13:26:30 +00:00
|
|
|
|
2016-02-05 19:44:12 +00:00
|
|
|
notifyAccessChanged();
|
|
|
|
}
|
|
|
|
|
2016-02-10 12:24:15 +00:00
|
|
|
public void clearAccess() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-13 12:09:23 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
db.delete("access", null, null);
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-01-30 13:26:30 +00:00
|
|
|
}
|
|
|
|
|
2016-02-05 19:44:12 +00:00
|
|
|
notifyAccessChanged();
|
2016-01-30 13:26:30 +00:00
|
|
|
}
|
|
|
|
|
2016-04-11 06:20:54 +00:00
|
|
|
public void clearAccess(int uid, boolean keeprules) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-13 12:09:23 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid
|
2016-03-09 16:51:49 +00:00
|
|
|
// There is an index on block
|
2016-04-11 06:20:54 +00:00
|
|
|
if (keeprules)
|
|
|
|
db.delete("access", "uid = ? AND block < 0", new String[]{Integer.toString(uid)});
|
|
|
|
else
|
|
|
|
db.delete("access", "uid = ?", new String[]{Integer.toString(uid)});
|
2016-02-13 12:09:23 +00:00
|
|
|
|
2016-02-15 18:49:33 +00:00
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-15 18:49:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
notifyAccessChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void resetUsage(int uid) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-15 18:49:33 +00:00
|
|
|
try {
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid
|
2016-02-15 18:49:33 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.putNull("sent");
|
|
|
|
cv.putNull("received");
|
2016-02-20 07:36:34 +00:00
|
|
|
cv.putNull("connections");
|
2016-02-15 18:49:33 +00:00
|
|
|
db.update("access", cv,
|
|
|
|
(uid < 0 ? null : "uid = ?"),
|
|
|
|
(uid < 0 ? null : new String[]{Integer.toString(uid)}));
|
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-01-30 13:26:30 +00:00
|
|
|
}
|
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
notifyAccessChanged();
|
2016-01-30 13:26:30 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 14:17:09 +00:00
|
|
|
public Cursor getAccess(int uid) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid
|
|
|
|
// There is no index on time for write performance
|
2017-03-08 21:04:43 +00:00
|
|
|
String query = "SELECT a.ID AS _id, a.*";
|
2017-03-17 09:00:44 +00:00
|
|
|
query += ", (SELECT COUNT(DISTINCT d.qname) FROM dns d WHERE d.resource IN (SELECT d1.resource FROM dns d1 WHERE d1.qname = a.daddr)) count";
|
2017-03-08 21:04:43 +00:00
|
|
|
query += " FROM access a";
|
|
|
|
query += " WHERE a.uid = ?";
|
|
|
|
query += " ORDER BY a.time DESC";
|
2016-02-10 12:24:15 +00:00
|
|
|
query += " LIMIT 50";
|
2017-11-05 14:17:09 +00:00
|
|
|
return db.rawQuery(query, new String[]{Integer.toString(uid)});
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-01-27 10:59:16 +00:00
|
|
|
}
|
|
|
|
|
2016-01-30 13:26:30 +00:00
|
|
|
public Cursor getAccess() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid
|
2016-02-19 07:03:41 +00:00
|
|
|
// There is an index on block
|
2016-02-10 12:24:15 +00:00
|
|
|
return db.query("access", null, "block >= 0", null, null, null, "uid");
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-01-30 13:26:30 +00:00
|
|
|
}
|
|
|
|
|
2017-08-04 06:24:03 +00:00
|
|
|
public Cursor getAccessUnset(int uid, int limit, long since) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-03-09 16:51:49 +00:00
|
|
|
// There is a segmented index on uid, block and daddr
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is no index on allowed and time for write performance
|
2016-02-10 12:24:15 +00:00
|
|
|
String query = "SELECT MAX(time) AS time, daddr, allowed";
|
|
|
|
query += " FROM access";
|
|
|
|
query += " WHERE uid = ?";
|
|
|
|
query += " AND block < 0";
|
2017-08-04 06:24:03 +00:00
|
|
|
query += " AND time >= ?";
|
2016-02-10 12:24:15 +00:00
|
|
|
query += " GROUP BY daddr, allowed";
|
|
|
|
query += " ORDER BY time DESC";
|
2016-02-22 13:16:41 +00:00
|
|
|
if (limit > 0)
|
|
|
|
query += " LIMIT " + limit;
|
2017-08-04 06:24:03 +00:00
|
|
|
return db.rawQuery(query, new String[]{Integer.toString(uid), Long.toString(since)});
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-01-30 18:52:31 +00:00
|
|
|
}
|
|
|
|
|
2017-03-26 11:59:43 +00:00
|
|
|
public long getHostCount(int uid, boolean usecache) {
|
|
|
|
if (usecache)
|
|
|
|
synchronized (mapUidHosts) {
|
|
|
|
if (mapUidHosts.containsKey(uid))
|
|
|
|
return mapUidHosts.get(uid);
|
|
|
|
}
|
|
|
|
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on uid
|
2016-02-19 07:03:41 +00:00
|
|
|
// There is an index on block
|
2017-03-26 11:59:43 +00:00
|
|
|
long hosts = db.compileStatement("SELECT COUNT(*) FROM access WHERE block >= 0 AND uid =" + uid).simpleQueryForLong();
|
|
|
|
synchronized (mapUidHosts) {
|
|
|
|
mapUidHosts.put(uid, hosts);
|
|
|
|
}
|
|
|
|
return hosts;
|
2016-02-14 14:54:23 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-14 14:54:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-08 15:34:54 +00:00
|
|
|
// DNS
|
|
|
|
|
2016-03-09 16:51:49 +00:00
|
|
|
public boolean insertDns(ResourceRecord rr) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-03 16:09:12 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
2016-11-11 19:02:15 +00:00
|
|
|
int ttl = rr.TTL;
|
2016-12-23 09:25:18 +00:00
|
|
|
|
2017-02-04 08:34:07 +00:00
|
|
|
int min = Integer.parseInt(prefs.getString("ttl", "259200"));
|
2016-12-23 09:25:18 +00:00
|
|
|
if (ttl < min)
|
|
|
|
ttl = min;
|
2016-11-11 19:02:15 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("time", rr.Time);
|
2016-11-11 19:02:15 +00:00
|
|
|
cv.put("ttl", ttl * 1000L);
|
2016-02-03 16:09:12 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
int rows = db.update("dns", cv, "qname = ? AND aname = ? AND resource = ?",
|
|
|
|
new String[]{rr.QName, rr.AName, rr.Resource});
|
2016-02-03 16:09:12 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (rows == 0) {
|
|
|
|
cv.put("qname", rr.QName);
|
|
|
|
cv.put("aname", rr.AName);
|
|
|
|
cv.put("resource", rr.Resource);
|
2016-02-03 16:09:12 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
if (db.insert("dns", null, cv) == -1)
|
|
|
|
Log.e(TAG, "Insert dns failed");
|
|
|
|
} else if (rows != 1)
|
|
|
|
Log.e(TAG, "Update dns failed rows=" + rows);
|
2016-02-03 16:09:12 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
db.setTransactionSuccessful();
|
2016-03-09 16:51:49 +00:00
|
|
|
|
|
|
|
return (rows == 0);
|
2016-02-13 12:09:23 +00:00
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-03 16:09:12 +00:00
|
|
|
}
|
|
|
|
}
|
2016-02-03 06:19:28 +00:00
|
|
|
|
2016-11-11 11:38:55 +00:00
|
|
|
public void cleanupDns() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-03 19:38:38 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is no index on time for write performance
|
2016-11-11 11:38:55 +00:00
|
|
|
long now = new Date().getTime();
|
|
|
|
db.execSQL("DELETE FROM dns WHERE time + ttl < " + now);
|
|
|
|
Log.i(TAG, "Cleanup DNS");
|
2016-02-13 12:09:23 +00:00
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-11-10 07:54:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void clearDns() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-11-10 07:54:32 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
db.delete("dns", null, new String[]{});
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-03 19:38:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-25 07:52:31 +00:00
|
|
|
public String getQName(int uid, String ip) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-03 16:59:24 +00:00
|
|
|
try {
|
2016-02-10 12:24:15 +00:00
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on resource
|
2017-02-25 07:52:31 +00:00
|
|
|
// There is an index on access.daddr
|
|
|
|
String query = "SELECT d.qname";
|
|
|
|
query += " FROM dns AS d";
|
|
|
|
query += " LEFT JOIN access AS a";
|
|
|
|
query += " ON a.daddr = d.qname AND a.uid = " + uid;
|
|
|
|
query += " WHERE d.resource = '" + ip.replace("'", "''") + "'";
|
2017-03-09 06:15:23 +00:00
|
|
|
query += " ORDER BY CASE a.daddr WHEN NULL THEN 1 ELSE 0 END, d.qname";
|
2016-02-29 19:29:01 +00:00
|
|
|
query += " LIMIT 1";
|
|
|
|
return db.compileStatement(query).simpleQueryForString();
|
2016-02-03 16:59:24 +00:00
|
|
|
} catch (SQLiteDoneException ignored) {
|
|
|
|
// Not found
|
|
|
|
return null;
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-03 16:59:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-17 09:00:44 +00:00
|
|
|
public Cursor getAlternateQNames(String qname) {
|
|
|
|
lock.readLock().lock();
|
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
|
|
String query = "SELECT DISTINCT d2.qname";
|
|
|
|
query += " FROM dns d1";
|
|
|
|
query += " JOIN dns d2";
|
|
|
|
query += " ON d2.resource = d1.resource AND d2.id <> d1.id";
|
|
|
|
query += " WHERE d1.qname = ?";
|
|
|
|
query += " ORDER BY d2.qname";
|
|
|
|
return db.rawQuery(query, new String[]{qname});
|
|
|
|
} finally {
|
|
|
|
lock.readLock().unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-03 16:59:24 +00:00
|
|
|
public Cursor getDns() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-13 06:54:44 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2017-03-09 06:15:23 +00:00
|
|
|
// There is an index on resource
|
2016-02-17 14:47:53 +00:00
|
|
|
// There is a segmented index on qname
|
2016-02-13 06:54:44 +00:00
|
|
|
String query = "SELECT ID AS _id, *";
|
|
|
|
query += " FROM dns";
|
2017-03-09 06:15:23 +00:00
|
|
|
query += " ORDER BY resource, qname";
|
2016-02-13 06:54:44 +00:00
|
|
|
return db.rawQuery(query, new String[]{});
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-13 06:54:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-09 16:51:49 +00:00
|
|
|
public Cursor getAccessDns(String dname) {
|
2016-11-11 11:38:55 +00:00
|
|
|
long now = new Date().getTime();
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
2016-02-03 16:59:24 +00:00
|
|
|
|
2016-02-19 07:03:41 +00:00
|
|
|
// There is a segmented index on dns.qname
|
2016-03-09 16:51:49 +00:00
|
|
|
// There is an index on access.daddr and access.block
|
2016-11-11 18:52:50 +00:00
|
|
|
String query = "SELECT a.uid, a.version, a.protocol, a.daddr, d.resource, a.dport, a.block, d.time, d.ttl";
|
2016-02-10 12:24:15 +00:00
|
|
|
query += " FROM access AS a";
|
2016-02-12 20:13:09 +00:00
|
|
|
query += " LEFT JOIN dns AS d";
|
2016-02-10 12:24:15 +00:00
|
|
|
query += " ON d.qname = a.daddr";
|
|
|
|
query += " WHERE a.block >= 0";
|
2017-03-09 10:35:13 +00:00
|
|
|
query += " AND d.time + d.ttl >= " + now;
|
2016-03-09 16:51:49 +00:00
|
|
|
if (dname != null)
|
|
|
|
query += " AND a.daddr = ?";
|
2016-02-03 16:59:24 +00:00
|
|
|
|
2017-03-09 10:35:13 +00:00
|
|
|
return db.rawQuery(query, dname == null ? new String[]{} : new String[]{dname});
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-02-03 16:59:24 +00:00
|
|
|
}
|
|
|
|
|
2016-02-08 15:34:54 +00:00
|
|
|
// Forward
|
|
|
|
|
2016-02-10 12:24:15 +00:00
|
|
|
public void addForward(int protocol, int dport, String raddr, int rport, int ruid) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-08 15:34:54 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("protocol", protocol);
|
|
|
|
cv.put("dport", dport);
|
|
|
|
cv.put("raddr", raddr);
|
|
|
|
cv.put("rport", rport);
|
|
|
|
cv.put("ruid", ruid);
|
|
|
|
|
|
|
|
if (db.insert("forward", null, cv) < 0)
|
|
|
|
Log.e(TAG, "Insert forward failed");
|
2016-02-08 15:34:54 +00:00
|
|
|
|
2016-02-13 12:09:23 +00:00
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-08 15:34:54 +00:00
|
|
|
}
|
2016-02-13 11:42:26 +00:00
|
|
|
|
|
|
|
notifyForwardChanged();
|
2016-02-08 15:34:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-29 11:06:12 +00:00
|
|
|
public void deleteForward() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-29 11:06:12 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
db.delete("forward", null, null);
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-29 11:06:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
notifyForwardChanged();
|
|
|
|
}
|
|
|
|
|
2016-02-10 12:24:15 +00:00
|
|
|
public void deleteForward(int protocol, int dport) {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
2016-02-08 15:34:54 +00:00
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
2016-02-13 12:09:23 +00:00
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
db.delete("forward", "protocol = ? AND dport = ?",
|
|
|
|
new String[]{Integer.toString(protocol), Integer.toString(dport)});
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
2016-02-10 12:24:15 +00:00
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.writeLock().unlock();
|
2016-02-08 15:34:54 +00:00
|
|
|
}
|
2016-02-13 11:42:26 +00:00
|
|
|
|
|
|
|
notifyForwardChanged();
|
2016-02-08 15:34:54 +00:00
|
|
|
}
|
|
|
|
|
2016-02-09 09:53:52 +00:00
|
|
|
public Cursor getForwarding() {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().lock();
|
2016-02-10 12:24:15 +00:00
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
|
|
String query = "SELECT ID AS _id, *";
|
|
|
|
query += " FROM forward";
|
|
|
|
query += " ORDER BY dport";
|
|
|
|
return db.rawQuery(query, new String[]{});
|
|
|
|
} finally {
|
2016-12-23 09:25:18 +00:00
|
|
|
lock.readLock().unlock();
|
2016-02-10 12:24:15 +00:00
|
|
|
}
|
2016-02-08 15:34:54 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 15:43:51 +00:00
|
|
|
public void addApp(String packageName, String label, boolean system, boolean internet, boolean enabled) {
|
|
|
|
lock.writeLock().lock();
|
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
ContentValues cv = new ContentValues();
|
|
|
|
cv.put("package", packageName);
|
|
|
|
if (label == null)
|
|
|
|
cv.putNull("label");
|
|
|
|
else
|
|
|
|
cv.put("label", label);
|
|
|
|
cv.put("system", system ? 1 : 0);
|
|
|
|
cv.put("internet", internet ? 1 : 0);
|
|
|
|
cv.put("enabled", enabled ? 1 : 0);
|
|
|
|
|
|
|
|
if (db.insert("app", null, cv) < 0)
|
|
|
|
Log.e(TAG, "Insert app failed");
|
|
|
|
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
lock.writeLock().unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public Cursor getApp(String packageName) {
|
|
|
|
lock.readLock().lock();
|
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getReadableDatabase();
|
|
|
|
|
|
|
|
// There is an index on package
|
|
|
|
String query = "SELECT * FROM app WHERE package = ?";
|
|
|
|
|
|
|
|
return db.rawQuery(query, new String[]{packageName});
|
|
|
|
} finally {
|
|
|
|
lock.readLock().unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void clearApps() {
|
|
|
|
lock.writeLock().lock();
|
|
|
|
try {
|
|
|
|
SQLiteDatabase db = this.getWritableDatabase();
|
|
|
|
db.beginTransactionNonExclusive();
|
|
|
|
try {
|
|
|
|
db.delete("app", null, null);
|
|
|
|
db.setTransactionSuccessful();
|
|
|
|
} finally {
|
|
|
|
db.endTransaction();
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
lock.writeLock().unlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-30 11:46:00 +00:00
|
|
|
public void addLogChangedListener(LogChangedListener listener) {
|
2016-01-05 12:40:02 +00:00
|
|
|
logChangedListeners.add(listener);
|
|
|
|
}
|
|
|
|
|
2016-01-30 11:46:00 +00:00
|
|
|
public void removeLogChangedListener(LogChangedListener listener) {
|
2016-01-05 12:40:02 +00:00
|
|
|
logChangedListeners.remove(listener);
|
|
|
|
}
|
|
|
|
|
2016-01-30 11:46:00 +00:00
|
|
|
public void addAccessChangedListener(AccessChangedListener listener) {
|
|
|
|
accessChangedListeners.add(listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeAccessChangedListener(AccessChangedListener listener) {
|
|
|
|
accessChangedListeners.remove(listener);
|
|
|
|
}
|
|
|
|
|
2016-02-13 11:42:26 +00:00
|
|
|
public void addForwardChangedListener(ForwardChangedListener listener) {
|
|
|
|
forwardChangedListeners.add(listener);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void removeForwardChangedListener(ForwardChangedListener listener) {
|
|
|
|
forwardChangedListeners.remove(listener);
|
|
|
|
}
|
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
private void notifyLogChanged() {
|
|
|
|
Message msg = handler.obtainMessage();
|
|
|
|
msg.what = MSG_LOG;
|
|
|
|
handler.sendMessage(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void notifyAccessChanged() {
|
|
|
|
Message msg = handler.obtainMessage();
|
|
|
|
msg.what = MSG_ACCESS;
|
|
|
|
handler.sendMessage(msg);
|
|
|
|
}
|
|
|
|
|
2016-02-13 11:42:26 +00:00
|
|
|
private void notifyForwardChanged() {
|
|
|
|
Message msg = handler.obtainMessage();
|
|
|
|
msg.what = MSG_FORWARD;
|
|
|
|
handler.sendMessage(msg);
|
|
|
|
}
|
|
|
|
|
2016-02-04 10:49:43 +00:00
|
|
|
private static void handleChangedNotification(Message msg) {
|
|
|
|
// Batch notifications
|
|
|
|
try {
|
|
|
|
Thread.sleep(1000);
|
2016-02-08 15:34:54 +00:00
|
|
|
if (handler.hasMessages(msg.what))
|
2016-02-04 10:49:43 +00:00
|
|
|
handler.removeMessages(msg.what);
|
|
|
|
} catch (InterruptedException ignored) {
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify listeners
|
|
|
|
if (msg.what == MSG_LOG) {
|
|
|
|
for (LogChangedListener listener : logChangedListeners)
|
|
|
|
try {
|
|
|
|
listener.onChanged();
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (msg.what == MSG_ACCESS) {
|
|
|
|
for (AccessChangedListener listener : accessChangedListeners)
|
|
|
|
try {
|
|
|
|
listener.onChanged();
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
}
|
2016-02-13 11:42:26 +00:00
|
|
|
|
|
|
|
} else if (msg.what == MSG_FORWARD) {
|
|
|
|
for (ForwardChangedListener listener : forwardChangedListeners)
|
|
|
|
try {
|
|
|
|
listener.onChanged();
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex));
|
|
|
|
}
|
2016-02-04 10:49:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-05 12:40:02 +00:00
|
|
|
public interface LogChangedListener {
|
2016-01-05 21:53:22 +00:00
|
|
|
void onChanged();
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|
2016-01-30 11:46:00 +00:00
|
|
|
|
|
|
|
public interface AccessChangedListener {
|
2016-02-04 10:49:43 +00:00
|
|
|
void onChanged();
|
2016-01-30 11:46:00 +00:00
|
|
|
}
|
2016-02-13 11:42:26 +00:00
|
|
|
|
|
|
|
public interface ForwardChangedListener {
|
|
|
|
void onChanged();
|
|
|
|
}
|
2016-01-05 12:40:02 +00:00
|
|
|
}
|