Skip to content

Commit dd54a70

Browse files
authored
Merge pull request #708 from Tencent/dev
sync dev to master.
2 parents 1e462d9 + 335b32d commit dd54a70

File tree

16 files changed

+231
-108
lines changed

16 files changed

+231
-108
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
# This option should only be used with decoupled projects. More details, visit
1717
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
1818
# org.gradle.parallel=true
19-
VERSION_NAME_PREFIX=1.9.1
19+
VERSION_NAME_PREFIX=1.9.2
2020
VERSION_NAME_SUFFIX=

tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/patch/BasePatchInternal.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ public static boolean extract(ZipFile zipFile, ZipEntry entryFile, File extractT
8686
TinkerLog.i(TAG, "isExtractionSuccessful: %b", isExtractionSuccessful);
8787

8888
if (!isExtractionSuccessful) {
89-
extractTo.delete();
90-
if (extractTo.exists()) {
89+
final boolean succ = extractTo.delete();
90+
if (!succ || extractTo.exists()) {
9191
TinkerLog.e(TAG, "Failed to delete corrupted dex " + extractTo.getPath());
9292
}
9393
}

tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/patch/DexDiffPatchInternal.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -257,15 +257,17 @@ private static boolean mergeClassNDexFiles(final Context context, final File pat
257257
File dexFile = classNDexInfo.get(info);
258258

259259
if (info.isJarMode) {
260-
TinkerZipFile dexZipFile = new TinkerZipFile(dexFile);
261-
TinkerZipEntry rawDexZipEntry = dexZipFile.getEntry(ShareConstants.DEX_IN_JAR);
262-
TinkerZipEntry newDexZipEntry = new TinkerZipEntry(rawDexZipEntry, info.rawName);
260+
TinkerZipFile dexZipFile = null;
263261
InputStream inputStream = null;
264262
try {
263+
dexZipFile = new TinkerZipFile(dexFile);
264+
TinkerZipEntry rawDexZipEntry = dexZipFile.getEntry(ShareConstants.DEX_IN_JAR);
265+
TinkerZipEntry newDexZipEntry = new TinkerZipEntry(rawDexZipEntry, info.rawName);
265266
inputStream = dexZipFile.getInputStream(rawDexZipEntry);
266267
TinkerZipUtil.extractTinkerEntry(newDexZipEntry, inputStream, out);
267268
} finally {
268269
StreamUtil.closeQuietly(inputStream);
270+
StreamUtil.closeQuietly(dexZipFile);
269271
}
270272
} else {
271273
TinkerZipEntry dexZipEntry = new TinkerZipEntry(info.rawName);
@@ -597,8 +599,8 @@ private static boolean extractDexToJar(ZipFile zipFile, ZipEntry entryFile, File
597599
TinkerLog.i(TAG, "isExtractionSuccessful: %b", isExtractionSuccessful);
598600

599601
if (!isExtractionSuccessful) {
600-
extractTo.delete();
601-
if (extractTo.exists()) {
602+
final boolean succ = extractTo.delete();
603+
if (!succ || extractTo.exists()) {
602604
TinkerLog.e(TAG, "Failed to delete corrupted dex " + extractTo.getPath());
603605
}
604606
}

tinker-android/tinker-android-lib/src/main/java/com/tencent/tinker/lib/tinker/TinkerApplicationHelper.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import java.io.File;
3030
import java.util.HashMap;
31+
import java.util.Map;
3132

3233
/**
3334
* sometimes, you may want to install tinker later, or never install tinker in some process.
@@ -317,7 +318,8 @@ public static boolean loadLibraryFromTinker(ApplicationLike applicationLike, Str
317318
File patchVersionDirectory = new File(patchDirectory.getAbsolutePath() + "/" + SharePatchFileUtil.getPatchVersionDirectory(currentVersion));
318319
String libPrePath = patchVersionDirectory.getAbsolutePath() + "/" + ShareConstants.SO_PATH;
319320

320-
for (String name : loadLibraries.keySet()) {
321+
for (Map.Entry<String, String> libEntry : loadLibraries.entrySet()) {
322+
final String name = libEntry.getKey();
321323
if (name.equals(relativeLibPath)) {
322324
String patchLibraryPath = libPrePath + "/" + name;
323325
File library = new File(patchLibraryPath);

tinker-android/tinker-android-loader/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ android {
2121
dependencies {
2222
compile fileTree(dir: 'libs', include: ['*.jar'])
2323
testCompile 'junit:junit:4.12'
24-
compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
24+
compile "com.android.support:support-annotations:${rootProject.ext.supportLibVersion}"
2525
}
2626

2727
task buildTinkerSdk(type: Copy, dependsOn: [build]) {

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ private void tryLoadPatchFilesInternal(TinkerApplication app, Intent resultInten
163163
}
164164

165165
//tinker/patch.info/patch-641e634c/patch-641e634c.apk
166-
File patchVersionFile = new File(patchVersionDirectoryFile.getAbsolutePath(), SharePatchFileUtil.getPatchVersionFile(version));
166+
final String patchVersionFileRelPath = SharePatchFileUtil.getPatchVersionFile(version);
167+
File patchVersionFile = (patchVersionFileRelPath != null ? new File(patchVersionDirectoryFile.getAbsolutePath(), patchVersionFileRelPath) : null);
167168

168169
if (!SharePatchFileUtil.isLegalFile(patchVersionFile)) {
169170
Log.w(TAG, "tryLoadPatchFiles:onPatchVersionFileNotFound");

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@
2525
import android.util.Log;
2626

2727
import com.tencent.tinker.loader.shareutil.ShareConstants;
28+
import com.tencent.tinker.loader.shareutil.SharePatchFileUtil;
2829
import com.tencent.tinker.loader.shareutil.ShareReflectUtil;
2930

31+
import java.io.InputStream;
3032
import java.lang.ref.WeakReference;
3133
import java.lang.reflect.Constructor;
3234
import java.lang.reflect.Field;
@@ -271,11 +273,14 @@ private static void clearPreloadTypedArrayIssue(Resources resources) {
271273
}
272274

273275
private static boolean checkResUpdate(Context context) {
276+
InputStream is = null;
274277
try {
275-
context.getAssets().open(TEST_ASSETS_VALUE);
278+
is = context.getAssets().open(TEST_ASSETS_VALUE);
276279
} catch (Throwable e) {
277280
Log.e(TAG, "checkResUpdate failed, can't find test resource assets file " + TEST_ASSETS_VALUE + " e:" + e.getMessage());
278281
return false;
282+
} finally {
283+
SharePatchFileUtil.closeQuietly(is);
279284
}
280285
Log.i(TAG, "checkResUpdate success, found test resource assets file " + TEST_ASSETS_VALUE);
281286
return true;

tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/hotplug/IncrementComponentManager.java

Lines changed: 70 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,51 +121,82 @@ void onTranslate(Context context, int tagType, String attrName, String attrValue
121121
} else if ("multiprocess".equals(attrName)) {
122122
if ("true".equalsIgnoreCase(attrValue)) {
123123
result.flags |= ActivityInfo.FLAG_MULTIPROCESS;
124+
} else {
125+
result.flags &= ~ActivityInfo.FLAG_MULTIPROCESS;
124126
}
125127
} else if ("finishOnTaskLaunch".equals(attrName)) {
126128
if ("true".equalsIgnoreCase(attrValue)) {
127129
result.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
130+
} else {
131+
result.flags &= ~ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
128132
}
129133
} else if ("clearTaskOnLaunch".equals(attrName)) {
130134
if ("true".equalsIgnoreCase(attrValue)) {
131135
result.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
136+
} else {
137+
result.flags &= ~ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
132138
}
133139
} else if ("noHistory".equals(attrName)) {
134140
if ("true".equalsIgnoreCase(attrValue)) {
135141
result.flags |= ActivityInfo.FLAG_NO_HISTORY;
142+
} else {
143+
result.flags &= ~ActivityInfo.FLAG_NO_HISTORY;
136144
}
137145
} else if ("alwaysRetainTaskState".equals(attrName)) {
138146
if ("true".equalsIgnoreCase(attrValue)) {
139147
result.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
148+
} else {
149+
result.flags &= ~ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
140150
}
141151
} else if ("stateNotNeeded".equals(attrName)) {
142152
if ("true".equalsIgnoreCase(attrValue)) {
143153
result.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
154+
} else {
155+
result.flags &= ~ActivityInfo.FLAG_STATE_NOT_NEEDED;
144156
}
145157
} else if ("excludeFromRecents".equals(attrName)) {
146158
if ("true".equalsIgnoreCase(attrValue)) {
147159
result.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
160+
} else {
161+
result.flags &= ~ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
148162
}
149163
} else if ("allowTaskReparenting".equals(attrName)) {
150164
if ("true".equalsIgnoreCase(attrValue)) {
151165
result.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
166+
} else {
167+
result.flags &= ~ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
152168
}
153169
} else if ("finishOnCloseSystemDialogs".equals(attrName)) {
154170
if ("true".equalsIgnoreCase(attrValue)) {
155171
result.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
172+
} else {
173+
result.flags &= ~ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
156174
}
157175
} else if ("showOnLockScreen".equals(attrName) || "showForAllUsers".equals(attrName)) {
158-
if (Build.VERSION.SDK_INT >= 23 && "true".equalsIgnoreCase(attrValue)) {
159-
result.flags |= ShareReflectUtil.getValueOfStaticIntField(ActivityInfo.class,
160-
"FLAG_SHOW_FOR_ALL_USERS", 0);
176+
if (Build.VERSION.SDK_INT >= 23) {
177+
final int flag = ShareReflectUtil
178+
.getValueOfStaticIntField(ActivityInfo.class, "FLAG_SHOW_FOR_ALL_USERS", 0);
179+
if ("true".equalsIgnoreCase(attrValue)) {
180+
result.flags |= flag;
181+
} else {
182+
result.flags &= ~flag;
183+
}
161184
}
162185
} else if ("immersive".equals(attrName)) {
163-
if (Build.VERSION.SDK_INT >= 18 && "true".equalsIgnoreCase(attrValue)) {
164-
result.flags |= ActivityInfo.FLAG_IMMERSIVE;
186+
if (Build.VERSION.SDK_INT >= 18) {
187+
if ("true".equalsIgnoreCase(attrValue)) {
188+
result.flags |= ActivityInfo.FLAG_IMMERSIVE;
189+
} else {
190+
result.flags &= ~ActivityInfo.FLAG_IMMERSIVE;
191+
}
165192
}
166193
} else if ("hardwareAccelerated".equals(attrName)) {
167-
if (Build.VERSION.SDK_INT >= 11 && "true".equalsIgnoreCase(attrValue)) {
168-
result.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
194+
if (Build.VERSION.SDK_INT >= 11) {
195+
if ("true".equalsIgnoreCase(attrValue)) {
196+
result.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
197+
} else {
198+
result.flags &= ~ActivityInfo.FLAG_HARDWARE_ACCELERATED;
199+
}
169200
}
170201
} else if ("documentLaunchMode".equals(attrName)) {
171202
if (Build.VERSION.SDK_INT >= 21) {
@@ -184,20 +215,36 @@ void onTranslate(Context context, int tagType, String attrName, String attrValue
184215
result.persistableMode = Integer.decode(attrValue);
185216
}
186217
} else if ("allowEmbedded".equals(attrName)) {
218+
final int flag = ShareReflectUtil
219+
.getValueOfStaticIntField(ActivityInfo.class, "FLAG_ALLOW_EMBEDDED", 0);
187220
if ("true".equalsIgnoreCase(attrValue)) {
188-
result.flags |= ShareReflectUtil.getValueOfStaticIntField(ActivityInfo.class, "FLAG_ALLOW_EMBEDDED", 0);
221+
result.flags |= flag;
222+
} else {
223+
result.flags &= ~flag;
189224
}
190225
} else if ("autoRemoveFromRecents".equals(attrName)) {
191-
if (Build.VERSION.SDK_INT >= 21 && "true".equalsIgnoreCase(attrValue)) {
192-
result.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
226+
if (Build.VERSION.SDK_INT >= 21) {
227+
if ("true".equalsIgnoreCase(attrValue)) {
228+
result.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
229+
} else {
230+
result.flags &= ~ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
231+
}
193232
}
194233
} else if ("relinquishTaskIdentity".equals(attrName)) {
195-
if (Build.VERSION.SDK_INT >= 21 && "true".equalsIgnoreCase(attrValue)) {
196-
result.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
234+
if (Build.VERSION.SDK_INT >= 21) {
235+
if ("true".equalsIgnoreCase(attrValue)) {
236+
result.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
237+
} else {
238+
result.flags &= ~ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
239+
}
197240
}
198241
} else if ("resumeWhilePausing".equals(attrName)) {
199-
if (Build.VERSION.SDK_INT >= 21 && "true".equalsIgnoreCase(attrValue)) {
200-
result.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
242+
if (Build.VERSION.SDK_INT >= 21) {
243+
if ("true".equalsIgnoreCase(attrValue)) {
244+
result.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
245+
} else {
246+
result.flags &= ~ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
247+
}
201248
}
202249
} else if ("screenOrientation".equals(attrName)) {
203250
result.screenOrientation = parseScreenOrientation(attrValue);
@@ -307,8 +354,9 @@ public static synchronized boolean init(Context context, ShareSecurityCheck chec
307354
sPackageName = context.getPackageName();
308355
final String xmlMeta = checker.getMetaContentMap().get(EnvConsts.INCCOMPONENT_META_FILE);
309356
StringReader sr = new StringReader(xmlMeta);
357+
XmlPullParser parser = null;
310358
try {
311-
final XmlPullParser parser = Xml.newPullParser();
359+
parser = Xml.newPullParser();
312360
parser.setInput(sr);
313361
int event = parser.getEventType();
314362
while (event != XmlPullParser.END_DOCUMENT) {
@@ -336,6 +384,13 @@ public static synchronized boolean init(Context context, ShareSecurityCheck chec
336384
} catch (XmlPullParserException e) {
337385
throw new IOException(e);
338386
} finally {
387+
if (parser != null) {
388+
try {
389+
parser.setInput(null);
390+
} catch (Throwable ignored) {
391+
// Ignored.
392+
}
393+
}
339394
SharePatchFileUtil.closeQuietly(sr);
340395
}
341396
}

tinker-android/tinker-android-loader/src/main/java/com/tencent/tinker/loader/hotplug/interceptor/ServiceBinderInterceptor.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727

2828
public class ServiceBinderInterceptor extends Interceptor<IBinder> {
2929
private static final String TAG = "Tinker.SvcBndrIntrcptr";
30-
private static final ClassLoader MY_CLASSLOADER = ServiceBinderInterceptor.class.getClassLoader();
3130

3231
private final Context mBaseContext;
3332
private final String mServiceName;
@@ -76,7 +75,7 @@ protected IBinder decorate(@Nullable IBinder target) throws Throwable {
7675
// Already intercepted, just return the target.
7776
return target;
7877
} else {
79-
return createProxy(target.getClass().getClassLoader(), getAllInterfacesThroughDeriveChain(target.getClass()),
78+
return createProxy(getAllInterfacesThroughDeriveChain(target.getClass()),
8079
new FakeClientBinderHandler(target, mBinderInvocationHandler));
8180
}
8281
}
@@ -145,20 +144,39 @@ private static void fixPMSBinderCache(Context context, IBinder fakeBinder) throw
145144
}
146145

147146
@SuppressWarnings("unchecked")
148-
private static <T> T createProxy(ClassLoader cl, Class<?>[] itfs, InvocationHandler handler) {
147+
private static <T> T createProxy(Class<?>[] itfs, InvocationHandler handler) {
149148
final Class<?>[] mergedItfs = new Class<?>[itfs.length + 1];
150149
System.arraycopy(itfs, 0, mergedItfs, 0, itfs.length);
151150
mergedItfs[itfs.length] = ITinkerHotplugProxy.class;
151+
ClassLoader cl = null;
152152
try {
153-
return (T) Proxy.newProxyInstance(MY_CLASSLOADER, mergedItfs, handler);
153+
cl = Thread.currentThread().getContextClassLoader();
154+
return (T) Proxy.newProxyInstance(cl, mergedItfs, handler);
154155
} catch (Throwable thr) {
155-
if (cl != null && cl != MY_CLASSLOADER) {
156-
try {
157-
return (T) Proxy.newProxyInstance(cl, mergedItfs, handler);
158-
} catch (Throwable thr2) {
159-
throw new RuntimeException("cl: " + cl, thr);
160-
}
156+
final Set<ClassLoader> uniqueCls = new HashSet<>(4);
157+
for (Class<?> itf : mergedItfs) {
158+
uniqueCls.add(itf.getClassLoader());
159+
}
160+
if (uniqueCls.size() == 1) {
161+
cl = uniqueCls.iterator().next();
161162
} else {
163+
cl = new ClassLoader() {
164+
@Override
165+
protected Class<?> loadClass(String className, boolean resolve)
166+
throws ClassNotFoundException {
167+
for (ClassLoader cl : uniqueCls) {
168+
final Class<?> res = cl.loadClass(className);
169+
if (res != null) {
170+
return res;
171+
}
172+
}
173+
throw new ClassNotFoundException("cannot find class: " + className);
174+
}
175+
};
176+
}
177+
try {
178+
return (T) Proxy.newProxyInstance(cl, mergedItfs, handler);
179+
} catch (Throwable thr2) {
162180
throw new RuntimeException("cl: " + cl, thr);
163181
}
164182
}
@@ -209,8 +227,7 @@ public Object invoke(Object fakeClientBinder, Method method, Object[] args) thro
209227
final InvocationHandler fakeInterfaceHandler
210228
= new FakeInterfaceHandler(originalInterface, (IBinder) fakeClientBinder, mBinderInvocationHandler);
211229

212-
return createProxy(originalInterface.getClass().getClassLoader(),
213-
getAllInterfacesThroughDeriveChain(originalInterface.getClass()), fakeInterfaceHandler);
230+
return createProxy(getAllInterfacesThroughDeriveChain(originalInterface.getClass()), fakeInterfaceHandler);
214231
} else {
215232
return method.invoke(mOriginalClientBinder, args);
216233
}

0 commit comments

Comments
 (0)