diff options
author | Po Lu <luangruo@yahoo.com> | 2024-03-28 19:56:31 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2024-03-29 08:26:48 +0800 |
commit | 755665d95adbba07335f400f1090e53b66c41ff5 (patch) | |
tree | 03dbc80da010992a04e52f7119338e28ba9bed36 /java | |
parent | 4cee95815b9d7d56f6f77abb1cc17e346c038685 (diff) | |
download | emacs-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.java | 55 |
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 (); |