Skip to content

Commit 6ea1178

Browse files
committed
fix: fix various bugs with starting the system bridge due to native libraries not being found
1 parent 1332c71 commit 6ea1178

7 files changed

Lines changed: 154 additions & 135 deletions

File tree

sysbridge/src/main/cpp/starter.cpp

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ v_current = (uintptr_t) v + v_size - sizeof(char *); \
9797
ARG_PUSH_FMT(argv, "-Djava.class.path=%s", apk_path)
9898
ARG_PUSH_FMT(argv, "-Dkeymapper_sysbridge.library.path=%s", lib_path)
9999
ARG_PUSH_FMT(argv, "-Dkeymapper_sysbridge.package=%s", package_name)
100-
ARG_PUSH_FMT(argv, "-Dkeymapper_sysbridge.version_code=%s", version_code)
100+
ARG_PUSH_FMT(argv, "-Dkeymapper_sysbridge.version=%s", version_code)
101101
ARG_PUSH_DEBUG_VM_PARAMS(argv)
102102
ARG_PUSH(argv, "/system/bin")
103103
ARG_PUSH_FMT(argv, "--nice-name=%s", process_name)
@@ -120,7 +120,7 @@ static void start_server(const char *apk_path, const char *lib_path, const char
120120
LOGD("child");
121121
run_server(apk_path, lib_path, main_class, process_name, package_name, version_code);
122122
} else {
123-
perrorf("fatal: can't fork\n");
123+
LOGE("fatal: can't fork");
124124
exit(EXIT_FATAL_FORK);
125125
}
126126
}
@@ -130,8 +130,7 @@ static int check_selinux(const char *s, const char *t, const char *c, const char
130130
#ifndef DEBUG
131131
if (res != 0) {
132132
#endif
133-
printf("info: selinux_check_access %s %s %s %s: %d\n", s, t, c, p, res);
134-
fflush(stdout);
133+
LOGI("selinux_check_access %s %s %s %s: %d", s, t, c, p, res);
135134
#ifndef DEBUG
136135
}
137136
#endif
@@ -143,28 +142,23 @@ static int switch_cgroup() {
143142
int spid = getpid();
144143

145144
if (cgroup::get_cgroup(spid, &s_cuid, &s_cpid) != 0) {
146-
printf("warn: can't read cgroup\n");
147-
fflush(stdout);
145+
LOGW("can't read cgroup");
148146
return -1;
149147
}
150148

151-
printf("info: cgroup is /uid_%d/pid_%d\n", s_cuid, s_cpid);
152-
fflush(stdout);
149+
LOGI("cgroup is /uid_%d/pid_%d", s_cuid, s_cpid);
153150

154151
if (cgroup::switch_cgroup(spid, -1, -1) != 0) {
155-
printf("warn: can't switch cgroup\n");
156-
fflush(stdout);
152+
LOGW("can't switch cgroup");
157153
return -1;
158154
}
159155

160156
if (cgroup::get_cgroup(spid, &s_cuid, &s_cpid) != 0) {
161-
printf("info: switch cgroup succeeded\n");
162-
fflush(stdout);
157+
LOGI("switch cgroup succeeded");
163158
return 0;
164159
}
165160

166-
printf("warn: can't switch self, current cgroup is /uid_%d/pid_%d\n", s_cuid, s_cpid);
167-
fflush(stdout);
161+
LOGW("can't switch self, current cgroup is /uid_%d/pid_%d", s_cuid, s_cpid);
168162
return -1;
169163
}
170164

@@ -174,7 +168,7 @@ int starter_main(int argc, char *argv[]) {
174168
char *apk_path = nullptr;
175169
char *lib_path = nullptr;
176170
char *package_name = nullptr;
177-
char *version_code = nullptr;
171+
char *version = nullptr;
178172

179173
// Get the apk path from the program arguments. This gets the path by setting the
180174
// start of the apk path array to after the "--apk=" by offsetting by 6 characters.
@@ -185,19 +179,19 @@ int starter_main(int argc, char *argv[]) {
185179
lib_path = argv[i] + 6;
186180
} else if (strncmp(argv[i], "--package=", 10) == 0) {
187181
package_name = argv[i] + 10;
188-
} else if (strncmp(argv[i], "--version_code=", 15) == 0) {
189-
version_code = argv[i] + 15;
182+
} else if (strncmp(argv[i], "--version=", 10) == 0) {
183+
version = argv[i] + 10;
190184
}
191185
}
192186

193-
printf("info: apk path = %s\n", apk_path);
194-
printf("info: lib path = %s\n", lib_path);
195-
printf("info: package name = %s\n", package_name);
196-
printf("info: version code = %s\n", version_code);
187+
LOGI("apk path = %s", apk_path);
188+
LOGI("lib path = %s", lib_path);
189+
LOGI("package name = %s", package_name);
190+
LOGI("version = %s", version);
197191

198192
int uid = getuid();
199193
if (uid != 0 && uid != 2000) {
200-
perrorf("fatal: run system bridge from non root nor adb user (uid=%d).\n", uid);
194+
LOGE("fatal: run system bridge from non root nor adb user (uid=%d).", uid);
201195
exit(EXIT_FATAL_UID);
202196
}
203197

@@ -215,7 +209,7 @@ int starter_main(int argc, char *argv[]) {
215209
sdkLevel = atoi(buf);
216210

217211
if (sdkLevel >= 29) {
218-
printf("info: switching mount namespace to init...\n");
212+
LOGI("switching mount namespace to init...");
219213
switch_mnt_ns(1);
220214
}
221215
}
@@ -228,27 +222,18 @@ int starter_main(int argc, char *argv[]) {
228222
res |= check_selinux("u:r:untrusted_app:s0", context, "binder", "transfer");
229223

230224
if (res != 0) {
231-
perrorf("fatal: the su you are using does not allow app (u:r:untrusted_app:s0) to connect to su (%s) with binder.\n",
225+
LOGE("fatal: the su you are using does not allow app (u:r:untrusted_app:s0) to connect to su (%s) with binder.",
232226
context);
233227
exit(EXIT_FATAL_BINDER_BLOCKED_BY_SELINUX);
234228
}
235229
se::freecon(context);
236230
}
237231
}
238232

239-
mkdir("/data/local/tmp/keymapper_sysbridge", 0707);
240-
chmod("/data/local/tmp/keymapper_sysbridge", 0707);
241-
if (uid == 0) {
242-
chown("/data/local/tmp/keymapper_sysbridge", 2000, 2000);
243-
se::setfilecon("/data/local/tmp/keymapper_sysbridge", "u:object_r:shell_data_file:s0");
244-
}
245-
246-
printf("info: starter begin\n");
247-
fflush(stdout);
233+
LOGI("starter begin");
248234

249235
// kill old server
250-
printf("info: killing old process...\n");
251-
fflush(stdout);
236+
LOGI("killing old process...");
252237

253238
foreach_proc([](pid_t pid) {
254239
if (pid == getpid()) return;
@@ -259,47 +244,42 @@ int starter_main(int argc, char *argv[]) {
259244
if (strcmp(SERVER_NAME, name) != 0) return;
260245

261246
if (kill(pid, SIGKILL) == 0)
262-
printf("info: killed %d (%s)\n", pid, name);
247+
LOGI("killed %d (%s)", pid, name);
263248
else if (errno == EPERM) {
264-
perrorf("fatal: can't kill %d, please try to stop existing sysbridge from app first.\n",
249+
LOGE("fatal: can't kill %d, please try to stop existing sysbridge from app first.",
265250
pid);
266251
exit(EXIT_FATAL_KILL);
267252
} else {
268-
printf("warn: failed to kill %d (%s)\n", pid, name);
253+
LOGW("failed to kill %d (%s)", pid, name);
269254
}
270255
});
271256

272257
if (access(apk_path, R_OK) == 0) {
273-
printf("info: use apk path from argv\n");
274-
fflush(stdout);
258+
LOGI("use apk path from argv");
275259
}
276260

277261
if (access(lib_path, R_OK) == 0) {
278-
printf("info: use lib path from argv\n");
279-
fflush(stdout);
262+
LOGI("use lib path from argv");
280263
}
281264

282265
if (!apk_path) {
283-
perrorf("fatal: can't get path of manager\n");
266+
LOGE("fatal: can't get path of manager");
284267
exit(EXIT_FATAL_PM_PATH);
285268
}
286269

287270
if (!lib_path) {
288-
perrorf("fatal: can't get path of native libraries\n");
271+
LOGE("fatal: can't get path of native libraries");
289272
exit(EXIT_FATAL_PM_PATH);
290273
}
291274

292-
printf("info: apk path is %s\n", apk_path);
293-
printf("info: lib path is %s\n", lib_path);
294275
if (access(apk_path, R_OK) != 0) {
295-
perrorf("fatal: can't access manager %s\n", apk_path);
276+
LOGE("fatal: can't access manager %s", apk_path);
296277
exit(EXIT_FATAL_PM_PATH);
297278
}
298279

299-
printf("info: starting server...\n");
300-
fflush(stdout);
280+
LOGI("starting server...");
301281
LOGD("start_server");
302-
start_server(apk_path, lib_path, SERVER_CLASS_PATH, SERVER_NAME, package_name, version_code);
282+
start_server(apk_path, lib_path, SERVER_CLASS_PATH, SERVER_NAME, package_name, version);
303283
exit(EXIT_SUCCESS);
304284
}
305285

sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/adb/AdbClient.kt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ internal class AdbClient(private val host: String, private val port: Int, privat
110110
return Success(Unit)
111111
}
112112

113-
fun shellCommand(command: String): ByteArray {
113+
fun shellCommand(command: String, listener: (ByteArray) -> Unit) {
114114
val localId = 1
115115
write(A_OPEN, localId, 0, "shell:$command")
116116

@@ -119,10 +119,11 @@ internal class AdbClient(private val host: String, private val port: Int, privat
119119
A_OKAY -> {
120120
while (true) {
121121
message = read()
122+
122123
val remoteId = message.arg0
123124
if (message.command == A_WRTE) {
124125
if (message.data_length > 0) {
125-
return message.data!!
126+
listener(message.data!!)
126127
}
127128
write(A_OKAY, localId, remoteId)
128129
} else if (message.command == A_CLSE) {
@@ -143,8 +144,6 @@ internal class AdbClient(private val host: String, private val port: Int, privat
143144
error("not A_OKAY or A_CLSE")
144145
}
145146
}
146-
147-
error("No response from adb?")
148147
}
149148

150149
private fun write(command: Int, arg0: Int, arg1: Int, data: ByteArray? = null) = write(
@@ -167,7 +166,7 @@ internal class AdbClient(private val host: String, private val port: Int, privat
167166

168167
private fun read(): AdbMessage {
169168
val buffer =
170-
ByteBuffer.allocate(AdbMessage.Companion.HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN)
169+
ByteBuffer.allocate(AdbMessage.HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN)
171170

172171
inputStream.readFully(buffer.array(), 0, 24)
173172

sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/adb/AdbManager.kt

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,18 @@ class AdbManagerImpl @Inject constructor(
5656

5757
return@withLock with(client) {
5858
connect().then {
59-
try {
60-
client.shellCommand(command).success()
61-
} catch (e: Exception) {
62-
Timber.e(e)
63-
AdbError.Unknown(e)
59+
val output = buildString {
60+
try {
61+
client.shellCommand(command) { append(String(it)) }
62+
} catch (e: Exception) {
63+
Timber.e(e)
64+
AdbError.Unknown(e)
65+
}
6466
}
67+
68+
Success(output)
6569
}
66-
}.then { String(it).success() }
70+
}
6771
}
6872
}
6973

sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/service/SystemBridge.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,13 @@ internal class SystemBridge : ISystemBridge.Stub() {
6767

6868
companion object {
6969
private const val TAG: String = "KeyMapperSystemBridge"
70-
private val systemBridgePackageName: String? =
70+
private val systemBridgePackageName: String? by lazy {
7171
System.getProperty("keymapper_sysbridge.package")
72+
}
7273

73-
private val systemBridgeVersionCode: Int =
74-
System.getProperty("keymapper_sysbridge.version_code")!!.toInt()
74+
private val systemBridgeVersionCode: Int by lazy {
75+
System.getProperty("keymapper_sysbridge.version")?.toIntOrNull() ?: -1
76+
}
7577

7678
private const val KEYMAPPER_CHECK_INTERVAL_MS = 60 * 1000L // 1 minute
7779
private const val DATA_ENABLED_REASON_USER: Int = 0
@@ -140,7 +142,7 @@ internal class SystemBridge : ISystemBridge.Stub() {
140142
private val sendBinderLock: Any = Any()
141143

142144
private val coroutineScope: CoroutineScope = MainScope()
143-
private val mainHandler = Handler(Looper.myLooper()!!)
145+
private val mainHandler by lazy { Handler(Looper.myLooper()!!) }
144146

145147
private val keyMapperCheckLock: Any = Any()
146148
private var keyMapperCheckJob: Job? = null
@@ -175,18 +177,24 @@ internal class SystemBridge : ISystemBridge.Stub() {
175177
}
176178

177179
init {
180+
if (versionCode == -1) {
181+
Log.e(TAG, "SystemBridge version code not set")
182+
throw IllegalStateException("SystemBridge version code not set")
183+
}
184+
178185
val libraryPath = System.getProperty("keymapper_sysbridge.library.path")
179186
@SuppressLint("UnsafeDynamicallyLoadedCode")
180187
System.load("$libraryPath/libevdev.so")
181188

182189
Log.i(TAG, "SystemBridge starting... Version code $versionCode")
183190

184-
waitSystemService("package")
185-
packageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package"))
186-
187191
waitSystemService(Context.ACTIVITY_SERVICE)
188192
waitSystemService(Context.USER_SERVICE)
189193
waitSystemService(Context.APP_OPS_SERVICE)
194+
195+
waitSystemService("package")
196+
packageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package"))
197+
190198
waitSystemService("permissionmgr")
191199
permissionManager =
192200
IPermissionManager.Stub.asInterface(ServiceManager.getService("permissionmgr"))

sysbridge/src/main/java/io/github/sds100/keymapper/sysbridge/service/SystemBridgeSetupController.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,9 @@ class SystemBridgeSetupControllerImpl @Inject constructor(
239239
}
240240

241241
// Try running a command to see if the pairing is working correctly.
242-
isAdbPairedResult.value = adbManager.executeCommand("sh").isSuccess
242+
// This will execute the "exit" command in the shell so it immediately closes
243+
// the connection.
244+
isAdbPairedResult.value = adbManager.executeCommand("exit").isSuccess
243245
}
244246
}
245247

0 commit comments

Comments
 (0)