Skip to content

Commit

Permalink
#273: Improved "memory low" event detection.
Browse files Browse the repository at this point in the history
  • Loading branch information
Keidan committed Oct 20, 2023
1 parent 5c18c36 commit 4f350e7
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,29 @@
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatCheckBox;
import androidx.transition.AutoTransition;
import androidx.transition.TransitionManager;

import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import fr.ralala.hexviewer.ApplicationCtx;
import fr.ralala.hexviewer.R;
import fr.ralala.hexviewer.models.LineEntry;
import fr.ralala.hexviewer.ui.adapters.LineUpdateHexArrayAdapter;
import fr.ralala.hexviewer.ui.adapters.holders.LineNumbersTitle;
import fr.ralala.hexviewer.ui.utils.LineUpdateTextWatcher;
import fr.ralala.hexviewer.ui.utils.UIHelper;
import fr.ralala.hexviewer.utils.MemoryMonitor;
import fr.ralala.hexviewer.utils.SysHelper;
import fr.ralala.hexviewer.utils.memory.MemoryMonitor;

/**
* ******************************************************************************
Expand Down Expand Up @@ -91,7 +91,7 @@ public class LineUpdateActivity extends AppCompatActivity implements View.OnClic
*/
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(((ApplicationCtx)base.getApplicationContext()).onAttach(base));
super.attachBaseContext(((ApplicationCtx) base.getApplicationContext()).onAttach(base));
}

/**
Expand All @@ -104,7 +104,7 @@ protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

setContentView(R.layout.activity_line_update);
mApp = (ApplicationCtx)getApplicationContext();
mApp = (ApplicationCtx) getApplicationContext();
mMemoryMonitor = new MemoryMonitor(mApp.getMemoryThreshold(), 2000);
ListView lvSource = findViewById(R.id.lvSource);
ListView lvResult = findViewById(R.id.lvResult);
Expand Down Expand Up @@ -203,7 +203,7 @@ protected void onCreate(final Bundle savedInstanceState) {
mHex = mHex.substring(0, mHex.length() - 1);
mEtInputHex.setText(mHex);
mEtInputHex.addTextChangedListener(new LineUpdateTextWatcher(
mAdapterResult, mTilInputHex, mApp, mShiftOffset, maxLengthWithPartial, mSequential));
mAdapterResult, mTilInputHex, mApp, mShiftOffset, maxLengthWithPartial, mSequential));

}

Expand Down Expand Up @@ -285,7 +285,7 @@ public boolean onOptionsItemSelected(MenuItem item) {
final byte[] buf = SysHelper.hexStringToByteArray(validate);
if (mRefLength != buf.length) {
UIHelper.showErrorDialog(this, getTitle(),
getString(R.string.error_open_sequential_add_or_delete_data));
getString(R.string.error_open_sequential_add_or_delete_data));
return super.onOptionsItemSelected(item);
}
}
Expand Down Expand Up @@ -320,13 +320,13 @@ public void onClick(View v) {
private void animateVisibility(ImageView iv, View v) {
if (v.getVisibility() == View.VISIBLE) {
TransitionManager.beginDelayedTransition(findViewById(R.id.base_view),
new AutoTransition());
new AutoTransition());
v.setVisibility(View.GONE);
if (iv != null)
iv.setImageResource(R.drawable.ic_expand_more);
} else {
TransitionManager.beginDelayedTransition(findViewById(R.id.base_view),
new AutoTransition());
new AutoTransition());
v.setVisibility(View.VISIBLE);
if (iv != null)
iv.setImageResource(R.drawable.ic_expand_less);
Expand Down
29 changes: 21 additions & 8 deletions app/src/main/java/fr/ralala/hexviewer/ui/tasks/TaskOpen.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Context;
import android.text.format.Formatter;

import java.io.IOException;
import java.nio.ByteBuffer;
Expand All @@ -17,9 +18,11 @@
import fr.ralala.hexviewer.models.LineEntry;
import fr.ralala.hexviewer.ui.adapters.HexTextArrayAdapter;
import fr.ralala.hexviewer.ui.utils.UIHelper;
import fr.ralala.hexviewer.utils.MemoryMonitor;
import fr.ralala.hexviewer.utils.SysHelper;
import fr.ralala.hexviewer.utils.io.RandomAccessFileChannel;
import fr.ralala.hexviewer.utils.memory.MemoryInfo;
import fr.ralala.hexviewer.utils.memory.MemoryListener;
import fr.ralala.hexviewer.utils.memory.MemoryMonitor;

/**
* ******************************************************************************
Expand All @@ -33,7 +36,7 @@
* </p>
* ******************************************************************************
*/
public class TaskOpen extends ProgressTask<ContentResolver, FileData, TaskOpen.Result> implements MemoryMonitor.MemoryListener {
public class TaskOpen extends ProgressTask<ContentResolver, FileData, TaskOpen.Result> implements MemoryListener {
private final Context mContext;
private static final int MAX_LENGTH = SysHelper.MAX_BY_ROW_16 * 20000;
private final HexTextArrayAdapter mAdapter;
Expand Down Expand Up @@ -105,6 +108,14 @@ else if (result.exception != null)
mAdapter.addAll(result.listHex);
}
}
if(!mLowMemory.get()) {
MemoryInfo mi = mMemoryMonitor.getLastMemoryInfo();
ApplicationCtx.addLog(mContext, "Open",
String.format(Locale.US, "Memory status, used: %s (%.02f%%), free: %s, max: %s",
Formatter.formatFileSize(mContext, mi.getUsedMemory()), mi.getPercentUsed(),
Formatter.formatFileSize(mContext, mi.getTotalFreeMemory()),
Formatter.formatFileSize(mContext, mi.getTotalMemory())));
}
if (mListener != null)
mListener.onOpenResult(result.exception == null && !isCancelled() && !mLowMemory.get(), true);
super.onPostExecute(result);
Expand Down Expand Up @@ -226,12 +237,14 @@ private void evaluateShiftOffset(FileData fd, long totalSequential) {
}
}

