Skip to content

Commit be55963

Browse files
committed
Merge commit '1b7cfbf722e00fb1ea858ba8e356c32ce4e92ec0'
# Conflicts: # PluginDemo/build.gradle # README.md # build.gradle # virtualapk-gradle-plugin/gradle.properties
2 parents e6cf90c + 1b7cfbf commit be55963

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1087
-351
lines changed

AndroidStub/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,6 @@ uploadArchives {
6363

6464
dependencies {
6565
compile 'com.android.support:support-annotations:22.2.0'
66+
compile 'com.android.databinding:library:1.3.1'
67+
compile 'com.android.databinding:baseLibrary:3.0.0'
6668
}

AndroidStub/src/main/java/android/content/pm/PackageParser.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ public final static class Package {
377377

378378
// Signatures that were read from the package.
379379
public Signature[] mSignatures;
380+
public SigningDetails mSigningDetails;
380381
public Certificate[][] mCertificates;
381382

382383
// For use by package manager service for quick lookup of
@@ -737,5 +738,9 @@ public PackageParserException(int error, String detailMessage, Throwable throwab
737738
}
738739

739740
}
741+
742+
public static class SigningDetails {
743+
public Signature[] signatures;
744+
}
740745

741746
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (C) 2014 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package android.databinding;
17+
import android.view.View;
18+
/**
19+
* This class will be stripped from the jar and then replaced by the annotation processor
20+
* as part of the code generation step. This class's existence is just to ensure that
21+
* compile works and no reflection is needed to access the generated class.
22+
*/
23+
class DataBinderMapper {
24+
public ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View view,
25+
int layoutId) {
26+
return null;
27+
}
28+
ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View[] view, int layoutId) {
29+
return null;
30+
}
31+
public int getLayoutId(String tag) { return 0; }
32+
public String convertBrIdToString(int id) {
33+
return null;
34+
}
35+
public static int TARGET_MIN_SDK = 0;
36+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright (C) 2015 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package android.databinding;
17+
/**
18+
* This interface is generated during compilation to contain getters for all used instance
19+
* BindingAdapters. When a BindingAdapter is an instance method, an instance of the class
20+
* implementing the method must be instantiated. This interface will be generated with a getter
21+
* for each class with the name get* where * is simple class name of the declaring BindingAdapter
22+
* class/interface. Name collisions will be resolved by adding a numeric suffix to the getter.
23+
* <p>
24+
* An instance of this class may also be passed into static or instance BindingAdapters as the
25+
* first parameter.
26+
* <p>
27+
* If you are using Dagger 2, you should extend this interface and annotate the extended interface
28+
* as a Component.
29+
*/
30+
public interface DataBindingComponent {
31+
}

