Skip to content

Commit dfac963

Browse files
committed
fix: rebind to the key event relay service when receiving a broadcast to do so
1 parent df54fd6 commit dfac963

2 files changed

Lines changed: 54 additions & 17 deletions

File tree

app/src/main/java/io/github/sds100/keymapper/inputmethod/latin/KeyEventRelayServiceWrapper.kt

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package io.github.sds100.keymapper.inputmethod.latin
22

3+
import android.content.BroadcastReceiver
34
import android.content.ComponentName
45
import android.content.Context
56
import android.content.Intent
7+
import android.content.IntentFilter
68
import android.content.ServiceConnection
79
import android.os.DeadObjectException
810
import android.os.IBinder
911
import android.os.RemoteException
1012
import android.util.Log
1113
import android.view.KeyEvent
14+
import androidx.core.content.ContextCompat
1215
import io.github.sds100.keymapper.api.IKeyEventRelayService
1316
import io.github.sds100.keymapper.api.IKeyEventRelayServiceCallback
1417

@@ -29,7 +32,10 @@ class KeyEventRelayServiceWrapperImpl(
2932
) : KeyEventRelayServiceWrapper {
3033

3134
companion object {
32-
const val ACTION_BIND_RELAY_SERVICE = "io.github.sds100.keymapper.ACTION_BIND_RELAY_SERVICE"
35+
/**
36+
* This is used to listen to when the key event relay service is restarted in Key Mapper.
37+
*/
38+
const val ACTION_REBIND_RELAY_SERVICE = "io.github.sds100.keymapper.ACTION_REBIND_RELAY_SERVICE"
3339
}
3440

3541
private val ctx: Context = context.applicationContext
@@ -46,23 +52,44 @@ class KeyEventRelayServiceWrapperImpl(
4652
) {
4753
synchronized(keyEventRelayServiceLock) {
4854
keyEventRelayService = IKeyEventRelayService.Stub.asInterface(service)
49-
Log.d(LatinIME.TAG, "Register with key event relay service")
55+
Log.d(LatinIME.TAG, "Key event relay service started: $servicePackageName")
5056
keyEventRelayService?.registerCallback(callback)
5157
}
5258
}
5359

5460
override fun onServiceDisconnected(name: ComponentName?) {
5561
synchronized(keyEventRelayServiceLock) {
56-
try {
57-
Log.d(LatinIME.TAG, "Unregister with key event relay service")
58-
keyEventRelayService?.unregisterCallback()
59-
} catch (_: RemoteException) {
60-
} finally {
61-
keyEventRelayService = null
62-
}
62+
// Do not unregister the callback in onServiceDisconnected
63+
// because the connection is already broken at that point and it
64+
// will fail.
65+
66+
Log.d(LatinIME.TAG, "Key event relay service stopped: $servicePackageName")
67+
68+
keyEventRelayService = null
69+
}
70+
}
71+
}
72+
73+
private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() {
74+
override fun onReceive(context: Context?, intent: Intent?) {
75+
context ?: return
76+
intent ?: return
77+
78+
when (intent.action) {
79+
ACTION_REBIND_RELAY_SERVICE -> {
80+
bind()
6381
}
6482
}
6583
}
84+
}
85+
86+
init {
87+
val intentFilter = IntentFilter().apply {
88+
addAction(ACTION_REBIND_RELAY_SERVICE)
89+
}
90+
91+
ContextCompat.registerReceiver(ctx, broadcastReceiver, intentFilter, ContextCompat.RECEIVER_EXPORTED)
92+
}
6693