public void onLowAppMemory(boolean disabled, long available, long used, float percentUsed) {
if (disabled) {
ApplicationCtx.addLog(mContext, "Open", "Low memory disabled");
} else {
ApplicationCtx.addLog(mContext, "Open",
String.format(Locale.US, "Low memory detected (a: %d, u: %d, pu: %f", available, used, percentUsed));
public void onLowAppMemory(boolean disabled, MemoryInfo mi) {
ApplicationCtx.addLog(mContext, "Open",
String.format(Locale.US, "Low memory %s, used: %s (%.02f%%), free: %s, max: %s",
disabled ? "disabled" : "detected",
Formatter.formatFileSize(mContext, mi.getUsedMemory()), mi.getPercentUsed(),
Formatter.formatFileSize(mContext, mi.getTotalFreeMemory()),
Formatter.formatFileSize(mContext, mi.getTotalMemory())));
if (!disabled) {
mLowMemory.set(true);
mCancel.set(true);
}
Expand Down
52 changes: 52 additions & 0 deletions app/src/main/java/fr/ralala/hexviewer/utils/memory/MemoryInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package fr.ralala.hexviewer.utils.memory;

/**
* ******************************************************************************
* <p><b>Project HexViewer</b><br/>
* Memory info.
* </p>
*
* @author Keidan
* <p>
* License: GPLv3
* </p>
* ******************************************************************************
*/
public class MemoryInfo {
private long mTotalMemory = 0L;
private long mUsedMemory = 0L;
private long mTotalFreeMemory = 0L;
private double mPercentUsed = 0.0;

public long getTotalMemory() {
return mTotalMemory;
}

public void setTotalMemory(long totalMemory) {
mTotalMemory = totalMemory;
}

public long getUsedMemory() {
return mUsedMemory;
}

public void setUsedMemory(long usedMemory) {
mUsedMemory = usedMemory;
}

public long getTotalFreeMemory() {
return mTotalFreeMemory;
}

public void setTotalFreeMemory(long totalFreeMemory) {
mTotalFreeMemory = totalFreeMemory;
}

public double getPercentUsed() {
return mPercentUsed;
}

public void setPercentUsed(double percentUsed) {
mPercentUsed = percentUsed;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.ralala.hexviewer.utils.memory;

/**
* ******************************************************************************
* <p><b>Project HexViewer</b><br/>
* Memory listener.
* </p>
*
* @author Keidan
* <p>
* License: GPLv3
* </p>
* ******************************************************************************
*/
public interface MemoryListener {
void onLowAppMemory(boolean disabled, MemoryInfo mi);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fr.ralala.hexviewer.utils;
package fr.ralala.hexviewer.utils.memory;

import android.os.Handler;
import android.os.Looper;
Expand All @@ -21,14 +21,32 @@ public class MemoryMonitor implements Runnable {
private final int mCheckFrequencyMs;
private boolean mAutoStop = false;
private MemoryListener mMemoryListener;

public interface MemoryListener {
void onLowAppMemory(boolean disabled, long available, long used, float percentUsed);
}
private final MemoryInfo mMemoryInfo;

public MemoryMonitor(final float threshold, final int checkFrequencyMs) {
mThreshold = threshold;
mCheckFrequencyMs = checkFrequencyMs;
mMemoryInfo = new MemoryInfo();
}

/**
* Loads memory information.
*/
private void loadMemoryInfo() {
Runtime r = Runtime.getRuntime();
mMemoryInfo.setTotalMemory(r.maxMemory());
mMemoryInfo.setUsedMemory(r.totalMemory() - r.freeMemory());
mMemoryInfo.setTotalFreeMemory(mMemoryInfo.getTotalMemory() - mMemoryInfo.getUsedMemory());
mMemoryInfo.setPercentUsed(mMemoryInfo.getUsedMemory() * 100.f / mMemoryInfo.getTotalMemory());
}

/**
* Returns the last known memory information.
*
* @return MemoryInfo
*/
public MemoryInfo getLastMemoryInfo() {
return mMemoryInfo;
}

/**
Expand All @@ -41,9 +59,10 @@ public void start(final MemoryListener memoryListener, final boolean autoStop) {
stop();
mMemoryListener = memoryListener;
mAutoStop = autoStop;
loadMemoryInfo();
if (mMemoryListener != null) {
if (mThreshold == -1) {
mMemoryListener.onLowAppMemory(true, 0, 0, 0);
mMemoryListener.onLowAppMemory(true, mMemoryInfo);
} else {
mMemoryHandler = new Handler(Looper.getMainLooper());
run();
Expand All @@ -64,13 +83,9 @@ public void stop() {

public void run() {
// Get app memory info
long available = Runtime.getRuntime().maxMemory();
long used = Runtime.getRuntime().totalMemory();

// Check for & and handle low memory state
float percentUsed = 100f * (1f - ((float) used / available));
if (percentUsed <= mThreshold) {
mMemoryListener.onLowAppMemory(false, available, used, percentUsed);
loadMemoryInfo();
if ((100.f - mMemoryInfo.getPercentUsed()) <= mThreshold) {
mMemoryListener.onLowAppMemory(false, mMemoryInfo);
if (mAutoStop)
stop();
}
Expand Down

0 comments on commit 4f350e7

Please sign in to comment.