Skip to content

Commit

Permalink
feat/gradle_plugin (#136)
Browse files Browse the repository at this point in the history
1. use asm api from gradle ClassRewriter's api
2. fix debugger init
  • Loading branch information
cpacm authored Dec 13, 2021
1 parent 92d0ee4 commit 61bcdf4
Show file tree
Hide file tree
Showing 16 changed files with 105 additions and 37 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ jobs:
- name: Run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 27
api-level: 29
profile: Nexus 6
target: google_apis
arch: x86
# emulator-build: 7425822
script: |
adb shell logcat -c
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.gio.test.three;

import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
Expand Down Expand Up @@ -86,7 +87,7 @@ public void onViewInitFinished(boolean b) {
.setUploadExceptionEnabled(false)
.setDebugEnabled(true)
.setDataCollectionEnabled(true)
.setExcludeEvent(EventExcludeFilter.of(EventExcludeFilter.EVENT_MASK_TRIGGER))
.setExcludeEvent(EventExcludeFilter.of(EventExcludeFilter.REENGAGE))
.setIgnoreField(FieldIgnoreFilter.of(FieldIgnoreFilter.FIELD_IGNORE_ALL))
.setPreloadComponent(new OaidLibraryGioModule());
}
Expand All @@ -99,7 +100,7 @@ public void onViewInitFinished(boolean b) {
}

private boolean isMainProcess() {
ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
@SuppressLint("WrongConstant") ActivityManager am = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));
List<ActivityManager.RunningAppProcessInfo> processInfos = am.getRunningAppProcesses();

