abouttreesummaryrefslogcommitdiff
path: root/srcs
diff options
context:
space:
mode:
authorJules Aguillon2025-12-26 16:43:34 +0100
committerGitHub2025-12-26 16:43:34 +0100
commitdab50e0572e98d00be1645e3c0843576eb1fb249 (patch)
tree2812c2077c5afa85f0ed58a0722e163264910ef8 /srcs
parentb40be68773939d3d3b55a819cdfe1d9e9a60bc4e (diff)
downloadunexpected-keyboard-dab50e0572e98d00be1645e3c0843576eb1fb249.tar.gz
unexpected-keyboard-dab50e0572e98d00be1645e3c0843576eb1fb249.zip
Fix clipboard manager crashes (#1148)
* Fix background crash in clipboard history service The clipboard history service might crash when the connection between the keyboard and the system is in a bad state. * Fix race condition in clipboard history service The clipboard history service callback appears to be called concurrently leading to concurrent accesses to data and to concurrent calls to 'on_clipboard_history_change'. Access are now synchronized. * Fix clipboard manager crash when device is locked
Diffstat (limited to 'srcs')
-rw-r--r--srcs/juloo.keyboard2/ClipboardHistoryService.java31
-rw-r--r--srcs/juloo.keyboard2/ClipboardPinView.java24
2 files changed, 33 insertions, 22 deletions
diff --git a/srcs/juloo.keyboard2/ClipboardHistoryService.java b/srcs/juloo.keyboard2/ClipboardHistoryService.java
index 27e2eb9..5ec5ab5 100644
--- a/srcs/juloo.keyboard2/ClipboardHistoryService.java
+++ b/srcs/juloo.keyboard2/ClipboardHistoryService.java
@@ -66,7 +66,7 @@ public final class ClipboardHistoryService
_cm.addPrimaryClipChangedListener(this.new SystemListener());
}
- public List<String> clear_expired_and_get_history()
+ public synchronized List<String> clear_expired_and_get_history()
{
long now_ms = System.currentTimeMillis();
List<String> dst = new ArrayList<String>();
@@ -83,30 +83,33 @@ public final class ClipboardHistoryService
}
/** This will call [on_clipboard_history_change]. */
- public void remove_history_entry(String clip)
+ public synchronized void remove_history_entry(String clip)
{
int last_pos = _history.size() - 1;
+ boolean last_pos_changed = false;
for (int pos = last_pos; pos >= 0; pos--)
{
if (!_history.get(pos).content.equals(clip))
continue;
// Removing the current clipboard, clear the system clipboard.
if (pos == last_pos)
- {
- if (VERSION.SDK_INT >= 28)
- _cm.clearPrimaryClip();
- else
- _cm.setText("");
- }
+ last_pos_changed = true;
_history.remove(pos);
- if (_listener != null)
- _listener.on_clipboard_history_change();
}
+ if (last_pos_changed)
+ {
+ if (VERSION.SDK_INT >= 28)
+ _cm.clearPrimaryClip();
+ else
+ _cm.setText("");
+ }
+ if (_listener != null)
+ _listener.on_clipboard_history_change();
}
/** Add clipboard entries to the history, skipping consecutive duplicates and
empty strings. */
- public void add_clip(String clip)
+ public synchronized void add_clip(String clip)
{
if (!Config.globalConfig().clipboard_history_enabled)
return;
@@ -120,7 +123,7 @@ public final class ClipboardHistoryService
_listener.on_clipboard_history_change();
}
- public void clear_history()
+ public synchronized void clear_history()
{
_history.clear();
if (_listener != null)
@@ -137,7 +140,9 @@ public final class ClipboardHistoryService
/** Add what is currently in the system clipboard into the history. */
void add_current_clip()
{
- ClipData clip = _cm.getPrimaryClip();
+ ClipData clip = null;
+ // getPrimaryClip might throw when the keyboard is disconnected.
+ try { clip = _cm.getPrimaryClip(); } catch (Exception _e) {}
if (clip == null)
return;
int count = clip.getItemCount();
diff --git a/srcs/juloo.keyboard2/ClipboardPinView.java b/srcs/juloo.keyboard2/ClipboardPinView.java
index 65f2f44..93c934a 100644
--- a/srcs/juloo.keyboard2/ClipboardPinView.java
+++ b/srcs/juloo.keyboard2/ClipboardPinView.java
@@ -30,9 +30,15 @@ public final class ClipboardPinView extends NonScrollListView
{
super(ctx, attrs);
_entries = new ArrayList<String>();
- _persist_store =
- ctx.getSharedPreferences("pinned_clipboards", Context.MODE_PRIVATE);
- load_from_prefs(_persist_store, _entries);
+ // Storage is not be available in direct-boot mode.
+ _persist_store = null;
+ try
+ {
+ _persist_store =
+ ctx.getSharedPreferences("pinned_clipboards", Context.MODE_PRIVATE);
+ load_from_prefs(_persist_store, _entries);
+ }
+ catch (Exception _e) {}
_adapter = this.new ClipboardPinEntriesAdapter();
setAdapter(_adapter);
}
@@ -63,8 +69,6 @@ public final class ClipboardPinView extends NonScrollListView
ClipboardHistoryService.paste(_entries.get(pos));
}
- void persist() { save_to_prefs(_persist_store, _entries); }
-
static void load_from_prefs(SharedPreferences store, List<String> dst)
{
String arr_s = store.getString(PERSIST_PREF, null);
@@ -79,12 +83,14 @@ public final class ClipboardPinView extends NonScrollListView
catch (JSONException _e) {}
}
- static void save_to_prefs(SharedPreferences store, List<String> entries)
+ void persist()
{
+ if (_persist_store == null)
+ return;
JSONArray arr = new JSONArray();
- for (int i = 0; i < entries.size(); i++)
- arr.put(entries.get(i));
- store.edit()
+ for (int i = 0; i < _entries.size(); i++)
+ arr.put(_entries.get(i));
+ _persist_store.edit()
.putString(PERSIST_PREF, arr.toString())
.apply();
}