emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 755665d95ad 1/2: Prevent Android OS task trimming from deleting E


From: Po Lu
Subject: master 755665d95ad 1/2: Prevent Android OS task trimming from deleting Emacs frames
Date: Thu, 28 Mar 2024 20:27:04 -0400 (EDT)

branch: master
commit 755665d95adbba07335f400f1090e53b66c41ff5
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    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.
---
 doc/emacs/android.texi                | 12 ++++++++
 java/org/gnu/emacs/EmacsActivity.java | 55 ++++++++++++++++++++++++++++++++++-
 2 files changed, 66 insertions(+), 1 deletion(-)

diff --git a/doc/emacs/android.texi b/doc/emacs/android.texi
index b367515cb35..01732961998 100644
--- a/doc/emacs/android.texi
+++ b/doc/emacs/android.texi
@@ -858,6 +858,18 @@ When the user closes the window created during application 
startup,
 and the window was not previously closed by the system in order to
 save resources, Emacs deletes any frame displayed within that window.
 
+However, on Android 7.0 and later, such frames are not deleted if the
+window is closed four or more hours after the window moves into the
+background, as the system automatically removes open windows once a
+certain period of inactivity elapses when the number of windows retained
+by the window manager surpasses a specific threshold, and window
+deletion by this mechanism is indistinguishable from window deletion by
+the user.  Emacs begins to ignore window deletion after two hours less
+than the default value of this threshold both to err on the side of
+caution, in case the system's record of inactivity and Emacs's differ,
+and for the reason that this threshold is open to customization by OS
+distributors.
+
 @item
 When the user or the system closes any window created by Emacs on
 behalf of a specific frame, Emacs deletes the frame displayed within
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> ();
@@ -271,6 +278,50 @@ public class EmacsActivity extends Activity
     syncFullscreenWith (window);
   }
 
+  @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 ()
@@ -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 ();



reply via email to

[Prev in Thread] Current Thread [Next in Thread]