From 957cf53a4012c5c32d72411149a9b187b11ef8f6 Mon Sep 17 00:00:00 2001 From: Caio Faustino Date: Sat, 19 Oct 2019 00:52:36 +0200 Subject: [PATCH 1/5] Stop service and remove notification if process stops. --- .../greenaddress/abcore/ABCoreService.java | 270 ++++++++++-------- 1 file changed, 154 insertions(+), 116 deletions(-) diff --git a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java index 34fe7598..4fe38358 100755 --- a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java +++ b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java @@ -5,7 +5,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; @@ -22,24 +21,157 @@ public class ABCoreService extends Service { private final static String TAG = ABCoreService.class.getName(); private final static int NOTIFICATION_ID = 922430164; private static final String PARAM_OUT_MSG = "rpccore"; - private Process mProcess; - private Process mProcessTor; - - private static void removeNotification(final Context c) { - ((NotificationManager) c.getSystemService(NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID); - final Intent broadcastIntent = new Intent(); - broadcastIntent.setAction(MainActivity.RPCResponseReceiver.ACTION_RESP); - broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); - broadcastIntent.putExtra(PARAM_OUT_MSG, "exception"); - broadcastIntent.putExtra("exception", ""); - c.sendBroadcast(broadcastIntent); - } + private Process mBitcoinProcess; + private Process mTorProcess; + + final ProcessLogger.OnError errorListener = new ProcessLogger.OnError() { + @Override + public void onError(final String[] error) { + final StringBuilder bf = new StringBuilder(); + for (final String e : error) { + if (!TextUtils.isEmpty(e)) { + bf.append(String.format("%s%s", e, System.getProperty("line.separator"))); + Log.e(TAG, "Process error - " + bf.toString()); + } + } + } + }; + + private final Thread bitcoinWaiterThread = new Thread(new Runnable() { + @Override + public void run() { + try { + final int exit = mBitcoinProcess.waitFor(); + Log.i(TAG, "Bitcoin process finished - " + exit); + stopSelf(); + } catch (InterruptedException e) { + Log.e(TAG, "Bitcoin InterruptedException", e); + } + } + }); + + private final Thread torWaiterThread = new Thread(new Runnable() { + @Override + public void run() { + try { + final int exit = mTorProcess.waitFor(); + Log.i(TAG, "Tor process finished - " + exit); + stopSelf(); + } catch (InterruptedException e) { + Log.e(TAG, "Tor InterruptedException", e); + } + } + }); @Override public IBinder onBind(final Intent intent) { return null; } + @Override + public int onStartCommand(final Intent intent, final int flags, final int startId) { + if (mBitcoinProcess != null || intent == null) + return START_STICKY; + + Log.i(TAG, "Core service msg"); + + try { + android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); + + startTor(); + startBitcoin(); + + setupNotificationAndMoveToForeground(); + + } catch (final IOException e) { + Log.e(TAG, "Native exception!", e); + Log.i(TAG, e.getMessage()); + Log.i(TAG, e.getLocalizedMessage()); + mBitcoinProcess = null; + mTorProcess = null; + stopSelf(); + } + Log.i(TAG, "background Task finished"); + + return START_STICKY; + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.i(TAG, "destroying core service"); + + if (mBitcoinProcess != null) { + mBitcoinProcess.destroy(); + mBitcoinProcess = null; + } + if (mTorProcess != null) { + mTorProcess.destroy(); + mTorProcess = null; + } + removeNotification(); + } + + private void startTor() throws IOException { + final String path = getNoBackupFilesDir().getCanonicalPath(); + + final ProcessBuilder torpb = new ProcessBuilder( + String.format("%s/%s", path, "tor"), + "SafeSocks", + "1", + "SocksPort", + "auto", + "NoExec", + "1", + "CookieAuthentication", + "1", + "ControlPort", + "9051", + "DataDirectory", + path + "/tordata" + ); + + torpb.directory(new File(path)); + + mTorProcess = torpb.start(); + + final ProcessLogger torErrorGobbler = new ProcessLogger(mTorProcess.getErrorStream(), errorListener); + final ProcessLogger torOutputGobbler = new ProcessLogger(mTorProcess.getInputStream(), errorListener); + + torErrorGobbler.start(); + torOutputGobbler.start(); + + torWaiterThread.start(); + } + + private void startBitcoin() throws IOException { + final String path = getNoBackupFilesDir().getCanonicalPath(); + // allow to pass in a different datadir directory + + // HACK: if user sets a datadir in the bitcoin.conf file that should then be the one + // used + final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + final String useDistribution = prefs.getString("usedistribution", "core"); + final String daemon = "liquid".equals(useDistribution) ? "liquidd" : "bitcoind"; + final ProcessBuilder pb = new ProcessBuilder( + String.format("%s/%s", path, daemon), + "--server=1", + String.format("--datadir=%s", Utils.getDataDir(this)), + String.format("--conf=%s", Utils.getBitcoinConf(this))); + + pb.directory(new File(path)); + + mBitcoinProcess = pb.start(); + + final ProcessLogger errorGobbler = new ProcessLogger(mBitcoinProcess.getErrorStream(), errorListener); + final ProcessLogger outputGobbler = new ProcessLogger(mBitcoinProcess.getInputStream(), errorListener); + + errorGobbler.start(); + outputGobbler.start(); + + bitcoinWaiterThread.start(); + } + private void setupNotificationAndMoveToForeground() { final Intent i = new Intent(this, MainActivity.class); i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | @@ -70,9 +202,9 @@ private void setupNotificationAndMoveToForeground() { b.setChannelId("channel_00"); } - final Notification n = b.build(); + Log.d(TAG, "startForeground"); startForeground(NOTIFICATION_ID, n); final Intent broadcastIntent = new Intent(); @@ -82,107 +214,13 @@ private void setupNotificationAndMoveToForeground() { sendBroadcast(broadcastIntent); } - @Override - public int onStartCommand(final Intent intent, final int flags, final int startId) { - if (mProcess != null || intent == null) - return START_STICKY; - - - Log.i(TAG, "Core service msg"); - - try { - - android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); - final String path = getNoBackupFilesDir().getCanonicalPath(); - - final ProcessBuilder torpb = new ProcessBuilder( - String.format("%s/%s", path, "tor"), - "SafeSocks", - "1", - "SocksPort", - "auto", - "NoExec", - "1", - "CookieAuthentication", - "1", - "ControlPort", - "9051", - "DataDirectory", - path + "/tordata" - ); - - torpb.directory(new File(path)); - - mProcessTor = torpb.start(); - - final ProcessLogger.OnError er = new ProcessLogger.OnError() { - @Override - public void onError(final String[] error) { - mProcess = null; - final StringBuilder bf = new StringBuilder(); - for (final String e : error) - if (!TextUtils.isEmpty(e)) - bf.append(String.format("%s%s", e, System.getProperty("line.separator"))); - - Log.i(TAG, bf.toString()); - } - }; - final ProcessLogger torErrorGobbler = new ProcessLogger(mProcessTor.getErrorStream(), er); - final ProcessLogger torOutputGobbler = new ProcessLogger(mProcessTor.getInputStream(), er); - - torErrorGobbler.start(); - torOutputGobbler.start(); - - // allow to pass in a different datadir directory - - // HACK: if user sets a datadir in the bitcoin.conf file that should then be the one - // used - final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); - final String useDistribution = prefs.getString("usedistribution", "core"); - final String daemon = "liquid".equals(useDistribution) ? "liquidd" : "bitcoind"; - final ProcessBuilder pb = new ProcessBuilder( - String.format("%s/%s", path, daemon), - "--server=1", - String.format("--datadir=%s", Utils.getDataDir(this)), - String.format("--conf=%s", Utils.getBitcoinConf(this))); - - pb.directory(new File(path)); - - mProcess = pb.start(); - - final ProcessLogger errorGobbler = new ProcessLogger(mProcess.getErrorStream(), er); - final ProcessLogger outputGobbler = new ProcessLogger(mProcess.getInputStream(), er); - - errorGobbler.start(); - outputGobbler.start(); - - setupNotificationAndMoveToForeground(); - - } catch (final IOException e) { - Log.i(TAG, "Native exception!"); - Log.i(TAG, e.getMessage()); - - Log.i(TAG, e.getLocalizedMessage()); - removeNotification(this); - mProcess = null; - mProcessTor = null; - e.printStackTrace(); - } - Log.i(TAG, "background Task finished"); - - return START_STICKY; - } - - @Override - public void onDestroy() { - super.onDestroy(); - Log.i(TAG, "destroying core service"); - - if (mProcess != null) { - mProcess.destroy(); - mProcessTor.destroy(); - mProcess = null; - mProcessTor = null; - } + private void removeNotification() { + ((NotificationManager) this.getSystemService(NOTIFICATION_SERVICE)).cancel(NOTIFICATION_ID); + final Intent broadcastIntent = new Intent(); + broadcastIntent.setAction(MainActivity.RPCResponseReceiver.ACTION_RESP); + broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT); + broadcastIntent.putExtra(PARAM_OUT_MSG, "exception"); + broadcastIntent.putExtra("exception", ""); + this.sendBroadcast(broadcastIntent); } } From c365b7e6807b633dabb6cab5612d3b743a37246d Mon Sep 17 00:00:00 2001 From: Caio Faustino Date: Mon, 16 Dec 2019 22:55:06 +0100 Subject: [PATCH 2/5] Differentiate between bitcoin and Tor logs. --- .../greenaddress/abcore/ABCoreService.java | 66 +++++++++++-------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java index 4fe38358..76fbfd5f 100755 --- a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java +++ b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java @@ -24,19 +24,6 @@ public class ABCoreService extends Service { private Process mBitcoinProcess; private Process mTorProcess; - final ProcessLogger.OnError errorListener = new ProcessLogger.OnError() { - @Override - public void onError(final String[] error) { - final StringBuilder bf = new StringBuilder(); - for (final String e : error) { - if (!TextUtils.isEmpty(e)) { - bf.append(String.format("%s%s", e, System.getProperty("line.separator"))); - Log.e(TAG, "Process error - " + bf.toString()); - } - } - } - }; - private final Thread bitcoinWaiterThread = new Thread(new Runnable() { @Override public void run() { @@ -85,8 +72,6 @@ public int onStartCommand(final Intent intent, final int flags, final int startI } catch (final IOException e) { Log.e(TAG, "Native exception!", e); - Log.i(TAG, e.getMessage()); - Log.i(TAG, e.getLocalizedMessage()); mBitcoinProcess = null; mTorProcess = null; stopSelf(); @@ -115,7 +100,7 @@ public void onDestroy() { private void startTor() throws IOException { final String path = getNoBackupFilesDir().getCanonicalPath(); - final ProcessBuilder torpb = new ProcessBuilder( + final ProcessBuilder torProcessBuilder = new ProcessBuilder( String.format("%s/%s", path, "tor"), "SafeSocks", "1", @@ -131,12 +116,25 @@ private void startTor() throws IOException { path + "/tordata" ); - torpb.directory(new File(path)); + torProcessBuilder.directory(new File(path)); - mTorProcess = torpb.start(); + mTorProcess = torProcessBuilder.start(); - final ProcessLogger torErrorGobbler = new ProcessLogger(mTorProcess.getErrorStream(), errorListener); - final ProcessLogger torOutputGobbler = new ProcessLogger(mTorProcess.getInputStream(), errorListener); + final ProcessLogger.OnError torErrorListener = new ProcessLogger.OnError() { + @Override + public void onError(final String[] error) { + final StringBuilder bf = new StringBuilder(); + for (final String e : error) { + if (!TextUtils.isEmpty(e)) { + bf.append(String.format("%s%s", e, System.getProperty("line.separator"))); + Log.e(TAG, "Tor process error - " + bf.toString()); + } + } + } + }; + + final ProcessLogger torErrorGobbler = new ProcessLogger(mTorProcess.getErrorStream(), torErrorListener); + final ProcessLogger torOutputGobbler = new ProcessLogger(mTorProcess.getInputStream(), torErrorListener); torErrorGobbler.start(); torOutputGobbler.start(); @@ -146,25 +144,37 @@ private void startTor() throws IOException { private void startBitcoin() throws IOException { final String path = getNoBackupFilesDir().getCanonicalPath(); - // allow to pass in a different datadir directory - // HACK: if user sets a datadir in the bitcoin.conf file that should then be the one - // used + // allow to pass in a different datadir directory + // HACK: if user sets a datadir in the bitcoin.conf file that should then be the one used final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); final String useDistribution = prefs.getString("usedistribution", "core"); final String daemon = "liquid".equals(useDistribution) ? "liquidd" : "bitcoind"; - final ProcessBuilder pb = new ProcessBuilder( + final ProcessBuilder bitcoinProcessBuilder = new ProcessBuilder( String.format("%s/%s", path, daemon), "--server=1", String.format("--datadir=%s", Utils.getDataDir(this)), String.format("--conf=%s", Utils.getBitcoinConf(this))); - pb.directory(new File(path)); + bitcoinProcessBuilder.directory(new File(path)); - mBitcoinProcess = pb.start(); + mBitcoinProcess = bitcoinProcessBuilder.start(); + + final ProcessLogger.OnError btcErrorListener = new ProcessLogger.OnError() { + @Override + public void onError(final String[] error) { + final StringBuilder bf = new StringBuilder(); + for (final String e : error) { + if (!TextUtils.isEmpty(e)) { + bf.append(String.format("%s%s", e, System.getProperty("line.separator"))); + Log.e(TAG, "Bitcoin process error - " + bf.toString()); + } + } + } + }; - final ProcessLogger errorGobbler = new ProcessLogger(mBitcoinProcess.getErrorStream(), errorListener); - final ProcessLogger outputGobbler = new ProcessLogger(mBitcoinProcess.getInputStream(), errorListener); + final ProcessLogger errorGobbler = new ProcessLogger(mBitcoinProcess.getErrorStream(), btcErrorListener); + final ProcessLogger outputGobbler = new ProcessLogger(mBitcoinProcess.getInputStream(), btcErrorListener); errorGobbler.start(); outputGobbler.start(); From 92dce1829c870805913344ca4b465355ee069442 Mon Sep 17 00:00:00 2001 From: Caio Faustino Date: Wed, 18 Dec 2019 21:11:24 +0100 Subject: [PATCH 3/5] Add process identifier to ProcessLogger --- .../greenaddress/abcore/ABCoreService.java | 8 +++---- .../greenaddress/abcore/ProcessLogger.java | 23 ++++++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java index 76fbfd5f..b798a39c 100755 --- a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java +++ b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java @@ -133,8 +133,8 @@ public void onError(final String[] error) { } }; - final ProcessLogger torErrorGobbler = new ProcessLogger(mTorProcess.getErrorStream(), torErrorListener); - final ProcessLogger torOutputGobbler = new ProcessLogger(mTorProcess.getInputStream(), torErrorListener); + final ProcessLogger torErrorGobbler = new ProcessLogger(mTorProcess.getErrorStream(),"TOR-ERR", torErrorListener); + final ProcessLogger torOutputGobbler = new ProcessLogger(mTorProcess.getInputStream(), "TOR", torErrorListener); torErrorGobbler.start(); torOutputGobbler.start(); @@ -173,8 +173,8 @@ public void onError(final String[] error) { } }; - final ProcessLogger errorGobbler = new ProcessLogger(mBitcoinProcess.getErrorStream(), btcErrorListener); - final ProcessLogger outputGobbler = new ProcessLogger(mBitcoinProcess.getInputStream(), btcErrorListener); + final ProcessLogger errorGobbler = new ProcessLogger(mBitcoinProcess.getErrorStream(), "BTC-ERR", btcErrorListener); + final ProcessLogger outputGobbler = new ProcessLogger(mBitcoinProcess.getInputStream(), "BTC", btcErrorListener); errorGobbler.start(); outputGobbler.start(); diff --git a/app/src/main/java/com/greenaddress/abcore/ProcessLogger.java b/app/src/main/java/com/greenaddress/abcore/ProcessLogger.java index b730d9e2..e1526382 100755 --- a/app/src/main/java/com/greenaddress/abcore/ProcessLogger.java +++ b/app/src/main/java/com/greenaddress/abcore/ProcessLogger.java @@ -11,37 +11,38 @@ class ProcessLogger extends Thread { - private final static String TAG = ProcessLogger.class.getName(); - private final InputStream is; - private final OnError er; + private final String mTAG; + private final InputStream mInputStream; + private final OnError mOnError; - ProcessLogger(final InputStream is, OnError er) { + ProcessLogger(final InputStream inputStream, String name, OnError onErrorCallback) { super(); - this.is = is; - this.er = er; + mTAG = ProcessLogger.class.getSimpleName() + "-" + name; + this.mInputStream = inputStream; + this.mOnError = onErrorCallback; android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); } @Override public void run() { try { - final InputStreamReader isr = new InputStreamReader(is); + final InputStreamReader isr = new InputStreamReader(mInputStream); final BufferedReader br = new BufferedReader(isr); String line; final String[] errors = new String[3]; int counter = 0; while ((line = br.readLine()) != null) { - Log.v(TAG, line); + Log.v(mTAG, line); errors[counter++ % 3] = line; } - if (er != null) - er.onError(errors); + if (mOnError != null) + mOnError.onError(errors); } catch (final IOException ioe) { ioe.printStackTrace(); } finally { - IOUtils.closeQuietly(is); + IOUtils.closeQuietly(mInputStream); } } From 33350d51c1f0c8f84ca3d3f8314f1860fe8fa836 Mon Sep 17 00:00:00 2001 From: Caio Faustino Date: Sat, 28 Dec 2019 01:20:44 +0100 Subject: [PATCH 4/5] Let Bitcoin process finish after Tor --- app/src/main/java/com/greenaddress/abcore/ABCoreService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java index b798a39c..2190c14b 100755 --- a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java +++ b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java @@ -43,7 +43,7 @@ public void run() { try { final int exit = mTorProcess.waitFor(); Log.i(TAG, "Tor process finished - " + exit); - stopSelf(); + // if the Tor process stops, the Bitcoin process will already stop itself } catch (InterruptedException e) { Log.e(TAG, "Tor InterruptedException", e); } From 3259cd7f48ff5177c1d2ec8cfdc3dcba2a4fad26 Mon Sep 17 00:00:00 2001 From: Caio Faustino Date: Mon, 24 Feb 2020 06:57:29 +0100 Subject: [PATCH 5/5] Redundant --datadir parameter. Already set in configs. --- app/src/main/java/com/greenaddress/abcore/ABCoreService.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java index 2190c14b..778ca3d3 100755 --- a/app/src/main/java/com/greenaddress/abcore/ABCoreService.java +++ b/app/src/main/java/com/greenaddress/abcore/ABCoreService.java @@ -145,15 +145,12 @@ public void onError(final String[] error) { private void startBitcoin() throws IOException { final String path = getNoBackupFilesDir().getCanonicalPath(); - // allow to pass in a different datadir directory - // HACK: if user sets a datadir in the bitcoin.conf file that should then be the one used final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); final String useDistribution = prefs.getString("usedistribution", "core"); final String daemon = "liquid".equals(useDistribution) ? "liquidd" : "bitcoind"; final ProcessBuilder bitcoinProcessBuilder = new ProcessBuilder( String.format("%s/%s", path, daemon), "--server=1", - String.format("--datadir=%s", Utils.getDataDir(this)), String.format("--conf=%s", Utils.getBitcoinConf(this))); bitcoinProcessBuilder.directory(new File(path));