summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2024-03-28 19:56:31 +0800
committerPo Lu <luangruo@yahoo.com>2024-03-29 08:26:48 +0800
commit755665d95adbba07335f400f1090e53b66c41ff5 (patch)
tree03dbc80da010992a04e52f7119338e28ba9bed36 /java
parent4cee95815b9d7d56f6f77abb1cc17e346c038685 (diff)
downloademacs-755665d95adbba07335f400f1090e53b66c41ff5.tar.gz
Prevent Android OS task trimming from deleting Emacs frames
* doc/emacs/android.texi (Android Windowing): Document proviso on Android 7.0 and later. * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity) <timeOfLastInteraction>: New field. (onStop, onResume): Set and clear timeOfLastInteraction. (isReallyFinishing): New function. (onDestroy): Don't delete frame even in the event isFinishing returns true if more than 4 hours have elapsed since the activity last moved into the background.
Diffstat (limited to 'java')
-rw-r--r--java/org/gnu/emacs/EmacsActivity.java55
1 files changed, 54 insertions, 1 deletions
diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java
index 6ab6a709bef..f5b05a9c184 100644
--- a/java/org/gnu/emacs/EmacsActivity.java
+++ b/java/org/gnu/emacs/EmacsActivity.java
@@ -20,9 +20,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
package org.gnu.emacs;
import java.lang.IllegalStateException;
+
import java.util.List;
import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+
import android.app.Activity;
import android.content.ContentResolver;
@@ -31,6 +34,7 @@ import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
+import android.os.SystemClock;
import android.util.Log;
@@ -78,6 +82,9 @@ public class EmacsActivity extends Activity
/* The last context menu to be closed. */
private static Menu lastClosedMenu;
+ /* The time of the most recent call to onStop. */
+ private static long timeOfLastInteraction;
+
static
{
focusedActivities = new ArrayList<EmacsActivity> ();
@@ -273,6 +280,50 @@ public class EmacsActivity extends Activity
@Override
public final void
+ onStop ()
+ {
+ timeOfLastInteraction = SystemClock.elapsedRealtime ();
+
+ super.onStop ();
+ }
+
+ /* Return whether the task is being finished in response to explicit
+ user action. That is to say, Activity.isFinished, but as
+ documented. */
+
+ public final boolean
+ isReallyFinishing ()
+ {
+ long atime, dtime;
+ int hours;
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.NOUGAT)
+ return isFinishing ();
+
+ /* When the number of tasks retained in the recents list exceeds a
+ threshold, Android 7 and later so destroy activities in trimming
+ them from recents on the expiry of a timeout that isFinishing
+ returns true, in direct contradiction to the documentation. This
+ timeout is generally 6 hours, but admits of customization by
+ individual system distributors, so to err on the side of the
+ caution, the timeout Emacs applies is a more conservative figure
+ of 4 hours. */
+
+ if (timeOfLastInteraction == 0)
+ return isFinishing ();
+
+ atime = timeOfLastInteraction;
+
+ /* Compare atime with the current system time. */
+ dtime = SystemClock.elapsedRealtime () - atime;
+ if (dtime + 1000000 < TimeUnit.HOURS.toMillis (4))
+ return isFinishing ();
+
+ return false;
+ }
+
+ @Override
+ public final void
onDestroy ()
{
EmacsWindowAttachmentManager manager;
@@ -283,7 +334,8 @@ public class EmacsActivity extends Activity
/* The activity will die shortly hereafter. If there is a window
attached, close it now. */
isMultitask = this instanceof EmacsMultitaskActivity;
- manager.removeWindowConsumer (this, isMultitask || isFinishing ());
+ manager.removeWindowConsumer (this, (isMultitask
+ || isReallyFinishing ()));
focusedActivities.remove (this);
invalidateFocus (2);
@@ -340,6 +392,7 @@ public class EmacsActivity extends Activity
onResume ()
{
isPaused = false;
+ timeOfLastInteraction = 0;
EmacsWindowAttachmentManager.MANAGER.noticeDeiconified (this);
super.onResume ();