CoreLibrary/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ repositories {
3131

3232
dependencies {
3333
compile fileTree(dir: 'libs', include: ['*.jar'])
34-
compile 'com.android.support:appcompat-v7:22.2.0'
3534

3635
provided project(':AndroidStub')
3736

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package android.databinding;
2+
3+
import android.support.annotation.NonNull;
4+
import android.util.Log;
5+
import android.view.View;
6+
7+
import com.didi.virtualapk.PluginManager;
8+
import com.didi.virtualapk.internal.LoadedPlugin;
9+
10+
import java.util.LinkedList;
11+
12+
/**
13+
* Replace {@link DataBindingUtil#sMapper}.
14+
* Created by qiaopu on 2018/4/11.
15+
*/
16+
public class DataBinderMapperProxy extends DataBinderMapper implements PluginManager.Callback {
17+
public static final String TAG = "DataBinderMapperProxy";
18+
19+
private final LinkedList<DataBinderMapper> mMappers;
20+
private DataBinderMapper[] mCache;
21+
22+
public DataBinderMapperProxy(@NonNull Object source) {
23+
mMappers = new LinkedList<>();
24+
25+
addMapper((DataBinderMapper) source);
26+
}
27+
28+
@Override
29+
public ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View view, int layoutId) {
30+
ViewDataBinding viewDataBinding;
31+
32+
for (DataBinderMapper mapper : getCache()) {
33+
viewDataBinding = mapper.getDataBinder(bindingComponent, view, layoutId);
34+
if (viewDataBinding != null) {
35+
// Log.d(TAG, "Found by mapper: " + mapper);
36+
return viewDataBinding;
37+
}
38+
}
39+
40+
return null;
41+
}
42+
43+
@Override
44+
ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View[] view, int layoutId) {
45+
ViewDataBinding viewDataBinding;
46+
47+
for (DataBinderMapper mapper : getCache()) {
48+
viewDataBinding = mapper.getDataBinder(bindingComponent, view, layoutId);
49+
if (viewDataBinding != null) {
50+
// Log.d(TAG, "Found by mapper: " + mapper);
51+
return viewDataBinding;
52+
}
53+
}
54+
55+
return null;
56+
}
57+
58+
@Override
59+
public int getLayoutId(String tag) {
60+
int layoutId;
61+
62+
for (DataBinderMapper mapper : getCache()) {
63+
layoutId = mapper.getLayoutId(tag);
64+
if (layoutId != 0) {
65+
// Log.d(TAG, "Found by mapper: " + mapper);
66+
return layoutId;
67+
}
68+
}
69+
70+
return 0;
71+
}
72+
73+
@Override
74+
public String convertBrIdToString(int id) {
75+
String brId;
76+
77+
for (DataBinderMapper mapper : getCache()) {
78+
brId = mapper.convertBrIdToString(id);
79+
if (brId != null) {
80+
// Log.d(TAG, "Found by mapper: " + mapper);
81+
return brId;
82+
}
83+
}
84+
85+
return null;
86+
}
87+
88+
@Override
89+
public void onAddedLoadedPlugin(LoadedPlugin plugin) {
90+
try {
91+
String clsName = "android.databinding.DataBinderMapper_" + plugin.getPackageName().replace('.', '_');
92+
Log.d(TAG, "Try to find the class: " + clsName);
93+
Class cls = Class.forName(clsName, true, plugin.getClassLoader());
94+
Object obj = cls.newInstance();
95+
96+
addMapper((DataBinderMapper) obj);
97+
98+
} catch (Exception e) {
99+
Log.w(TAG, e);
100+
}
101+
}
102+
103+
private void addMapper(DataBinderMapper mapper) {
104+
int size = 0;
105+
synchronized (mMappers) {
106+
mMappers.add(mapper);
107+
mCache = null;
108+
size = mMappers.size();
109+
}
110+
111+
Log.d(TAG, "Added mapper: " + mapper + ", size: " + size);
112+
}
113+
114+
private DataBinderMapper[] getCache() {
115+
synchronized (mMappers) {
116+
if (mCache == null) {
117+
mCache = mMappers.toArray(new DataBinderMapper[mMappers.size()]);
118+
}
119+
return mCache;
120+
}
121+
}
122+
}

