aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorPo Lu2024-03-28 19:56:31 +0800
committerPo Lu2024-03-29 08:26:48 +0800
commit755665d95adbba07335f400f1090e53b66c41ff5 (patch)
tree03dbc80da010992a04e52f7119338e28ba9bed36 /java
parent4cee95815b9d7d56f6f77abb1cc17e346c038685 (diff)
downloademacs-755665d95adbba07335f400f1090e53b66c41ff5.tar.gz
emacs-755665d95adbba07335f400f1090e53b66c41ff5.zip
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/>. */
20package org.gnu.emacs; 20package org.gnu.emacs;
21 21
22import java.lang.IllegalStateException; 22import java.lang.IllegalStateException;
23
23import java.util.List; 24import java.util.List;
24import java.util.ArrayList; 25import java.util.ArrayList;
25 26
27import java.util.concurrent.TimeUnit;
28
26import android.app.Activity; 29import android.app.Activity;
27 30
28import android.content.ContentResolver; 31import android.content.ContentResolver;
@@ -31,6 +34,7 @@ import android.content.Intent;
31 34
32import android.os.Build; 35import android.os.Build;
33import android.os.Bundle; 36import android.os.Bundle;
37import android.os.SystemClock;
34 38
35import android.util.Log; 39import android.util.Log;
36 40
@@ -78,6 +82,9 @@ public class EmacsActivity extends Activity
78 /* The last context menu to be closed. */ 82 /* The last context menu to be closed. */
79 private static Menu lastClosedMenu; 83 private static Menu lastClosedMenu;
80 84
85 /* The time of the most recent call to onStop. */
86 private static long timeOfLastInteraction;
87
81 static 88 static
82 { 89 {
83 focusedActivities = new ArrayList<EmacsActivity> (); 90 focusedActivities = new ArrayList<EmacsActivity> ();
@@ -273,6 +280,50 @@ public class EmacsActivity extends Activity
273 280
274 @Override 281 @Override
275 public final void 282 public final void
283 onStop ()
284 {
285 timeOfLastInteraction = SystemClock.elapsedRealtime ();
286
287 super.onStop ();
288 }
289
290 /* Return whether the task is being finished in response to explicit
291 user action. That is to say, Activity.isFinished, but as
292 documented. */
293
294 public final boolean
295 isReallyFinishing ()
296 {
297 long atime, dtime;
298 int hours;
299
300 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.NOUGAT)
301 return isFinishing ();
302
303 /* When the number of tasks retained in the recents list exceeds a
304 threshold, Android 7 and later so destroy activities in trimming
305 them from recents on the expiry of a timeout that isFinishing
306 returns true, in direct contradiction to the documentation. This
307 timeout is generally 6 hours, but admits of customization by
308 individual system distributors, so to err on the side of the
309 caution, the timeout Emacs applies is a more conservative figure
310 of 4 hours. */
311
312 if (timeOfLastInteraction == 0)
313 return isFinishing ();
314
315 atime = timeOfLastInteraction;
316
317 /* Compare atime with the current system time. */
318 dtime = SystemClock.elapsedRealtime () - atime;
319 if (dtime + 1000000 < TimeUnit.HOURS.toMillis (4))
320 return isFinishing ();
321
322 return false;
323 }
324
325 @Override
326 public final void
276 onDestroy () 327 onDestroy ()
277 { 328 {
278 EmacsWindowAttachmentManager manager; 329 EmacsWindowAttachmentManager manager;
@@ -283,7 +334,8 @@ public class EmacsActivity extends Activity
283 /* The activity will die shortly hereafter. If there is a window 334 /* The activity will die shortly hereafter. If there is a window
284 attached, close it now. */ 335 attached, close it now. */
285 isMultitask = this instanceof EmacsMultitaskActivity; 336 isMultitask = this instanceof EmacsMultitaskActivity;
286 manager.removeWindowConsumer (this, isMultitask || isFinishing ()); 337 manager.removeWindowConsumer (this, (isMultitask
338 || isReallyFinishing ()));
287 focusedActivities.remove (this); 339 focusedActivities.remove (this);
288 invalidateFocus (2); 340 invalidateFocus (2);
289 341
@@ -340,6 +392,7 @@ public class EmacsActivity extends Activity
340 onResume () 392 onResume ()
341 { 393 {
342 isPaused = false; 394 isPaused = false;
395 timeOfLastInteraction = 0;
343 396
344 EmacsWindowAttachmentManager.MANAGER.noticeDeiconified (this); 397 EmacsWindowAttachmentManager.MANAGER.noticeDeiconified (this);
345 super.onResume (); 398 super.onResume ();