wownero
/
wownerujo
Archived
4
0
Fork 0

Merge pull request #39 from m2049r/bugfix_issue_36

Use AsyncTask with 5MB stack in lots of places
upstream
m2049r 7 years ago committed by GitHub
commit 5b3e92e91a

@ -17,8 +17,10 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -28,15 +30,13 @@ import android.widget.TextView;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.MoneroHandlerThread; import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import java.io.File;
public class GenerateReviewFragment extends Fragment { public class GenerateReviewFragment extends Fragment {
static final String TAG = "GenerateReviewFragment"; static final String TAG = "GenerateReviewFragment";
static final public String VIEW_DETAILS = "details"; static final public String VIEW_TYPE_DETAILS = "details";
static final public String VIEW_ACCEPT = "accept"; static final public String VIEW_TYPE_ACCEPT = "accept";
static final public String VIEW_WALLET = "wallet"; static final public String VIEW_TYPE_WALLET = "wallet";
ProgressBar pbProgress; ProgressBar pbProgress;
TextView tvWalletName; TextView tvWalletName;
@ -76,16 +76,12 @@ public class GenerateReviewFragment extends Fragment {
showProgress(); showProgress();
Bundle b = getArguments(); Bundle args = getArguments();
String type = b.getString("type"); String path = args.getString("path");
if (!type.equals(VIEW_WALLET)) { String password = args.getString("password");
String path = b.getString("path"); String type = args.getString("type");
String password = b.getString("password"); new AsyncShow().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR,
tvWalletName.setText(new File(path).getName()); path, password, type);
show(path, password, type);
} else {
show(walletCallback.getWallet(), null, type);
}
return view; return view;
} }
@ -96,40 +92,64 @@ public class GenerateReviewFragment extends Fragment {
acceptCallback.onAccept(name, password); acceptCallback.onAccept(name, password);
} }
private void show(final String walletPath, final String password, final String type) { private class AsyncShow extends AsyncTask<String, Void, Boolean> {
new Thread(null, String type;
new Runnable() { String password;
@Override
public void run() { String name;
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password); String address;
getActivity().runOnUiThread(new Runnable() { String seed;
public void run() { String viewKey;
show(wallet, password, type); boolean isWatchOnly;
wallet.close();
} @Override
}); protected Boolean doInBackground(String... params) {
} if (params.length != 3) return false;
} String walletPath = params[0];
, "DetailsReview", MoneroHandlerThread.THREAD_STACK_SIZE).start(); password = params[1];
} type = params[2];
private void show(final Wallet wallet, final String password, final String type) { Wallet wallet;
if (type.equals(GenerateReviewFragment.VIEW_ACCEPT)) { boolean closeWallet;
tvWalletPassword.setText(password); if (type.equals(GenerateReviewFragment.VIEW_TYPE_WALLET)) {
bAccept.setVisibility(View.VISIBLE); wallet = GenerateReviewFragment.this.walletCallback.getWallet();
bAccept.setEnabled(true); closeWallet = false;
} else {
wallet = WalletManager.getInstance().openWallet(walletPath, password);
closeWallet = true;
}
if (wallet.getStatus() != Wallet.Status.Status_Ok) return false;
name = wallet.getName();
address = wallet.getAddress();
seed = wallet.getSeed();
viewKey = wallet.getSecretViewKey();
isWatchOnly = wallet.isWatchOnly();
if (closeWallet) wallet.close();
return true;
} }
tvWalletName.setText(wallet.getName());
tvWalletAddress.setText(wallet.getAddress()); @Override
tvWalletMnemonic.setText(wallet.getSeed()); protected void onPostExecute(Boolean result) {
tvWalletViewKey.setText(wallet.getSecretViewKey()); super.onPostExecute(result);
String spend = wallet.isWatchOnly() ? "" : "not available - use seed for recovery"; if (result) {
if (spend.length() > 0) { //TODO should be == 64, but spendkey is not in the API yet if (type.equals(GenerateReviewFragment.VIEW_TYPE_ACCEPT)) {
tvWalletSpendKey.setText(spend); tvWalletPassword.setText(password);
} else { bAccept.setVisibility(View.VISIBLE);
tvWalletSpendKey.setText(getString(R.string.generate_wallet_watchonly)); bAccept.setEnabled(true);
}
tvWalletName.setText(name);
tvWalletAddress.setText(address);
tvWalletMnemonic.setText(seed);
tvWalletViewKey.setText(viewKey);
String spend = isWatchOnly ? "" : "not available - use seed for recovery";
if (spend.length() > 0) { //TODO should be == 64, but spendkey is not in the API yet
tvWalletSpendKey.setText(spend);
} else {
tvWalletSpendKey.setText(getString(R.string.generate_wallet_watchonly));
}
}
hideProgress();
} }
hideProgress();
} }
GenerateReviewFragment.Listener acceptCallback = null; GenerateReviewFragment.Listener acceptCallback = null;
@ -141,6 +161,7 @@ public class GenerateReviewFragment extends Fragment {
public interface ListenerWithWallet { public interface ListenerWithWallet {
Wallet getWallet(); Wallet getWallet();
} }
@Override @Override

@ -121,7 +121,7 @@ public class LoginActivity extends AppCompatActivity
promptPassword(walletName, new PasswordAction() { promptPassword(walletName, new PasswordAction() {
@Override @Override
public void action(String walletName, String password) { public void action(String walletName, String password) {
startDetails(walletFile, password, GenerateReviewFragment.VIEW_DETAILS); startDetails(walletFile, password, GenerateReviewFragment.VIEW_TYPE_DETAILS);
} }
}); });
} else { // this cannot really happen as we prefilter choices } else { // this cannot really happen as we prefilter choices
@ -646,6 +646,7 @@ public class LoginActivity extends AppCompatActivity
////////////////////////////////////////// //////////////////////////////////////////
static final String MNEMONIC_LANGUAGE = "English"; // see mnemonics/electrum-words.cpp for more static final String MNEMONIC_LANGUAGE = "English"; // see mnemonics/electrum-words.cpp for more
// TODO make this an AsyncTask?
public void createWallet(final String name, final String password, final WalletCreator walletCreator) { public void createWallet(final String name, final String password, final WalletCreator walletCreator) {
final GenerateFragment genFragment = (GenerateFragment) final GenerateFragment genFragment = (GenerateFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
@ -666,7 +667,7 @@ public class LoginActivity extends AppCompatActivity
cacheFile.delete(); cacheFile.delete();
File keysFile = new File(newWalletFolder, name + ".keys"); File keysFile = new File(newWalletFolder, name + ".keys");
keysFile.delete(); keysFile.delete();
final File addressFile = new File(newWalletFolder, name + ".address.txt"); File addressFile = new File(newWalletFolder, name + ".address.txt");
addressFile.delete(); addressFile.delete();
if (cacheFile.exists() || keysFile.exists() || addressFile.exists()) { if (cacheFile.exists() || keysFile.exists() || addressFile.exists()) {
@ -678,7 +679,7 @@ public class LoginActivity extends AppCompatActivity
File newWalletFile = new File(newWalletFolder, name); File newWalletFile = new File(newWalletFolder, name);
boolean success = walletCreator.createWallet(newWalletFile, password); boolean success = walletCreator.createWallet(newWalletFile, password);
if (success) { if (success) {
startDetails(newWalletFile, password, GenerateReviewFragment.VIEW_ACCEPT); startDetails(newWalletFile, password, GenerateReviewFragment.VIEW_TYPE_ACCEPT);
} else { } else {
Toast.makeText(LoginActivity.this, Toast.makeText(LoginActivity.this,
getString(R.string.generate_wallet_create_failed), Toast.LENGTH_LONG).show(); getString(R.string.generate_wallet_create_failed), Toast.LENGTH_LONG).show();

@ -18,6 +18,7 @@ package com.m2049r.xmrwallet;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.Editable; import android.text.Editable;
@ -34,6 +35,7 @@ import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.BarcodeFormat; import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType; import com.google.zxing.EncodeHintType;
@ -43,8 +45,8 @@ import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -187,37 +189,49 @@ public class ReceiveFragment extends Fragment {
} }
} }
private void show(final String address) { private void show(String address) {
getActivity().runOnUiThread(new Runnable() { tvAddress.setText(address);
public void run() { etPaymentId.setEnabled(true);
tvAddress.setText(address); etAmount.setEnabled(true);
etPaymentId.setEnabled(true); bPaymentId.setEnabled(true);
etAmount.setEnabled(true); bGenerate.setEnabled(true);
bPaymentId.setEnabled(true); hideProgress();
bGenerate.setEnabled(true); generateQr();
}
private void show(String walletPath, String password) {
new ReceiveFragment.AsyncShow().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR,
walletPath, password);
}
private class AsyncShow extends AsyncTask<String, Void, Boolean> {
String password;
String address;
@Override
protected Boolean doInBackground(String... params) {
if (params.length != 2) return false;
String walletPath = params[0];
password = params[1];
Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
address = wallet.getAddress();
wallet.close();
return true;
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (result) {
show(address);
} else {
Toast.makeText(getActivity(), getString(R.string.receive_cannot_open), Toast.LENGTH_LONG).show();
hideProgress(); hideProgress();
generateQr();
} }
}); }
} }
private void show(final String walletPath, final String password) {
new Thread(null,
new Runnable() {
@Override
public void run() {
final Wallet wallet = WalletManager.getInstance().openWallet(walletPath, password);
getActivity().runOnUiThread(new Runnable() {
public void run() {
String address = wallet.getAddress();
wallet.close();
show(address);
}
});
}
}
, "Receive", MoneroHandlerThread.THREAD_STACK_SIZE).start();
}
private boolean amountOk() { private boolean amountOk() {
String amountEntry = etAmount.getText().toString(); String amountEntry = etAmount.getText().toString();

@ -24,7 +24,6 @@ import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.net.UrlQuerySanitizer;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
@ -35,8 +34,6 @@ import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.Log; import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem; import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
@ -49,7 +46,6 @@ import com.m2049r.xmrwallet.util.BarcodeData;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.TxData; import com.m2049r.xmrwallet.util.TxData;
import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -594,7 +590,7 @@ public class WalletActivity extends AppCompatActivity implements WalletFragment.
switch (which) { switch (which) {
case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_POSITIVE:
Bundle extras = new Bundle(); Bundle extras = new Bundle();
extras.putString("type", GenerateReviewFragment.VIEW_WALLET); extras.putString("type", GenerateReviewFragment.VIEW_TYPE_WALLET);
replaceFragment(new GenerateReviewFragment(), null, extras); replaceFragment(new GenerateReviewFragment(), null, extras);
break; break;
case DialogInterface.BUTTON_NEGATIVE: case DialogInterface.BUTTON_NEGATIVE:

@ -0,0 +1,56 @@
/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.m2049r.xmrwallet.util;
import com.m2049r.xmrwallet.service.MoneroHandlerThread;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class MoneroThreadPoolExecutor {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);
public Thread newThread(Runnable r) {
return new Thread(null, r, "MoneroTask #" + mCount.getAndIncrement(), MoneroHandlerThread.THREAD_STACK_SIZE);
}
};
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<>(128);
public static final Executor MONERO_THREAD_POOL_EXECUTOR;
static {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
sPoolWorkQueue, sThreadFactory);
threadPoolExecutor.allowCoreThreadTimeOut(true);
MONERO_THREAD_POOL_EXECUTOR = threadPoolExecutor;
}
}

@ -177,6 +177,7 @@
<string name="receive_paymentid_hint">(optional)</string> <string name="receive_paymentid_hint">(optional)</string>
<string name="receive_amount_label">Amount</string> <string name="receive_amount_label">Amount</string>
<string name="receive_amount_hint">(optional)</string> <string name="receive_amount_hint">(optional)</string>
<string name="receive_cannot_open">Could not open wallet!</string>
<string name="details_alert_message">Sensitive data will now be shown.\nLook over your shoulder!</string> <string name="details_alert_message">Sensitive data will now be shown.\nLook over your shoulder!</string>
<string name="details_alert_yes">I\'m safe</string> <string name="details_alert_yes">I\'m safe</string>