if (processInfos == null) {
Expand Down
4 changes: 3 additions & 1 deletion growingio-autotracker-gradle-plugin/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ dependencies {
testImplementation libraries.asm.asm_commons
testImplementation libraries.asm.asm_util
testImplementation libraries.asm.asm_tree
testImplementation libraries.android.gradle_plugin

compileOnly gradleApi()
implementation libraries.android.gradle_plugin
compileOnly libraries.android.gradle_plugin
//implementation "com.android.tools.build:gradle:7.0.3"
}

apply from: "${rootProject.projectDir}/gradle/publishMaven.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
public class AutotrackExtension {
private boolean mIsLogEnabled = false;
private boolean mIsDevelopment = true;
private boolean mExcludeOfficialPackages = true;
private String[] mExcludePackages;

public boolean isLogEnabled() {
Expand All @@ -44,4 +45,12 @@ public String[] getExcludePackages() {
public void setExcludePackages(String[] excludePackages) {
mExcludePackages = excludePackages;
}

public boolean isExcludeOfficialPackages() {
return mExcludeOfficialPackages;
}

public void setExcludeOfficialPackages(boolean mExcludeOfficialPackages) {
this.mExcludeOfficialPackages = mExcludeOfficialPackages;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2020 Beijing Yishu Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.growingio.sdk.plugin.autotrack.compile;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;


/**
* <p>
* just for get asm version
* @author cpacm 2021/12/6
*/
public class AutotrackClassWriter extends ClassWriter {

public AutotrackClassWriter(final ClassReader classReader, final int flags) {
super(classReader, flags);
}

public int getApi() {
return api;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void transform(Context context, Collection<TransformInput> inputs, Collec
urlList.toArray(urlArray);
URLClassLoader classLoader = new URLClassLoader(urlArray);
mOutputProvider = outputProvider;
mClassRewriter = new ClassRewriter(mLog, classLoader, mAutotrackExtension.getExcludePackages());
mClassRewriter = new ClassRewriter(mLog, classLoader, mAutotrackExtension.getExcludePackages(), mAutotrackExtension.isExcludeOfficialPackages());

if (!isIncremental) {
// 1. 非增量模式下删除上次所有的编译产物
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class ClassRewriter {
private final Log mLog;
private final ClassLoader mClassLoader;
private final String[] mUserExcludePackages;
private final boolean mExcludeOfficial;
private static final String[] EXCLUDED_PACKAGES = new String[]{
"com/growingio/android/sdk/",
"com/growingio/giokit/",
Expand All @@ -51,10 +52,21 @@ public class ClassRewriter {
"android/taobao/windvane/webview",
};

private static final String[] OFFICIAL_PACKAGES = new String[]{
"android/arch/",
"com/google/",
"javax/",
// "com/squareup/",
"io/rectivex/rxjava",
// "org/apache",
"org/jetbrains/kotlin",
};


public ClassRewriter(final Log log, ClassLoader classLoader, String[] userExcludePackages) {
public ClassRewriter(final Log log, ClassLoader classLoader, String[] userExcludePackages, boolean excludeOfficial) {
mLog = log;
mClassLoader = classLoader;
mExcludeOfficial = excludeOfficial;
if (userExcludePackages == null) {
mUserExcludePackages = new String[0];
} else {
Expand All @@ -77,6 +89,14 @@ private boolean isExcludedPackage(String packageName) {
return true;
}
}

if (!mExcludeOfficial) return false;

for (String exPackage : OFFICIAL_PACKAGES) {
if (packageName.startsWith(exPackage)) {
return true;
}
}
return false;
}

Expand Down Expand Up @@ -113,17 +133,17 @@ private byte[] visitClassBytes(byte[] bytes) {
String className = null;
try {
ClassReader classReader = new ClassReader(bytes);
ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
AutotrackClassWriter classWriter = new AutotrackClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
Context context = new Context(mLog, mClassLoader);
classReader.accept(new ContextClassVisitor(context), ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
classReader.accept(new ContextClassVisitor(classWriter.getApi(), context), ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);
className = context.getClassName();
ClassVisitor classVisitor;
if (className == null || this.isExcludedPackage(context.getClassName())) {
return null;
}
DesugaringClassVisitor desugaringClassVisitor = new DesugaringClassVisitor(
new InjectAroundClassVisitor(
new InjectSuperClassVisitor(classWriter, context),
DesugaringClassVisitor desugaringClassVisitor = new DesugaringClassVisitor(classWriter.getApi(),
new InjectAroundClassVisitor(classWriter.getApi(),
new InjectSuperClassVisitor(classWriter.getApi(), classWriter, context),
context),
context);
classVisitor = desugaringClassVisitor;
Expand All @@ -132,8 +152,8 @@ private byte[] visitClassBytes(byte[] bytes) {
// lambda 表达式需要特殊处理两次
mLog.debug(String.format("GIO: deal with lambda second time: %s", className));
ClassReader lambdaReader = new ClassReader(classWriter.toByteArray());
classWriter = new ClassWriter(lambdaReader, ClassWriter.COMPUTE_MAXS);
lambdaReader.accept(new DesugaredClassVisitor(classWriter, context, desugaringClassVisitor.getNeedInjectTargetMethods()), ClassReader.SKIP_FRAMES | ClassReader.EXPAND_FRAMES);
classWriter = new AutotrackClassWriter(lambdaReader, ClassWriter.COMPUTE_MAXS);
lambdaReader.accept(new DesugaredClassVisitor(classWriter.getApi(), classWriter, context, desugaringClassVisitor.getNeedInjectTargetMethods()), ClassReader.SKIP_FRAMES | ClassReader.EXPAND_FRAMES);
}
if (context.isClassModified()) {
return classWriter.toByteArray();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

package com.growingio.sdk.plugin.autotrack.compile;

import org.objectweb.asm.Opcodes;

public class Context {
private final Log mLog;
private final ClassLoader mClassLoader;
Expand All @@ -32,10 +30,6 @@ public Context(Log log, ClassLoader classLoader) {
mClassLoader = classLoader;
}

public int getASMVersion() {
return Opcodes.ASM6;
}

public ClassLoader getClassLoader() {
return mClassLoader;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
public class ContextClassVisitor extends ClassVisitor {
private final Context mContext;

public ContextClassVisitor(Context context) {
super(context.getASMVersion());
public ContextClassVisitor(int api, Context context) {
super(api);
mContext = context;
}

Expand All @@ -35,4 +35,5 @@ public void visit(int version, int access, String name, String sig, String super
mContext.setAbstract((access & Opcodes.ACC_ABSTRACT) != 0);
super.visit(version, access, name, sig, superName, interfaces);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public class DesugaredClassVisitor extends ClassVisitor {
private final Log mLog;
private final Set<TargetMethod> mNeedInjectTargetMethods;

public DesugaredClassVisitor(ClassVisitor cv, Context context, Set<TargetMethod> needInjectTargetMethods) {
super(context.getASMVersion(), cv);
public DesugaredClassVisitor(int api, ClassVisitor cv, Context context, Set<TargetMethod> needInjectTargetMethods) {
super(api, cv);
mContext = context;
mLog = context.getLog();
mNeedInjectTargetMethods = needInjectTargetMethods;
Expand All @@ -44,7 +44,7 @@ public DesugaredClassVisitor(ClassVisitor cv, Context context, Set<TargetMethod>
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
return new DesugaredMethodVisitor(mContext.getASMVersion(), methodVisitor, access, name, desc);
return new DesugaredMethodVisitor(api, methodVisitor, access, name, desc);
}

private TargetMethod findTargetMethod(String name, String desc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ public class DesugaringClassVisitor extends ClassVisitor {
private final HashMap<String, GenerateMethodBlock> mGenerateMethodBlocks = new HashMap<>();
private int mGenerateMethodIndex = 0;

public DesugaringClassVisitor(ClassVisitor cv, Context context) {
super(context.getASMVersion(), cv);
public DesugaringClassVisitor(int api, ClassVisitor cv, Context context) {
super(api, cv);
mContext = context;
mLog = context.getLog();
}

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor methodVisitor = super.visitMethod(access, name, desc, signature, exceptions);
return new DesugaringMethodVisitor(mContext.getASMVersion(), methodVisitor, access, name, desc);
return new DesugaringMethodVisitor(api, methodVisitor, access, name, desc);
}

@Override
Expand Down Expand Up @@ -148,6 +148,7 @@ private DesugaringMethodVisitor(int api, MethodVisitor mv, int access, String na

@Override
public void visitInvokeDynamicInsn(String lambdaMethodName, String desc, Handle bsm, Object... bsmArgs) {
mLog.debug(String.format("DesugaringMethodVisitor(%s): on method %s", mContext.getClassName(), mName));
int index = desc.lastIndexOf(")L");
if (index == -1) {
super.visitInvokeDynamicInsn(lambdaMethodName, desc, bsm, bsmArgs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ public class InjectAroundClassVisitor extends ClassVisitor {
private final Log mLog;
private String mCurrentClass;

public InjectAroundClassVisitor(ClassVisitor classVisitor, Context context) {
super(context.getASMVersion(), classVisitor);
public InjectAroundClassVisitor(int api, ClassVisitor classVisitor, Context context) {
super(api, classVisitor);
mContext = context;
mLog = mContext.getLog();
}
Expand All @@ -52,13 +52,13 @@ public void visit(int version, int access, String name, String signature, String
@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
return new AroundMethodVisitor(mv, access, name, desc);
return new AroundMethodVisitor(api, mv, access, name, desc);
}

private final class AroundMethodVisitor extends GeneratorAdapter {

AroundMethodVisitor(MethodVisitor mv, int access, String name, String desc) {
super(mContext.getASMVersion(), mv, access, name, desc);
AroundMethodVisitor(int api, MethodVisitor mv, int access, String name, String desc) {
super(api, mv, access, name, desc);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public class InjectSuperClassVisitor extends ClassVisitor {
private final Set<TargetMethod> mOverrideMethods = new HashSet<>();
private String mCurrentClass;

public InjectSuperClassVisitor(ClassVisitor classVisitor, Context context) {
super(context.getASMVersion(), classVisitor);
public InjectSuperClassVisitor(int api, ClassVisitor classVisitor, Context context) {
super(api, classVisitor);
mContext = context;
mLog = context.getLog();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.common.truth.Truth;
import com.growingio.sdk.plugin.autotrack.ByteCodeClassLoader;
import com.growingio.sdk.plugin.autotrack.ClassUtils;
import com.growingio.sdk.plugin.autotrack.compile.AutotrackClassWriter;
import com.growingio.sdk.plugin.autotrack.compile.Context;
import com.growingio.sdk.plugin.autotrack.compile.SystemLog;
import com.growingio.sdk.plugin.autotrack.hook.HookClassesConfig;
Expand Down Expand Up @@ -71,9 +72,9 @@ public void injectSuperBefore() throws IOException, IllegalAccessException, Inst

InputStream resourceAsStream = ClassUtils.classToInputStream(SubExample.class);
ClassReader cr = new ClassReader(resourceAsStream);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
AutotrackClassWriter cw = new AutotrackClassWriter(cr, ClassWriter.COMPUTE_MAXS);
Context context = new Context(new SystemLog(), getClass().getClassLoader());
cr.accept(new InjectSuperClassVisitor(cw, context), ClassReader.SKIP_FRAMES | ClassReader.EXPAND_FRAMES);
cr.accept(new InjectSuperClassVisitor(cw.getApi(), cw, context), ClassReader.SKIP_FRAMES | ClassReader.EXPAND_FRAMES);
Class<?> aClass = new ByteCodeClassLoader(getClass().getClassLoader()).defineClass(SubExample.class.getName(), cw.toByteArray());
Object obj = aClass.newInstance();
final SuperExample[] callbackResult = new SuperExample[1];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public Factory() {

@Override
public ModelLoader<Debugger, WebService> build() {
DebuggerEventWrapper.get().observeEventBuild();
return new DebuggerDataLoader(getsInternalClient());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,5 @@ public class DebuggerLibraryGioModule extends LibraryGioModule {
@Override
public void registerComponents(Context context, TrackerRegistry registry) {
registry.register(Debugger.class, WebService.class, new DebuggerDataLoader.Factory());
DebuggerEventWrapper.get().observeEventBuild();
}
}

0 comments on commit 61bcdf4

Please sign in to comment.