Skip to content

Commit d682c32

Browse files
committed
fix: main thread blocked
The main thread is blocked, which causes the Receiver to malfunction.
1 parent 754feda commit d682c32

1 file changed

Lines changed: 42 additions & 56 deletions

File tree

app-process/src/main/java/com/rosan/app_process/NewProcessReceiver.java

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,81 +7,67 @@
77
import android.content.IntentFilter;
88
import android.os.Build;
99
import android.os.Bundle;
10+
import android.os.Handler;
11+
import android.os.HandlerThread;
1012
import android.os.IBinder;
1113

1214
import androidx.annotation.NonNull;
1315

1416
import java.io.IOException;
1517
import java.util.Objects;
1618
import java.util.UUID;
17-
import java.util.concurrent.ExecutionException;
18-
import java.util.concurrent.ExecutorService;
19-
import java.util.concurrent.Executors;
20-
import java.util.concurrent.Future;
21-
import java.util.concurrent.LinkedBlockingQueue;
19+
import java.util.concurrent.Exchanger;
2220
import java.util.concurrent.TimeUnit;
23-
import java.util.concurrent.atomic.AtomicReference;
21+
import java.util.concurrent.TimeoutException;
2422

2523
abstract class NewProcessReceiver extends BroadcastReceiver {
26-
private static boolean waitFor(Process process, long timeout, TimeUnit unit) throws InterruptedException {
27-
long startTime = System.nanoTime();
28-
long rem = unit.toNanos(timeout);
24+
public static IBinder start(Context context, AppProcess appProcess, ComponentName componentName) {
25+
final String token = UUID.randomUUID().toString();
2926

30-
do {
31-
try {
32-
process.exitValue();
33-
return true;
34-
} catch (IllegalArgumentException ex) {
35-
if (rem > 0)
36-
Thread.sleep(
37-
Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100));
38-
}
39-
rem = unit.toNanos(timeout) - (System.nanoTime() - startTime);
40-
} while (rem > 0);
41-
return false;
42-
}
27+
final Exchanger<IBinder> exchanger = new Exchanger<>();
4328

44-
public static IBinder start(Context context, AppProcess appProcess, ComponentName componentName) {
45-
String token = UUID.randomUUID().toString();
46-
IntentFilter filter = new IntentFilter();
47-
filter.addAction(ACTION_SEND_NEW_PROCESS);
48-
LinkedBlockingQueue<AtomicReference<NewProcessResult>> queue = new LinkedBlockingQueue<>();
49-
BroadcastReceiver receiver = new NewProcessReceiver() {
29+
HandlerThread worker = new HandlerThread("IPCWorker");
30+
worker.start();
31+
32+
BroadcastReceiver receiver = new BroadcastReceiver() {
5033
@Override
51-
void onReceive(NewProcessResult result) {
52-
if (!result.getToken().equals(token)) return;
53-
queue.offer(new AtomicReference<>(result));
34+
public void onReceive(Context context, Intent intent) {
35+
if (token.equals(intent.getStringExtra(NewProcessReceiver.EXTRA_TOKEN))) {
36+
IBinder binder = intent.getExtras().getBinder(NewProcessReceiver.EXTRA_NEW_PROCESS);
37+
try {
38+
exchanger.exchange(binder);
39+
} catch (InterruptedException ignored) {
40+
Thread.currentThread().interrupt();
41+
}
42+
}
5443
}
5544
};
56-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
57-
context.registerReceiver(receiver, filter, Context.RECEIVER_NOT_EXPORTED);
58-
else context.registerReceiver(receiver, filter);
59-
ExecutorService executorService = Executors.newCachedThreadPool();
60-
Future<AtomicReference<NewProcessResult>> future = executorService.submit(queue::take);
45+
6146
try {
62-
Process process = appProcess.start(context.getPackageCodePath(), NewProcess.class, new String[]{
63-
String.format("--package=%s", context.getPackageName()),
64-
String.format("--token=%s", token),
65-
String.format("--component=%s", componentName.flattenToString())
66-
});
67-
executorService.execute(() -> {
68-
try {
69-
waitFor(process, 15, TimeUnit.SECONDS);
70-
} catch (Throwable e) {
71-
e.printStackTrace();
72-
}
73-
queue.offer(new AtomicReference<>());
47+
IntentFilter filter = new IntentFilter(ACTION_SEND_NEW_PROCESS);
48+
Handler handler = new Handler(worker.getLooper());
49+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
50+
context.registerReceiver(receiver, filter, null, handler, Context.RECEIVER_NOT_EXPORTED);
51+
} else {
52+
context.registerReceiver(receiver, filter, null, handler);
53+
}
54+
55+
appProcess.start(context.getPackageCodePath(), NewProcess.class, new String[]{
56+
"--package=" + context.getPackageName(),
57+
"--token=" + token,
58+
"--component=" + componentName.flattenToString()
7459
});
75-
NewProcessResult result = future.get().get();
76-
IBinder binder = result != null ? result.getBinder() : null;
77-
if (binder == null) process.destroy();
78-
return binder;
79-
} catch (IOException | ExecutionException | InterruptedException e) {
80-
e.printStackTrace();
60+
61+
return exchanger.exchange(null, 15, TimeUnit.SECONDS);
62+
63+
} catch (TimeoutException | InterruptedException | IOException e) {
8164
return null;
8265
} finally {
83-
context.unregisterReceiver(receiver);
84-
executorService.shutdown();
66+
try {
67+
context.unregisterReceiver(receiver);
68+
} catch (Exception ignored) {
69+
}
70+
worker.quitSafely();
8571
}
8672
}
8773

0 commit comments

Comments
 (0)