Skip to content

Commit 1044ce2

Browse files
committed
Revert "[tinker] Avoid suicide after system theme was changed."
This reverts commit 9d2ecb5.
1 parent fac7c90 commit 1044ce2

File tree

4 files changed

+268
-210
lines changed

4 files changed

+268
-210
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package com.tencent.tinker.loader;
2+
3+
import android.app.Application;
4+
import android.content.Context;
5+
import android.os.Build;
6+
import android.os.Handler;
7+
import android.os.Message;
8+
import android.os.Process;
9+
import android.util.Log;
10+
11+
import com.tencent.tinker.loader.app.TinkerApplication;
12+
import com.tencent.tinker.loader.shareutil.ShareReflectUtil;
13+
import com.tencent.tinker.loader.shareutil.ShareTinkerLog;
14+
15+
import java.lang.reflect.Field;
16+
17+
/**
18+
* Created by tangyinsheng on 2020/5/10.
19+
* <p>
20+
* Some situations may cause our resource modification to be ineffective,
21+
* for example, an APPLICATION_INFO_CHANGED message will reset LoadedApk#mResDir
22+
* to default value, then a relaunch activity which using tinker resources may
23+
* throw an Resources$NotFoundException.
24+
* <p>
25+
* Monitor and handle them.
26+
* <p>
27+
*
28+
*/
29+
public final class AppInfoChangedBlocker {
30+
private static final String TAG = "Tinker.AppInfoChangedBlocker";
31+
32+
public static boolean tryStart(Application app) {
33+
if (Build.VERSION.SDK_INT < 26) {
34+
Log.i(TAG, "tryStart: SDK_INT is less than 26, skip rest logic.");
35+
return true;
36+
}
37+
try {
38+
ShareTinkerLog.i(TAG, "tryStart called.");
39+
interceptHandler(fetchMHObject(app));
40+
ShareTinkerLog.i(TAG, "tryStart done.");
41+
return true;
42+
} catch (Throwable e) {
43+
ShareTinkerLog.e(TAG, "AppInfoChangedBlocker start failed, simply ignore.", e);
44+
return false;
45+
}
46+
}
47+
48+
private static Handler fetchMHObject(Context context) throws Exception {
49+
final Object activityThread = ShareReflectUtil.getActivityThread(context, null);
50+
final Field mHField = ShareReflectUtil.findField(activityThread, "mH");
51+
return (Handler) mHField.get(activityThread);
52+
}
53+
54+
private static void interceptHandler(Handler mH) throws Exception {
55+
final Field mCallbackField = ShareReflectUtil.findField(Handler.class, "mCallback");
56+
final Handler.Callback originCallback = (Handler.Callback) mCallbackField.get(mH);
57+
if (!(originCallback instanceof HackerCallback)) {
58+
HackerCallback hackerCallback = new HackerCallback(originCallback, mH.getClass());
59+
mCallbackField.set(mH, hackerCallback);
60+
} else {
61+
ShareTinkerLog.w(TAG, "Already intercepted, skip rest logic.");
62+
}
63+
}
64+
65+
private static class HackerCallback implements Handler.Callback {
66+
67+
private final int APPLICATION_INFO_CHANGED;
68+
69+
private Handler.Callback origin;
70+
71+
HackerCallback(Handler.Callback ori, Class $H) {
72+
this.origin = ori;
73+
int appInfoChanged;
74+
try {
75+
appInfoChanged = ShareReflectUtil.findField($H, "APPLICATION_INFO_CHANGED").getInt(null);
76+
} catch (Throwable e) {
77+
appInfoChanged = 156; // default value
78+
}
79+
APPLICATION_INFO_CHANGED = appInfoChanged;
80+
}
81+
82+
@Override
83+
public boolean handleMessage(Message msg) {
84+
boolean consume = false;
85+
if (hackMessage(msg)) {
86+
consume = true;
87+
} else if (origin != null) {
88+
consume = origin.handleMessage(msg);
89+
}
90+
return consume;
91+
}
92+
93+
private boolean hackMessage(Message msg) {
94+
if (msg.what == APPLICATION_INFO_CHANGED) {
95+
// We are generally in the background this moment(signal trigger is
96+
// in front of user), and the signal was going to relaunch all our
97+
// activities to apply new overlay resources. So we could simply kill
98+
// ourselves, or ignore this signal, or reload tinker resources.
99+
ShareTinkerLog.w(TAG, "Suicide now.");
100+
Process.killProcess(Process.myPid());
101+
return true;
102+
}
103+
return false;
104+
}
105+
106+
}
107+
}

tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/PatchedResourcesInsuranceLogic.java

-204
This file was deleted.

tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/TinkerLoader.java

+6
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,12 @@ private void tryLoadPatchFilesInternal(TinkerApplication app, Intent resultInten
389389
ComponentHotplug.install(app, securityCheck);
390390
}
391391

392+
if (!AppInfoChangedBlocker.tryStart(app)) {
393+
ShareTinkerLog.w(TAG, "tryLoadPatchFiles:AppInfoChangedBlocker install fail.");
394+
ShareIntentUtil.setIntentReturnCode(resultIntent, ShareConstants.ERROR_LOAD_PATCH_BAIL_HACK_FAILURE);
395+
return;
396+
}
397+
392398
// Before successfully exit, we should update stored version info and kill other process
393399
// to make them load latest patch when we first applied newer one.
394400
if (mainProcess && (versionChanged || oatModeChanged)) {

0 commit comments

Comments
 (0)