CoreLibrary/src/main/java/com/didi/virtualapk/PluginManager.java

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import android.content.Intent;
2929
import android.content.pm.ProviderInfo;
3030
import android.content.pm.ResolveInfo;
31+
import android.databinding.DataBinderMapperProxy;
3132
import android.net.Uri;
3233
import android.os.Build;
3334
import android.util.Log;
@@ -65,6 +66,7 @@ public class PluginManager {
6566
private Context mContext;
6667
private ComponentsHandler mComponentsHandler;
6768
private Map<String, LoadedPlugin> mPlugins = new ConcurrentHashMap<>();
69+
private final List<Callback> mCallbacks = new ArrayList<>();
6870

6971
private Instrumentation mInstrumentation; // Hooked instrumentation
7072
private IActivityManager mActivityManager; // Hooked IActivityManager binder
@@ -94,11 +96,8 @@ private PluginManager(Context context) {
9496
private void prepare() {
9597
Systems.sHostContext = getHostContext();
9698
this.hookInstrumentationAndHandler();
97-
if (Build.VERSION.SDK_INT >= 26) {
98-
this.hookAMSForO();
99-
} else {
100-
this.hookSystemServices();
101-
}
99+
this.hookSystemServices();
100+
hookDataBindingUtil();
102101
}
103102

104103
public void init() {
@@ -113,13 +112,42 @@ public void run() {
113112

114113
private void doInWorkThread() {
115114
}
115+
116+
private void hookDataBindingUtil() {
117+
try {
118+
Class cls = Class.forName("android.databinding.DataBindingUtil");
119+
Object old = ReflectUtil.getField(cls, null, "sMapper");
120+
Callback callback = new DataBinderMapperProxy(old);
121+
ReflectUtil.setField(cls, null, "sMapper", callback);
122+
123+
addCallback(callback);
124+
125+
} catch (Exception e) {
126+
e.printStackTrace();
127+
}
128+
}
129+
130+
public void addCallback(Callback callback) {
131+
if (callback == null) {
132+
return;
133+
}
134+
synchronized (mCallbacks) {
135+
mCallbacks.add(callback);
136+
}
137+
}
116138

117139
/**
118140
* hookSystemServices, but need to compatible with Android O in future.
119141
*/
120142
private void hookSystemServices() {
121143
try {
122-
Singleton<IActivityManager> defaultSingleton = (Singleton<IActivityManager>) ReflectUtil.getField(ActivityManagerNative.class, null, "gDefault");
144+
Singleton<IActivityManager> defaultSingleton;
145+
146+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
147+
defaultSingleton = (Singleton<IActivityManager>) ReflectUtil.getField(ActivityManager.class, null, "IActivityManagerSingleton");
148+
} else {
149+
defaultSingleton = (Singleton<IActivityManager>) ReflectUtil.getField(ActivityManagerNative.class, null, "gDefault");
150+
}
123151
IActivityManager activityManagerProxy = ActivityManagerProxy.newInstance(this, defaultSingleton.get());
124152

125153
// Hook IActivityManager from ActivityManagerNative
@@ -133,17 +161,6 @@ private void hookSystemServices() {
133161
}
134162
}
135163

136-
137-
private void hookAMSForO() {
138-
try {
139-
Singleton<IActivityManager> defaultSingleton = (Singleton<IActivityManager>) ReflectUtil.getField(ActivityManager.class, null, "IActivityManagerSingleton");
140-
IActivityManager activityManagerProxy = ActivityManagerProxy.newInstance(this, defaultSingleton.get());
141-
ReflectUtil.setField(defaultSingleton.getClass().getSuperclass(), defaultSingleton, "mInstance", activityManagerProxy);
142-
} catch (Exception e) {
143-
e.printStackTrace();
144-
}
145-
}
146-
147164
private void hookInstrumentationAndHandler() {
148165
try {
149166
Instrumentation baseInstrumentation = ReflectUtil.getInstrumentation(this.mContext);
@@ -219,6 +236,11 @@ public void loadPlugin(File apk) throws Exception {
219236
LoadedPlugin plugin = LoadedPlugin.create(this, this.mContext, apk);
220237
if (null != plugin) {
221238
this.mPlugins.put(plugin.getPackageName(), plugin);
239+
synchronized (mCallbacks) {
240+
for (int i = 0; i < mCallbacks.size(); i++) {
241+
mCallbacks.get(i).onAddedLoadedPlugin(plugin);
242+
}
243+
}
222244
// try to invoke plugin's application
223245
plugin.invokeApplication();
224246
} else {
@@ -357,4 +379,7 @@ public List<ResolveInfo> queryBroadcastReceivers(Intent intent, int flags) {
357379
return resolveInfos;
358380
}
359381

382+
public interface Callback {
383+
void onAddedLoadedPlugin(LoadedPlugin plugin);
384+
}
360385
}

0 commit comments

Comments
 (0)