6794
override fun sendKeyEvent(
6895
event: KeyEvent?,
@@ -106,6 +133,15 @@ class KeyEventRelayServiceWrapperImpl(
106133
// an exception is thrown if you unbind from a service
107134
// while there is no registered connection.
108135
if (isBound) {
136+
// Unregister the callback if this input method is unbinding
137+
// from the relay service. This should not happen in onServiceDisconnected
138+
// because the connection is already broken at that point and it
139+
// will fail.
140+
try {
141+
keyEventRelayService?.unregisterCallback()
142+
} catch (e: RemoteException) {
143+
// do nothing
144+
}
109145
ctx.unbindService(serviceConnection)
110146
}
111147
}

app/src/main/java/io/github/sds100/keymapper/inputmethod/latin/LatinIME.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858

5959
import javax.annotation.Nonnull;
6060

61+
import androidx.core.content.ContextCompat;
6162
import io.github.sds100.keymapper.api.IKeyEventRelayServiceCallback;
6263
import io.github.sds100.keymapper.inputmethod.accessibility.AccessibilityUtils;
6364
import io.github.sds100.keymapper.inputmethod.annotations.UsedForTesting;
@@ -744,39 +745,39 @@ public void onCreate() {
744745
// Register to receive ringer mode change.
745746
final IntentFilter filter = new IntentFilter();
746747
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
747-
registerReceiver(mRingerModeChangeReceiver, filter);
748+
ContextCompat.registerReceiver(this, mRingerModeChangeReceiver, filter, ContextCompat.RECEIVER_EXPORTED);
748749

749750
// Register to receive installation and removal of a dictionary pack.
750751
final IntentFilter packageFilter = new IntentFilter();
751752
packageFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
752753
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
753754
packageFilter.addDataScheme(SCHEME_PACKAGE);
754-
registerReceiver(mDictionaryPackInstallReceiver, packageFilter);
755+
ContextCompat.registerReceiver(this, mDictionaryPackInstallReceiver, packageFilter, ContextCompat.RECEIVER_EXPORTED);
755756

756757
final IntentFilter newDictFilter = new IntentFilter();
757758
newDictFilter.addAction(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
758-
registerReceiver(mDictionaryPackInstallReceiver, newDictFilter);
759+
ContextCompat.registerReceiver(this, mDictionaryPackInstallReceiver, newDictFilter, ContextCompat.RECEIVER_NOT_EXPORTED);
759760

760761
final IntentFilter dictDumpFilter = new IntentFilter();
761762
dictDumpFilter.addAction(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION);
762-
registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter);
763+
ContextCompat.registerReceiver(this, mDictionaryDumpBroadcastReceiver, dictDumpFilter, ContextCompat.RECEIVER_NOT_EXPORTED);
763764

764765
final IntentFilter hideSoftInputFilter = new IntentFilter();
765766
hideSoftInputFilter.addAction(ACTION_HIDE_SOFT_INPUT);
766-
registerReceiver(mHideSoftInputReceiver, hideSoftInputFilter, PERMISSION_HIDE_SOFT_INPUT,
767-
null /* scheduler */);
767+
ContextCompat.registerReceiver(this, mHideSoftInputReceiver, hideSoftInputFilter, PERMISSION_HIDE_SOFT_INPUT,
768+
null /* scheduler */, ContextCompat.RECEIVER_EXPORTED);
768769

769770
final IntentFilter restartAfterUnlockFilter = new IntentFilter();
770771
restartAfterUnlockFilter.addAction(Intent.ACTION_USER_UNLOCKED);
771-
registerReceiver(mRestartAfterDeviceUnlockReceiver, restartAfterUnlockFilter);
772+
ContextCompat.registerReceiver(this, mRestartAfterDeviceUnlockReceiver, restartAfterUnlockFilter, ContextCompat.RECEIVER_EXPORTED);
772773

773774
final IntentFilter keyMapperIntentFilter = new IntentFilter();
774775
keyMapperIntentFilter.addAction(KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN_UP);
775776
keyMapperIntentFilter.addAction(KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_DOWN);
776777
keyMapperIntentFilter.addAction(KEY_MAPPER_INPUT_METHOD_ACTION_INPUT_UP);
777778
keyMapperIntentFilter.addAction(KEY_MAPPER_INPUT_METHOD_ACTION_TEXT);
778779

779-
registerReceiver(mKeyMapperBroadcastReceiver, keyMapperIntentFilter);
780+
ContextCompat.registerReceiver(this, mKeyMapperBroadcastReceiver, keyMapperIntentFilter, ContextCompat.RECEIVER_EXPORTED);
780781

781782
// Connect to the different key mapper build types.
782783
mKeyEventRelayServiceWrapperRelease =

0 commit comments

Comments
 (0)