Skip to content

Commit

Permalink
完成对okhttp的监控
Browse files Browse the repository at this point in the history
  • Loading branch information
crosswall committed Jul 26, 2021
1 parent b08ad57 commit c2801a2
Show file tree
Hide file tree
Showing 37 changed files with 395 additions and 23 deletions.
6 changes: 4 additions & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
45 changes: 45 additions & 0 deletions ASMInject/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
plugins {
id 'com.android.library'
id 'kotlin-android'
}

android {
compileSdkVersion 30
buildToolsVersion "30.0.2"

defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.1.0'
implementation("com.squareup.okhttp3:okhttp:4.9.1")
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.github.crosswall.inject

import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4

import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Assert.*

/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.github.crosswall.inject.test", appContext.packageName)
}
}
5 changes: 5 additions & 0 deletions ASMInject/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.github.crosswall.inject">

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.github.crosswall.inject;

import com.github.crosswall.inject.http.TimingOKEventListener;

import java.util.ArrayList;
import java.util.List;

import okhttp3.Dns;
import okhttp3.EventListener;
import okhttp3.Interceptor;

public class OkHttpHooker {
public static EventListener.Factory globalEventFactory = TimingOKEventListener.FACTORY;

// new EventListener.Factory() {
// public EventListener create(Call call) {
// return EventListener.NONE;
// }
// };

public static Dns globalDns = Dns.SYSTEM;

public static List<Interceptor> globalInterceptors = new ArrayList<>();

public static List<Interceptor> globalNetworkInterceptors = new ArrayList<>();

public static void installEventListenerFactory(EventListener.Factory factory) {
globalEventFactory = factory;
}

public static void installDns(Dns dns) {
globalDns = dns;
}

public static void installInterceptor(Interceptor interceptor) {
if(interceptor != null)
globalInterceptors.add(interceptor);
}

public static void installNetworkInterceptors(Interceptor networkInterceptor) {
if(networkInterceptor != null)
globalNetworkInterceptors.add(networkInterceptor);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.github.crosswall.inject;

import android.os.SystemClock;
import android.util.Log;

import java.util.HashMap;
import java.util.Map;

public class TimingTrace {

private static final String TAG = "TimingTrace";

private static Map<String,Long> startMap = new HashMap<>();

public static void start(String name){
startMap.put(name, SystemClock.elapsedRealtimeNanos());
}

public static void end(String name){
long cost = SystemClock.elapsedRealtimeNanos() - startMap.get(name);
Log.d(TAG,"测试方法耗时====>>> " + name + " ---- " + cost / 1000000.f + "ms");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.github.crosswall.inject.http;

import android.os.SystemClock;
import android.util.Log;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.concurrent.atomic.AtomicLong;

import okhttp3.Call;
import okhttp3.EventListener;

public class TimingOKEventListener extends EventListener{

private static final String TAG = "TimingTrace";

public static final EventListener.Factory FACTORY = new EventListener.Factory() {

AtomicLong nextCallId = new AtomicLong(1L);

@Override
public EventListener create(Call call) {
long callId = nextCallId.getAndIncrement();
return new TimingOKEventListener(callId);
}

};

private long callId;
private long callStartNanos = 0L;
private boolean isNewConnection = false;

public TimingOKEventListener(long callId) {
this.callId = callId;
}

@Override
public void callStart(Call call) {
callStartNanos = SystemClock.elapsedRealtimeNanos();
}

@Override
public void connectStart(Call call, InetSocketAddress inetSocketAddress, Proxy proxy) {
isNewConnection = true;
}

@Override
public void callEnd(Call call) {
printResult(true, call);
}

@Override
public void callFailed(Call call, IOException ioe) {
printResult(false, call);
}

private void printResult(boolean success, Call call) {
float elapsed = (SystemClock.elapsedRealtimeNanos() - callStartNanos) / 1000000.f;
String from = isNewConnection ? "newest connection" : "pooled connection";
String url = call.request().url().toString();
String result = String.format("%04d %s Call From %s costs %.3f ms, url %s", callId, success ? "Success" : "Fail", from, elapsed, url);
Log.i(TAG, "测试请求耗时====>>>" + result);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.github.crosswall.inject

import org.junit.Test

import org.junit.Assert.*

/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
1 change: 1 addition & 0 deletions Plugin/ASMHookerPlugin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ dependencies {
implementation localGroovy()
implementation 'com.android.tools.build:gradle:3.1.0'
implementation 'commons-io:commons-io:2.6'

implementation 'org.ow2.asm:asm:7.1'
implementation 'org.ow2.asm:asm-util:7.1'
implementation 'org.ow2.asm:asm-commons:7.1'

// implementation 'org.javassist:javassist:3.27.0-GA'
// kapt "com.google.auto.service:auto-service:1.0-rc6"
// implementation 'com.google.auto.service:auto-service:1.0-rc6'
Expand Down
Empty file.
21 changes: 21 additions & 0 deletions Plugin/ASMHookerPlugin/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.github.crosswall.plugin

import com.android.build.api.transform.*
import com.android.build.gradle.internal.pipeline.TransformManager
import com.github.crosswall.plugin.core.OkHttpClassVisitor
import com.github.crosswall.plugin.core.TimeClassVisitor
import com.github.crosswall.plugin.option.HookerOption
import org.apache.commons.io.FileUtils
Expand All @@ -21,7 +22,7 @@ import java.util.jar.JarOutputStream
class ASMTransformer(private val project: Project, private val option: HookerOption) :
Transform() {

override fun getName(): String = "time-class-transform"
override fun getName(): String = "asm-hooker-transform"

override fun getInputTypes(): MutableSet<QualifiedContent.ContentType> =
TransformManager.CONTENT_CLASS
Expand Down Expand Up @@ -71,10 +72,13 @@ class ASMTransformer(private val project: Project, private val option: HookerOpt
//字节码插桩
val clzReader = ClassReader(f.readBytes())
val clzWriter = ClassWriter(clzReader, ClassWriter.COMPUTE_MAXS)
val cv = TimeClassVisitor(Opcodes.ASM5, clzWriter, option)

val cv = if (f.name.contains("okhttp3"))
OkHttpClassVisitor(Opcodes.ASM6, clzWriter) else TimeClassVisitor(Opcodes.ASM6, clzWriter, option)
clzReader.accept(cv, ClassReader.EXPAND_FRAMES)
val byteArray = clzWriter.toByteArray()
val fos = FileOutputStream(f.parentFile.absolutePath + File.separator + f.name)
val fos =
FileOutputStream(f.parentFile.absolutePath + File.separator + f.name)
fos.write(byteArray)
fos.close()
}
Expand Down Expand Up @@ -120,7 +124,8 @@ class ASMTransformer(private val project: Project, private val option: HookerOpt
//字节码插桩
val clzReader = ClassReader(IOUtils.toByteArray(inputStream))
val clzWriter = ClassWriter(clzReader, ClassWriter.COMPUTE_MAXS)
val cv = TimeClassVisitor(Opcodes.ASM5, clzWriter, option)
val cv = if (entryName.contains("okhttp3"))
OkHttpClassVisitor(Opcodes.ASM6, clzWriter) else TimeClassVisitor(Opcodes.ASM6, clzWriter, option)
clzReader.accept(cv, ClassReader.EXPAND_FRAMES)
val byteArray = clzWriter.toByteArray()
jarOutputStream.write(byteArray)
Expand Down
Loading

0 comments on commit c2801a2

Please sign in to comment.