33 |
34 |
35 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
86 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/android/bluetooth/IBluetooth.java:
--------------------------------------------------------------------------------
1 | package android.bluetooth;
2 |
3 | public interface IBluetooth extends android.os.IInterface {
4 | /**
5 | * Local-side IPC implementation stub class.
6 | */
7 | public static abstract class Stub extends android.os.Binder implements IBluetooth {
8 | private static final String DESCRIPTOR = "android.bluetooth.IBluetooth";
9 |
10 | /**
11 | * Construct the stub at attach it to the interface.
12 | */
13 | public Stub() {
14 | this.attachInterface(this, DESCRIPTOR);
15 | }
16 |
17 | /**
18 | * Cast an IBinder object into an android.bluetooth.IBluetooth interface,
19 | * generating a proxy if needed.
20 | */
21 | public static IBluetooth asInterface(android.os.IBinder obj) {
22 | if ((obj == null)) {
23 | return null;
24 | }
25 | android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
26 | if (((iin != null) && (iin instanceof IBluetooth))) {
27 | return ((IBluetooth) iin);
28 | }
29 | return new Proxy(obj);
30 | }
31 |
32 | @Override
33 | public android.os.IBinder asBinder() {
34 | return this;
35 | }
36 |
37 | @Override
38 | public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
39 | String descriptor = DESCRIPTOR;
40 | switch (code) {
41 | case INTERFACE_TRANSACTION: {
42 | reply.writeString(descriptor);
43 | return true;
44 | }
45 | default: {
46 | return super.onTransact(code, data, reply, flags);
47 | }
48 | }
49 | }
50 |
51 | private static class Proxy implements IBluetooth {
52 | private android.os.IBinder mRemote;
53 |
54 | Proxy(android.os.IBinder remote) {
55 | mRemote = remote;
56 | }
57 |
58 | @Override
59 | public android.os.IBinder asBinder() {
60 | return mRemote;
61 | }
62 |
63 | public String getInterfaceDescriptor() {
64 | return DESCRIPTOR;
65 | }
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/BluetoothBinderHook.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import android.os.IBinder;
4 | import android.os.IInterface;
5 | import android.util.Log;
6 |
7 | import java.lang.reflect.InvocationHandler;
8 | import java.lang.reflect.Method;
9 | import java.lang.reflect.Proxy;
10 |
11 | /**
12 | * author: okbean
13 | * date: On 2020/10/01
14 | * email: okbean020@163.com
15 | * description: 该类主要用来拦截IBluetoothManager里的queryLocalInterface函数,
16 | * 把返回结果替换成android.bluetooth.IBluetoothManager$Stub的代理类(使用动态代理方式)
17 | */
18 | public final class BluetoothBinderHook implements InvocationHandler {
19 |
20 | private final static String TAG = BluetoothBinderHook.class.getSimpleName();
21 |
22 | private final IBinder mTarget;
23 |
24 | public BluetoothBinderHook(final IBinder target){
25 | this.mTarget = target;
26 | }
27 |
28 | @Override
29 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
30 | final String methodName = method.getName();
31 | Log.i(TAG, "invoke method:" + methodName);
32 | if ("queryLocalInterface".equals(method.getName())) {
33 | final Object obj = hookQueryLocalInterface();
34 | if(obj != null){
35 | return obj;
36 | }
37 | }
38 | return method.invoke(mTarget, args);
39 | }
40 |
41 | private Object hookQueryLocalInterface() {
42 | Object val = null;
43 | try{
44 | final String className = "android.bluetooth.IBluetoothManager";
45 | final Class> clazz = ReflectUtils.getClass(className);
46 | final Object obj = ReflectUtils.invokeMethod(
47 | null,
48 | "android.bluetooth.IBluetoothManager$Stub",
49 | "asInterface",
50 | new Class>[]{IBinder.class},
51 | new Object[]{mTarget} );
52 | final Class>[] interfaces = new Class>[]{IBinder.class, IInterface.class, clazz};
53 | final ClassLoader loader = mTarget.getClass().getClassLoader();
54 | final InvocationHandler handler = new BluetoothManagerServiceHook(obj);
55 | val = Proxy.newProxyInstance(loader,interfaces, handler);
56 | }catch (Exception e){
57 | e.printStackTrace();
58 | }
59 | return val;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/BluetoothManagerCallbackHook.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import android.bluetooth.IBluetooth;
4 | import android.bluetooth.IBluetoothManagerCallback;
5 | import android.os.IBinder;
6 | import android.os.IInterface;
7 | import android.os.RemoteException;
8 | import android.util.Log;
9 |
10 | import java.lang.reflect.InvocationHandler;
11 | import java.lang.reflect.Proxy;
12 |
13 | /**
14 | * author: okbean
15 | * date: On 2020/10/01
16 | * email: okbean020@163.com
17 | * description:BluetoothManagerCallback服务代理类
18 | */
19 | public class BluetoothManagerCallbackHook extends IBluetoothManagerCallback.Stub{
20 |
21 | public final static String TAG = BluetoothManagerCallbackHook.class.getSimpleName();
22 |
23 | private final IBluetoothManagerCallback mDelegate;
24 |
25 | public BluetoothManagerCallbackHook(final IBluetoothManagerCallback delegate){
26 | this.mDelegate = delegate;
27 | }
28 |
29 |
30 | @Override
31 | public void onBluetoothServiceUp(IBluetooth bluetoothService) throws RemoteException {
32 | final String msg = "onBluetoothServiceUp";
33 | Log.d(TAG, msg);
34 | final Object newObj = hookBluetoothService(bluetoothService);
35 | if(newObj != null && newObj instanceof IBluetooth){
36 | mDelegate.onBluetoothServiceUp((IBluetooth)newObj);
37 | return;
38 | }
39 | mDelegate.onBluetoothServiceUp(bluetoothService);
40 | }
41 |
42 |
43 | @Override
44 | public void onBluetoothServiceDown() throws RemoteException {
45 | final String msg = "onBluetoothServiceDown";
46 | Log.d(TAG, msg);
47 | mDelegate.onBluetoothServiceDown();
48 | }
49 |
50 |
51 | @Override
52 | public void onBrEdrDown() throws RemoteException {
53 | final String msg = "onBrEdrDown";
54 | Log.d(TAG, msg);
55 | mDelegate.onBrEdrDown();
56 | }
57 |
58 |
59 | private static Object hookBluetoothService(Object obj){
60 | Object val = null;
61 | try{
62 | final String className = "android.bluetooth.IBluetooth";
63 | final Class> clazz = ReflectUtils.getClass(className);
64 | final Class>[] interfaces = new Class>[]{IBinder.class, IInterface.class, clazz};
65 | final ClassLoader loader = clazz.getClassLoader();
66 | final InvocationHandler handler = new BluetoothServiceHook(obj);
67 | val = Proxy.newProxyInstance(loader,interfaces, handler);
68 | }catch (Exception e){
69 | e.printStackTrace();
70 | }
71 | return val;
72 | }
73 |
74 |
75 | }
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/ReflectUtils.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.InvocationTargetException;
5 | import java.lang.reflect.Method;
6 |
7 | /**
8 | * author: okbean
9 | * date: On 2020/10/01
10 | * email: okbean020@163.com
11 | * description:反射操作工具类
12 | */
13 | public final class ReflectUtils {
14 |
15 | public static Class> getClass(final String className) throws ClassNotFoundException {
16 | final Class> val = Class.forName(className);
17 | return val;
18 | }
19 |
20 | public static Object getFieldValue(final Object obj,final String className, final String fieldName) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
21 | final Class> clazz = getClass(className);
22 | final Field field = clazz.getDeclaredField(fieldName);
23 | field.setAccessible(true);
24 | final Object val = field.get(obj);
25 | return val;
26 | }
27 |
28 | public static Field getField(final Class> clazz, final String fieldName) throws NoSuchFieldException {
29 | final Field val = clazz.getDeclaredField(fieldName);
30 | return val;
31 | }
32 |
33 |
34 | public static Field getField(final String className, final String fieldName) throws NoSuchFieldException, ClassNotFoundException {
35 | final Class> clazz = getClass(className);
36 | final Field val = getField(clazz, fieldName);
37 | return val;
38 | }
39 |
40 |
41 | public static Method getMethod(final Class> clazz, final String methodName, final Class>... parameterTypes) throws NoSuchMethodException {
42 | final Method val = clazz.getDeclaredMethod(methodName,parameterTypes);
43 | return val;
44 | }
45 |
46 |
47 |
48 | public static Method getMethod(final String className, final String methodName, final Class>... parameterTypes) throws NoSuchMethodException, ClassNotFoundException {
49 | final Class> clazz = getClass(className);
50 | final Method val = getMethod(clazz, methodName, parameterTypes);
51 | return val;
52 | }
53 |
54 |
55 |
56 | public static Object invokeMethod(final Object obj, final String className,final String methodName, final Class>[] parameterTypes, final Object... args) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
57 | final Method method = getMethod(className, methodName, parameterTypes);
58 | final Object val = method.invoke(obj, args);
59 | return val;
60 | }
61 |
62 |
63 | private ReflectUtils(){}
64 | }
65 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/Hex.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | /**
4 | * author: okbean
5 | * date: On 2020/10/01
6 | * email: okbean020@163.com
7 | * description:
8 | */
9 | public final class Hex {
10 |
11 | public static String toString(final byte[] data) {
12 | if(data == null){
13 | return null;
14 | }
15 | return new String(encodeHex(data));
16 | }
17 |
18 | public static String toString(final byte[] data, final char delimiter) {
19 | if(data == null){
20 | return null;
21 | }
22 | final char[] chars = encodeHex(data);
23 | final int len = chars.length;
24 | final StringBuilder sb = new StringBuilder(len * 2 - 1);
25 |
26 | for(int i=0; i>> 4];
64 | out[j++] = toDigits[0x0F & data[i]];
65 | }
66 | return out;
67 | }
68 |
69 | protected static char[] encodeHex(final byte[] data, final int offset, final int length, final char[] toDigits) {
70 | final int l = data.length;
71 | final char[] out = new char[length << 1];
72 | for (int i = offset, j = 0; i < length; i++) {
73 | out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
74 | out[j++] = toDigits[0x0F & data[i]];
75 | }
76 | return out;
77 | }
78 |
79 | private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
80 |
81 | private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
82 |
83 | private Hex(){}
84 | }
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/BluetoothGattServiceHook.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import android.bluetooth.IBluetoothGattCallback;
4 | import android.os.Build;
5 | import android.util.Log;
6 |
7 | import java.lang.reflect.InvocationHandler;
8 | import java.lang.reflect.Method;
9 |
10 | import static okble.bluetooth_hook.OkBluetoothHook.supportHiddenApi;
11 |
12 | /**
13 | * author: okbean
14 | * date: On 2020/10/01
15 | * email: okbean020@163.com
16 | * description:IBluetoothGatt服务代理类,拦截BluetoothGatt的一些操作,比如读写特征值,读写描述符,设置MTU等
17 | */
18 | public final class BluetoothGattServiceHook implements InvocationHandler {
19 |
20 | private final static String TAG = BluetoothGattServiceHook.class.getSimpleName();
21 |
22 | private final Object mTarget;
23 | public BluetoothGattServiceHook(final Object target){
24 | this.mTarget = target;
25 | }
26 |
27 | @Override
28 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
29 | final String methodName = method.getName();
30 | Log.i(TAG, "invoke method:" + methodName);
31 | if("registerClient".equals(method.getName())){
32 | if(Build.VERSION.SDK_INT < 28 || supportHiddenApi()){
33 | final Object obj = args[1];
34 | final Object newObj = hookRegisterClient(obj);
35 | if(newObj != null){
36 | final Object[] newArgs = new Object[2];
37 | newArgs[0] = args[0];
38 | newArgs[1] = newObj;
39 | return method.invoke(mTarget, newArgs);
40 | }
41 | }
42 | }else if("writeDescriptor".equals(method.getName())){
43 | for(Object obj : args){
44 | if(obj instanceof byte[]){
45 | Log.i(TAG, "writeDescriptor data:(0x)" + Hex.toString((byte[])obj, '-'));
46 | break;
47 | }
48 | }
49 | }else if("writeCharacteristic".equals(method.getName())){
50 | for(Object obj : args){
51 | if(obj instanceof byte[]){
52 | Log.i(TAG, "writeCharacteristic data:(0x)" + Hex.toString((byte[])obj, '-'));
53 | break;
54 | }
55 | }
56 | }
57 | return method.invoke(mTarget, args);
58 | }
59 |
60 |
61 |
62 | private Object hookRegisterClient(Object obj){
63 | Object val = null;
64 | try{
65 | if(obj != null && obj instanceof IBluetoothGattCallback.Stub){
66 | val = new BluetoothGattCallbackHook((IBluetoothGattCallback)(obj));
67 | }
68 | }catch (Exception e){
69 | e.printStackTrace();
70 | }
71 | return val;
72 | }
73 |
74 |
75 |
76 | // private Object hookRegisterClient(Object bluetoothGattCallbackObj){
77 | // Object val = null;
78 | // try{
79 | // final String clazzName = "android.bluetooth.IBluetoothGattCallback";
80 | // final Class> clazz = ReflectUtils.getClass(clazzName);
81 | // final Class>[] interfaces = new Class>[]{IBinder.class, IInterface.class, clazz};
82 | // final ClassLoader loader = mTarget.getClass().getClassLoader();
83 | // final InvocationHandler handler = new BluetoothGattCallbackHookOld(bluetoothGattCallbackObj);
84 | // val = Proxy.newProxyInstance(loader,interfaces, handler);
85 | // }catch (Exception e){
86 | // e.printStackTrace();
87 | // }
88 | // return val;
89 | // }
90 |
91 |
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/.idea/codeStyles/Project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | xmlns:android
14 |
15 | ^$
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | xmlns:.*
25 |
26 | ^$
27 |
28 |
29 | BY_NAME
30 |
31 |
32 |
33 |
34 |
35 |
36 | .*:id
37 |
38 | http://schemas.android.com/apk/res/android
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | .*:name
48 |
49 | http://schemas.android.com/apk/res/android
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | name
59 |
60 | ^$
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | style
70 |
71 | ^$
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | .*
81 |
82 | ^$
83 |
84 |
85 | BY_NAME
86 |
87 |
88 |
89 |
90 |
91 |
92 | .*
93 |
94 | http://schemas.android.com/apk/res/android
95 |
96 |
97 | ANDROID_ATTRIBUTE_ORDER
98 |
99 |
100 |
101 |
102 |
103 |
104 | .*
105 |
106 | .*
107 |
108 |
109 | BY_NAME
110 |
111 |
112 |
113 |
114 |
115 |
116 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/OkBluetoothHook.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import android.app.Application;
4 | import android.os.Build;
5 | import android.os.IBinder;
6 |
7 | import java.lang.reflect.Method;
8 | import java.lang.reflect.Proxy;
9 | import java.util.Map;
10 |
11 |
12 | /**
13 | * author: okbean
14 | * date: On 2020/10/01
15 | * email: okbean020@163.com
16 | * description: 该类主要提供模块注册入口,以及通过反射调用把系统缓存的
17 | * IBluetoothManager服务替换成IBluetoothManager服务代理(使用动态代理方式)。
18 | * 注册后可以无侵入原代码的方式来观察APP的所有关于蓝牙操作(目前主要是BLE),比如发送数据和接收数据
19 | */
20 | public final class OkBluetoothHook {
21 |
22 | private static boolean sInjected = false;
23 |
24 | public static boolean inject(final Application app){
25 | if(!sInjected){
26 | sInjected = inject0();
27 | }
28 |
29 | if(!sSupportHiddenApi && Build.VERSION.SDK_INT >= 28){
30 | sSupportHiddenApi = makeSupportHiddenApi();
31 | }
32 | return sInjected;
33 | }
34 |
35 |
36 | public static boolean isInjected(){
37 | return sInjected;
38 | }
39 |
40 | private static boolean inject0(){
41 | try{
42 | final IBinder binder = getService();
43 | final Map cache = getServiceCache();
44 | final IBinder proxy = (IBinder) Proxy.newProxyInstance(binder.getClass().getClassLoader(),
45 | new Class>[]{IBinder.class},
46 | new BluetoothBinderHook(binder));
47 | //替换cache里的IBluetoothManager服务
48 | cache.put("bluetooth_manager", proxy);
49 | return true;
50 | }catch (Exception e){
51 | e.printStackTrace();
52 | }
53 | return false;
54 | }
55 |
56 |
57 |
58 | private static boolean sSupportHiddenApi = false;
59 | public static boolean supportHiddenApi(){
60 | return sSupportHiddenApi;
61 | }
62 |
63 |
64 | /**
65 | * SDK VERSION 大于28时需要通过反射调用让系统允许调用某些隐藏的(hide)API
66 | * @return
67 | */
68 | private static boolean makeSupportHiddenApi(){
69 | try {
70 | final Method forNameMethod = Class.class.getDeclaredMethod("forName", String.class);
71 | final Method getDeclaredMethodMethod = Class.class.getDeclaredMethod("getDeclaredMethod", String.class, Class[].class);
72 | final Class> vmRuntimeClass = (Class>) forNameMethod.invoke(null, "dalvik.system.VMRuntime");
73 | final Method getRuntimeMethod = (Method) getDeclaredMethodMethod.invoke(vmRuntimeClass, "getRuntime", null);
74 | final Method setHiddenApiExemptionsMethod = (Method) getDeclaredMethodMethod.invoke(vmRuntimeClass, "setHiddenApiExemptions", new Class[]{String[].class});
75 | final Object vmRuntimeObj = getRuntimeMethod.invoke(null);
76 | setHiddenApiExemptionsMethod.invoke(vmRuntimeObj, new Object[]{new String[]{"L"}});
77 | return true;
78 | } catch (Exception e) {
79 | e.printStackTrace();
80 | }
81 | return false;
82 | }
83 |
84 |
85 | private static Map getServiceCache(){
86 | Map val = null;
87 | try {
88 | final Object obj = ReflectUtils.getFieldValue(null,
89 | "android.os.ServiceManager",
90 | "sCache");
91 | if(obj != null){
92 | if(!(obj instanceof Map)){
93 | throw new IllegalStateException("sCache not a instance of Map!");
94 | }
95 | val = (Map)obj ;
96 | }
97 | } catch (Exception e) {
98 | e.printStackTrace();
99 | }
100 | return val;
101 | }
102 |
103 |
104 | private static IBinder getService(){
105 | IBinder val = null;
106 | try {
107 | final Object obj = ReflectUtils.invokeMethod(null,
108 | "android.os.ServiceManager",
109 | "getService",
110 | new Class>[]{String.class},
111 | new Object[]{"bluetooth_manager"} );
112 | val = (IBinder) obj;
113 | } catch (Exception e) {
114 | e.printStackTrace();
115 | }
116 | return val;
117 | }
118 |
119 | private OkBluetoothHook(){throw new IllegalStateException();}
120 | }
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/BluetoothManagerServiceHook.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import android.bluetooth.IBluetoothManagerCallback;
4 | import android.os.Build;
5 | import android.os.IBinder;
6 | import android.os.IInterface;
7 | import android.util.Log;
8 |
9 | import java.lang.reflect.InvocationHandler;
10 | import java.lang.reflect.Method;
11 | import java.lang.reflect.Proxy;
12 |
13 | import static okble.bluetooth_hook.OkBluetoothHook.supportHiddenApi;
14 |
15 | /**
16 | * author: okbean
17 | * date: On 2020/10/01
18 | * email: okbean020@163.com
19 | * description:android.bluetooth.IBluetoothManager$Stub 代理类,
20 | * 拦截getBluetoothGatt方法,返回IBluetoothGatt服务的代理类(动态代理),
21 | * 拦截registerAdapter方法,返回IBluetooth服务的代理类(动态代理),以及在拦截registerAdapter方法的
22 | * 同时,拦截BluetoothManagerCallback服务(静态代理)
23 | */
24 | public final class BluetoothManagerServiceHook implements InvocationHandler {
25 |
26 | private final static String TAG = BluetoothManagerServiceHook.class.getSimpleName();
27 |
28 | private final Object mTarget;
29 | public BluetoothManagerServiceHook(final Object target){
30 | this.mTarget = target;
31 | }
32 |
33 |
34 | @Override
35 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
36 | final String methodName = method.getName();
37 | Log.i(TAG, "invoke method:" + methodName);
38 | if ("getBluetoothGatt".equals(methodName)) {
39 | final Object obj = method.invoke(mTarget, args);
40 | final Object newObj = hookGetBluetoothGatt(obj);
41 | if(newObj != null){
42 | return newObj;
43 | }else{
44 | return obj;
45 | }
46 | }else if("registerAdapter".equals(methodName)){
47 | Object[] newArgs = args;
48 | if(Build.VERSION.SDK_INT < 28 || supportHiddenApi()){
49 | final Object argObj = args != null && args.length == 1 ? args[0] : null;
50 | final Object newArgObj = hookBluetoothManagerCallback(argObj);
51 | if(newArgObj != null){
52 | newArgs = new Object[1];
53 | newArgs[0] = newArgObj;
54 | }
55 | }
56 | final Object obj = method.invoke(mTarget, newArgs);
57 | final Object newObj = hookRegisterAdapter(obj);
58 | if(newObj != null){
59 | return newObj;
60 | }else{
61 | return obj;
62 | }
63 | }
64 | return method.invoke(mTarget, args);
65 | }
66 |
67 |
68 | private Object hookBluetoothManagerCallback(final Object obj){
69 | Object val = null;
70 | try{
71 | if(obj != null && obj instanceof IBluetoothManagerCallback.Stub){
72 | val = new BluetoothManagerCallbackHook((IBluetoothManagerCallback)(obj));
73 | }
74 | }catch (Exception e){
75 | e.printStackTrace();
76 | }
77 | return val;
78 | }
79 |
80 |
81 | private Object hookRegisterAdapter(Object obj){
82 | Object val = null;
83 | try{
84 | final String className = "android.bluetooth.IBluetooth";
85 | final Class> clazz = ReflectUtils.getClass(className);
86 | final Class>[] interfaces = new Class>[]{IBinder.class, IInterface.class, clazz};
87 | final ClassLoader loader = mTarget.getClass().getClassLoader();
88 | final InvocationHandler handler = new BluetoothServiceHook(obj);
89 | val = Proxy.newProxyInstance(loader,interfaces, handler);
90 | }catch (Exception e){
91 | e.printStackTrace();
92 | }
93 | return val;
94 | }
95 |
96 |
97 | private Object hookGetBluetoothGatt(Object obj){
98 | Object val = null;
99 | try{
100 | final String className = "android.bluetooth.IBluetoothGatt";
101 | final Class> clazz = ReflectUtils.getClass(className);
102 | final Class>[] interfaces = new Class>[]{IBinder.class, IInterface.class, clazz};
103 | final ClassLoader loader = mTarget.getClass().getClassLoader();
104 | final InvocationHandler handler = new BluetoothGattServiceHook(obj);
105 | val = Proxy.newProxyInstance(loader,interfaces, handler);
106 | }catch (Exception e){
107 | e.printStackTrace();
108 | }
109 | return val;
110 | }
111 |
112 | }
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/android/bluetooth/IBluetoothManagerCallback.java:
--------------------------------------------------------------------------------
1 | package android.bluetooth;
2 | public interface IBluetoothManagerCallback extends android.os.IInterface
3 | {
4 | /** Local-side IPC implementation stub class. */
5 | public static abstract class Stub extends android.os.Binder implements IBluetoothManagerCallback
6 | {
7 | private static final String DESCRIPTOR = "android.bluetooth.IBluetoothManagerCallback";
8 | /** Construct the stub at attach it to the interface. */
9 | public Stub()
10 | {
11 | this.attachInterface(this, DESCRIPTOR);
12 | }
13 | /**
14 | * Cast an IBinder object into an android.bluetooth.IBluetoothManagerCallback interface,
15 | * generating a proxy if needed.
16 | */
17 | public static IBluetoothManagerCallback asInterface(android.os.IBinder obj)
18 | {
19 | if ((obj==null)) {
20 | return null;
21 | }
22 | android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
23 | if (((iin!=null)&&(iin instanceof IBluetoothManagerCallback))) {
24 | return ((IBluetoothManagerCallback)iin);
25 | }
26 | return new Proxy(obj);
27 | }
28 | @Override public android.os.IBinder asBinder()
29 | {
30 | return this;
31 | }
32 | @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
33 | {
34 | String descriptor = DESCRIPTOR;
35 | switch (code)
36 | {
37 | case INTERFACE_TRANSACTION:
38 | {
39 | reply.writeString(descriptor);
40 | return true;
41 | }
42 | case TRANSACTION_onBluetoothServiceUp:
43 | {
44 | data.enforceInterface(descriptor);
45 | IBluetooth _arg0;
46 | _arg0 = IBluetooth.Stub.asInterface(data.readStrongBinder());
47 | this.onBluetoothServiceUp(_arg0);
48 | reply.writeNoException();
49 | return true;
50 | }
51 | case TRANSACTION_onBluetoothServiceDown:
52 | {
53 | data.enforceInterface(descriptor);
54 | this.onBluetoothServiceDown();
55 | reply.writeNoException();
56 | return true;
57 | }
58 | case TRANSACTION_onBrEdrDown:
59 | {
60 | data.enforceInterface(descriptor);
61 | this.onBrEdrDown();
62 | reply.writeNoException();
63 | return true;
64 | }
65 | default:
66 | {
67 | return super.onTransact(code, data, reply, flags);
68 | }
69 | }
70 | }
71 | private static class Proxy implements IBluetoothManagerCallback
72 | {
73 | private android.os.IBinder mRemote;
74 | Proxy(android.os.IBinder remote)
75 | {
76 | mRemote = remote;
77 | }
78 | @Override public android.os.IBinder asBinder()
79 | {
80 | return mRemote;
81 | }
82 | public String getInterfaceDescriptor()
83 | {
84 | return DESCRIPTOR;
85 | }
86 | @Override public void onBluetoothServiceUp(IBluetooth bluetoothService) throws android.os.RemoteException
87 | {
88 | android.os.Parcel _data = android.os.Parcel.obtain();
89 | android.os.Parcel _reply = android.os.Parcel.obtain();
90 | try {
91 | _data.writeInterfaceToken(DESCRIPTOR);
92 | _data.writeStrongBinder((((bluetoothService!=null))?(bluetoothService.asBinder()):(null)));
93 | mRemote.transact(Stub.TRANSACTION_onBluetoothServiceUp, _data, _reply, 0);
94 | _reply.readException();
95 | }
96 | finally {
97 | _reply.recycle();
98 | _data.recycle();
99 | }
100 | }
101 | @Override public void onBluetoothServiceDown() throws android.os.RemoteException
102 | {
103 | android.os.Parcel _data = android.os.Parcel.obtain();
104 | android.os.Parcel _reply = android.os.Parcel.obtain();
105 | try {
106 | _data.writeInterfaceToken(DESCRIPTOR);
107 | mRemote.transact(Stub.TRANSACTION_onBluetoothServiceDown, _data, _reply, 0);
108 | _reply.readException();
109 | }
110 | finally {
111 | _reply.recycle();
112 | _data.recycle();
113 | }
114 | }
115 | @Override public void onBrEdrDown() throws android.os.RemoteException
116 | {
117 | android.os.Parcel _data = android.os.Parcel.obtain();
118 | android.os.Parcel _reply = android.os.Parcel.obtain();
119 | try {
120 | _data.writeInterfaceToken(DESCRIPTOR);
121 | mRemote.transact(Stub.TRANSACTION_onBrEdrDown, _data, _reply, 0);
122 | _reply.readException();
123 | }
124 | finally {
125 | _reply.recycle();
126 | _data.recycle();
127 | }
128 | }
129 | }
130 | static final int TRANSACTION_onBluetoothServiceUp = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
131 | static final int TRANSACTION_onBluetoothServiceDown = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
132 | static final int TRANSACTION_onBrEdrDown = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
133 | }
134 | public void onBluetoothServiceUp(IBluetooth bluetoothService) throws android.os.RemoteException;
135 | public void onBluetoothServiceDown() throws android.os.RemoteException;
136 | public void onBrEdrDown() throws android.os.RemoteException;
137 | }
138 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/OkBluetoothHook/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/okble/bluetooth_hook/BluetoothGattCallbackHook.java:
--------------------------------------------------------------------------------
1 | package okble.bluetooth_hook;
2 |
3 | import android.bluetooth.BluetoothDevice;
4 | import android.bluetooth.BluetoothGattService;
5 | import android.bluetooth.IBluetoothGattCallback;
6 | import android.bluetooth.le.AdvertiseSettings;
7 | import android.bluetooth.le.ScanResult;
8 | import android.os.ParcelUuid;
9 | import android.util.Log;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * author: okbean
15 | * date: On 2020/10/01
16 | * email: okbean020@163.com
17 | * description:BluetoothGattCallback服务代理类,该类主要拦截所有BluetoothGatt操作的回调
18 | */
19 | public final class BluetoothGattCallbackHook extends IBluetoothGattCallback.Stub{
20 |
21 | public final static String TAG = BluetoothGattCallbackHook.class.getSimpleName();
22 |
23 | private final IBluetoothGattCallback mDelegate;
24 |
25 | public BluetoothGattCallbackHook(final IBluetoothGattCallback delegate){
26 | this.mDelegate = delegate;
27 | }
28 |
29 | @Override
30 | public void onClientRegistered(int status, int clientIf) throws android.os.RemoteException {
31 | final String msg = "onClientRegistered. status:%d , clientIf:%d";
32 | Log.d(TAG, String.format(msg, status, clientIf));
33 | mDelegate.onClientRegistered(status, clientIf);
34 | }
35 |
36 | @Override
37 | public void onClientConnectionState(int status, int clientIf, boolean connected, String address) throws android.os.RemoteException {
38 | final String msg = "onClientConnectionState. status:%d , clientIf:%d , connected:%b , address:%s";
39 | Log.d(TAG, String.format(msg, status, clientIf, connected, address));
40 | mDelegate.onClientConnectionState(status, clientIf, connected, address);
41 | }
42 |
43 | @Override
44 | public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) throws android.os.RemoteException {
45 | final String msg = "onPhyUpdate. status:%d , txPhy:%d , rxPhy:%d , address:%s";
46 | Log.d(TAG, String.format(msg, status, txPhy, rxPhy, address));
47 | mDelegate.onPhyUpdate(address, txPhy, rxPhy, status);
48 | }
49 |
50 | @Override
51 | public void onPhyRead(String address, int txPhy, int rxPhy, int status) throws android.os.RemoteException {
52 | final String msg = "onPhyRead. status:%d , txPhy:%d , rxPhy:%d , address:%s";
53 | Log.d(TAG, String.format(msg, status, txPhy, rxPhy, address));
54 | mDelegate.onPhyRead(address, txPhy, rxPhy, status);
55 | }
56 |
57 | @Override
58 | public void onSearchComplete(String address, List services, int status) throws android.os.RemoteException {
59 | final String msg = "onSearchComplete. status:%d , address:%s";
60 | Log.d(TAG, String.format(msg, status, address));
61 | mDelegate.onSearchComplete(address, services, status);
62 | }
63 |
64 | @Override
65 | public void onCharacteristicRead(String address, int status, int handle, byte[] value) throws android.os.RemoteException {
66 | final String msg = "onCharacteristicRead. status:%d , value:(0x)%s , address:%s";
67 | Log.d(TAG, String.format(msg, status, Hex.toString(value, '-'), address));
68 | mDelegate.onCharacteristicRead( address, status, handle, value);
69 | }
70 |
71 | @Override
72 | public void onCharacteristicWrite(String address, int status, int handle) throws android.os.RemoteException {
73 | final String msg = "onCharacteristicWrite. status:%d , address:%s";
74 | Log.d(TAG, String.format(msg, status, address));
75 | mDelegate.onCharacteristicWrite(address, status, handle);
76 | }
77 |
78 | @Override
79 | public void onExecuteWrite(String address, int status) throws android.os.RemoteException {
80 | final String msg = "onExecuteWrite. status:%d, address:%s";
81 | Log.d(TAG, String.format(msg, status, address));
82 | mDelegate.onExecuteWrite( address, status);
83 | }
84 |
85 | @Override
86 | public void onDescriptorRead(String address, int status, int handle, byte[] value) throws android.os.RemoteException {
87 | final String msg = "onDescriptorRead. status:%d , value:(0x)%s , address:%s";
88 | Log.d(TAG, String.format(msg, status, Hex.toString(value, '-'), address));
89 | mDelegate.onDescriptorRead( address, status, handle, value);
90 | }
91 |
92 | @Override
93 | public void onDescriptorWrite(String address, int status, int handle) throws android.os.RemoteException {
94 | final String msg = "onDescriptorWrite. status:%d, address:%s";
95 | Log.d(TAG, String.format(msg, status, address));
96 | mDelegate.onDescriptorWrite( address, status, handle);
97 | }
98 |
99 | @Override
100 | public void onNotify(String address, int handle, byte[] value) throws android.os.RemoteException {
101 | final String msg = "onNotify. value:(0x)%s, address:%s";
102 | Log.d(TAG, String.format(msg, Hex.toString(value, '-'), address));
103 | mDelegate.onNotify(address, handle, value);
104 | }
105 |
106 | @Override
107 | public void onReadRemoteRssi(String address, int rssi, int status) throws android.os.RemoteException {
108 | final String msg = "onReadRemoteRssi. status:%d , rssi:%d, address:%s";
109 | Log.d(TAG, String.format(msg, status, rssi, address));
110 | mDelegate.onReadRemoteRssi(address, rssi, status);
111 | }
112 |
113 | @Override
114 | public void onConfigureMTU(String address, int mtu, int status) throws android.os.RemoteException {
115 | final String msg = "onConfigureMTU. status:%d , mtu:%d, address:%s";
116 | Log.d(TAG, String.format(msg, status, mtu, address));
117 | mDelegate.onConfigureMTU(address, mtu, status);
118 | }
119 |
120 | @Override
121 | public void onConnectionUpdated(String address, int interval, int latency, int timeout, int status) throws android.os.RemoteException {
122 | final String msg = "onConnectionUpdated. status:%d , interval:%d, latency:%d, timeout:%d , address:%s";
123 | Log.d(TAG, String.format(msg, status, interval, latency, timeout, address));
124 | mDelegate.onConnectionUpdated(address, interval, latency, timeout, status);
125 | }
126 |
127 |
128 |
129 | public void onScanResult(ScanResult scanResult) throws android.os.RemoteException{
130 | final String msg = "onScanResult. address:%s , rssi:%d";
131 | final BluetoothDevice device = scanResult == null ? null : scanResult.getDevice();
132 | final int rssi = scanResult == null ? Integer.MAX_VALUE : scanResult.getRssi();
133 | Log.d(TAG, String.format(msg, device, rssi));
134 | mDelegate.onScanResult(scanResult);
135 | }
136 |
137 |
138 |
139 | public void onBatchScanResults(List batchResults) throws android.os.RemoteException{
140 | final String msg = "onBatchScanResults.";
141 | Log.d(TAG, msg);
142 | mDelegate.onBatchScanResults(batchResults);
143 | }
144 |
145 |
146 | public void onMultiAdvertiseCallback(int status, boolean isStart, AdvertiseSettings advertiseSettings) throws android.os.RemoteException{
147 | final String msg = "onMultiAdvertiseCallback. status:%d";
148 | Log.d(TAG, String.format(msg, status));
149 | mDelegate.onMultiAdvertiseCallback(status, isStart, advertiseSettings);
150 | }
151 |
152 |
153 | public void onScanManagerErrorCallback(int errorCode) throws android.os.RemoteException{
154 | final String msg = "onScanManagerErrorCallback. errorCode:%d";
155 | Log.d(TAG, String.format(msg, errorCode));
156 | mDelegate.onScanManagerErrorCallback(errorCode);
157 | }
158 |
159 |
160 | public void onFoundOrLost(boolean onFound, ScanResult scanResult) throws android.os.RemoteException{
161 | final String msg = "onFoundOrLost. onFound:%b , address:%s , rssi:%d";
162 | final BluetoothDevice device = scanResult == null ? null : scanResult.getDevice();
163 | final int rssi = scanResult == null ? Integer.MAX_VALUE : scanResult.getRssi();
164 | Log.d(TAG, String.format(msg, onFound, device, rssi));
165 | mDelegate.onFoundOrLost(onFound, scanResult);
166 | }
167 |
168 |
169 | public void onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid) throws android.os.RemoteException{
170 | final String msg = "onGetService. address:%s , uuid:%s";
171 | Log.d(TAG, String.format(msg, address, srvcUuid));
172 | mDelegate.onGetService(address, srvcType, srvcInstId, srvcUuid);
173 | }
174 |
175 |
176 | public void onGetIncludedService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid) throws android.os.RemoteException{
177 | final String msg = "onGetIncludedService. address:%s , uuid:%s";
178 | Log.d(TAG, String.format(msg, address, inclSrvcUuid));
179 | mDelegate.onGetIncludedService( address, srvcType, srvcInstId, srvcUuid, inclSrvcType, inclSrvcInstId, inclSrvcUuid);
180 | }
181 |
182 |
183 | public void onGetCharacteristic(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps) throws android.os.RemoteException{
184 | final String msg = "onGetCharacteristic. address:%s , uuid:%s";
185 | Log.d(TAG, String.format(msg, address, charUuid));
186 | mDelegate.onGetCharacteristic( address, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, charProps);
187 | }
188 |
189 |
190 | public void onGetDescriptor(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) throws android.os.RemoteException{
191 | final String msg = "onGetDescriptor. address:%s , uuid:%s";
192 | Log.d(TAG, String.format(msg, address, descrUuid));
193 | mDelegate.onGetDescriptor( address, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, descrInstId, descrUuid);
194 | }
195 |
196 |
197 | public void onSearchComplete(String address, int status) throws android.os.RemoteException{
198 | final String msg = "onSearchComplete. status:%d , address:%s";
199 | Log.d(TAG, String.format(msg, status, address));
200 | mDelegate.onSearchComplete(address, status);
201 | }
202 |
203 |
204 | public void onCharacteristicRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) throws android.os.RemoteException{
205 | final String msg = "onCharacteristicRead. status:%d , value:(0x)%s";
206 | Log.d(TAG, String.format(msg, status, Hex.toString(value, '-')));
207 | mDelegate.onCharacteristicRead( address, status, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, value);
208 | }
209 |
210 |
211 | public void onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid) throws android.os.RemoteException{
212 | final String msg = "onCharacteristicWrite. status:%d";
213 | Log.d(TAG, String.format(msg, status));
214 | mDelegate.onCharacteristicWrite( address, status, srvcType, srvcInstId, srvcUuid, charInstId, charUuid);
215 | }
216 |
217 |
218 | public void onDescriptorRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid, byte[] value) throws android.os.RemoteException{
219 | final String msg = "onDescriptorRead. status:%d , value:(0x)%s";
220 | Log.d(TAG, String.format(msg, status, Hex.toString(value, '-')));
221 | mDelegate.onDescriptorRead( address, status, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, descrInstId, descrUuid, value);
222 | }
223 |
224 |
225 | public void onDescriptorWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) throws android.os.RemoteException{
226 | final String msg = "onCharacteristicWrite. status:%d";
227 | Log.d(TAG, String.format(msg, status));
228 | mDelegate.onDescriptorWrite( address, status, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, descrInstId, descrUuid);
229 | }
230 |
231 |
232 | public void onNotify(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) throws android.os.RemoteException{
233 | final String msg = "onNotify. value:(0x)%s";
234 | Log.d(TAG, String.format(msg, Hex.toString(value, '-')));
235 | mDelegate.onNotify( address, srvcType, srvcInstId, srvcUuid, charInstId, charUuid, value);
236 | }
237 |
238 |
239 | public void onClientConnParamsChanged(String address, int interval, int status) throws android.os.RemoteException{
240 | final String msg = "onClientConnParamsChanged. status:%d , interval:%d";
241 | Log.d(TAG, String.format(msg, status, interval));
242 | mDelegate.onClientConnParamsChanged(address, interval, status);
243 | }
244 |
245 | }
246 |
--------------------------------------------------------------------------------
/OkBluetoothHook/src/main/java/android/bluetooth/IBluetoothGattCallback.java:
--------------------------------------------------------------------------------
1 | package android.bluetooth;
2 |
3 | import android.os.ParcelUuid;
4 |
5 | public interface IBluetoothGattCallback extends android.os.IInterface {
6 | public void onClientRegistered(int status, int clientIf) throws android.os.RemoteException;
7 |
8 | public void onClientConnectionState(int status, int clientIf, boolean connected, String address) throws android.os.RemoteException;
9 |
10 | public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) throws android.os.RemoteException;
11 |
12 | public void onPhyRead(String address, int txPhy, int rxPhy, int status) throws android.os.RemoteException;
13 |
14 | public void onSearchComplete(String address, java.util.List services, int status) throws android.os.RemoteException;
15 |
16 | public void onCharacteristicRead(String address, int status, int handle, byte[] value) throws android.os.RemoteException;
17 |
18 | public void onCharacteristicWrite(String address, int status, int handle) throws android.os.RemoteException;
19 |
20 | public void onExecuteWrite(String address, int status) throws android.os.RemoteException;
21 |
22 | public void onDescriptorRead(String address, int status, int handle, byte[] value) throws android.os.RemoteException;
23 |
24 | public void onDescriptorWrite(String address, int status, int handle) throws android.os.RemoteException;
25 |
26 | public void onNotify(String address, int handle, byte[] value) throws android.os.RemoteException;
27 |
28 | public void onReadRemoteRssi(String address, int rssi, int status) throws android.os.RemoteException;
29 |
30 | public void onConfigureMTU(String address, int mtu, int status) throws android.os.RemoteException;
31 |
32 | public void onConnectionUpdated(String address, int interval, int latency, int timeout, int status) throws android.os.RemoteException;
33 |
34 | public void onScanResult(android.bluetooth.le.ScanResult scanResult) throws android.os.RemoteException;
35 |
36 | public void onBatchScanResults(java.util.List batchResults) throws android.os.RemoteException;
37 |
38 | public void onMultiAdvertiseCallback(int status, boolean isStart, android.bluetooth.le.AdvertiseSettings advertiseSettings) throws android.os.RemoteException;
39 |
40 | public void onScanManagerErrorCallback(int errorCode) throws android.os.RemoteException;
41 |
42 | public void onFoundOrLost(boolean onFound, android.bluetooth.le.ScanResult scanResult) throws android.os.RemoteException;
43 |
44 | public void onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid) throws android.os.RemoteException;
45 |
46 | public void onGetIncludedService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid) throws android.os.RemoteException;
47 |
48 | public void onGetCharacteristic(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps) throws android.os.RemoteException;
49 |
50 | public void onGetDescriptor(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) throws android.os.RemoteException;
51 |
52 | public void onSearchComplete(String address, int status) throws android.os.RemoteException;
53 |
54 | public void onCharacteristicRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) throws android.os.RemoteException;
55 |
56 | public void onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid) throws android.os.RemoteException;
57 |
58 | public void onDescriptorRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid, byte[] value) throws android.os.RemoteException;
59 |
60 | public void onDescriptorWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) throws android.os.RemoteException;
61 |
62 | public void onNotify(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) throws android.os.RemoteException;
63 |
64 | public void onClientConnParamsChanged(String address, int interval, int status) throws android.os.RemoteException;
65 |
66 | /**
67 | *╭∩╮( -_- )╭∩╮
68 | *
69 | *╭∩╮( -_- )╭∩╮
70 | * /
71 | /**
72 | * Local-side IPC implementation stub class.
73 | *
74 | */
75 | public static abstract class Stub extends android.os.Binder implements IBluetoothGattCallback {
76 | static final int TRANSACTION_onClientRegistered = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
77 | static final int TRANSACTION_onClientConnectionState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
78 | static final int TRANSACTION_onPhyUpdate = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
79 | static final int TRANSACTION_onPhyRead = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
80 | static final int TRANSACTION_onSearchComplete = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
81 | static final int TRANSACTION_onCharacteristicRead = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
82 | static final int TRANSACTION_onCharacteristicWrite = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
83 | static final int TRANSACTION_onExecuteWrite = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
84 | static final int TRANSACTION_onDescriptorRead = (android.os.IBinder.FIRST_CALL_TRANSACTION + 8);
85 | static final int TRANSACTION_onDescriptorWrite = (android.os.IBinder.FIRST_CALL_TRANSACTION + 9);
86 | static final int TRANSACTION_onNotify = (android.os.IBinder.FIRST_CALL_TRANSACTION + 10);
87 | static final int TRANSACTION_onReadRemoteRssi = (android.os.IBinder.FIRST_CALL_TRANSACTION + 11);
88 | static final int TRANSACTION_onConfigureMTU = (android.os.IBinder.FIRST_CALL_TRANSACTION + 12);
89 | static final int TRANSACTION_onConnectionUpdated = (android.os.IBinder.FIRST_CALL_TRANSACTION + 13);
90 | static final int TRANSACTION_onScanResult = (android.os.IBinder.FIRST_CALL_TRANSACTION + 14);
91 | static final int TRANSACTION_onBatchScanResults = (android.os.IBinder.FIRST_CALL_TRANSACTION + 15);
92 | static final int TRANSACTION_onMultiAdvertiseCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16);
93 | static final int TRANSACTION_onScanManagerErrorCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 17);
94 | static final int TRANSACTION_onFoundOrLost = (android.os.IBinder.FIRST_CALL_TRANSACTION + 18);
95 | private static final String DESCRIPTOR = "android.bluetooth.IBluetoothGattCallback";
96 |
97 | /**
98 | * Construct the stub at attach it to the interface.
99 | */
100 | public Stub() {
101 | this.attachInterface(this, DESCRIPTOR);
102 | }
103 |
104 | /**
105 | *
106 | * Cast an IBinder object into an android.bluetooth.IBluetoothGattCallback interface,
107 | * generating a proxy if needed.
108 | */
109 | public static IBluetoothGattCallback asInterface(android.os.IBinder obj) {
110 | if ((obj == null)) {
111 | return null;
112 | }
113 | android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
114 | if (((iin != null) && (iin instanceof IBluetoothGattCallback))) {
115 | return ((IBluetoothGattCallback) iin);
116 | }
117 | return new Proxy(obj);
118 | }
119 |
120 | @Override
121 | public android.os.IBinder asBinder() {
122 | return this;
123 | }
124 |
125 | @Override
126 | public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
127 | String descriptor = DESCRIPTOR;
128 | switch (code) {
129 | case INTERFACE_TRANSACTION: {
130 | reply.writeString(descriptor);
131 | return true;
132 | }
133 | case TRANSACTION_onClientRegistered: {
134 | data.enforceInterface(descriptor);
135 | int _arg0;
136 | _arg0 = data.readInt();
137 | int _arg1;
138 | _arg1 = data.readInt();
139 | this.onClientRegistered(_arg0, _arg1);
140 | reply.writeNoException();
141 | return true;
142 | }
143 | case TRANSACTION_onClientConnectionState: {
144 | data.enforceInterface(descriptor);
145 | int _arg0;
146 | _arg0 = data.readInt();
147 | int _arg1;
148 | _arg1 = data.readInt();
149 | boolean _arg2;
150 | _arg2 = (0 != data.readInt());
151 | String _arg3;
152 | _arg3 = data.readString();
153 | this.onClientConnectionState(_arg0, _arg1, _arg2, _arg3);
154 | reply.writeNoException();
155 | return true;
156 | }
157 | case TRANSACTION_onPhyUpdate: {
158 | data.enforceInterface(descriptor);
159 | String _arg0;
160 | _arg0 = data.readString();
161 | int _arg1;
162 | _arg1 = data.readInt();
163 | int _arg2;
164 | _arg2 = data.readInt();
165 | int _arg3;
166 | _arg3 = data.readInt();
167 | this.onPhyUpdate(_arg0, _arg1, _arg2, _arg3);
168 | reply.writeNoException();
169 | return true;
170 | }
171 | case TRANSACTION_onPhyRead: {
172 | data.enforceInterface(descriptor);
173 | String _arg0;
174 | _arg0 = data.readString();
175 | int _arg1;
176 | _arg1 = data.readInt();
177 | int _arg2;
178 | _arg2 = data.readInt();
179 | int _arg3;
180 | _arg3 = data.readInt();
181 | this.onPhyRead(_arg0, _arg1, _arg2, _arg3);
182 | reply.writeNoException();
183 | return true;
184 | }
185 | case TRANSACTION_onSearchComplete: {
186 | data.enforceInterface(descriptor);
187 | String _arg0;
188 | _arg0 = data.readString();
189 | java.util.List _arg1;
190 | _arg1 = data.createTypedArrayList(null);
191 | int _arg2;
192 | _arg2 = data.readInt();
193 | this.onSearchComplete(_arg0, _arg1, _arg2);
194 | reply.writeNoException();
195 | return true;
196 | }
197 | case TRANSACTION_onCharacteristicRead: {
198 | data.enforceInterface(descriptor);
199 | String _arg0;
200 | _arg0 = data.readString();
201 | int _arg1;
202 | _arg1 = data.readInt();
203 | int _arg2;
204 | _arg2 = data.readInt();
205 | byte[] _arg3;
206 | _arg3 = data.createByteArray();
207 | this.onCharacteristicRead(_arg0, _arg1, _arg2, _arg3);
208 | reply.writeNoException();
209 | return true;
210 | }
211 | case TRANSACTION_onCharacteristicWrite: {
212 | data.enforceInterface(descriptor);
213 | String _arg0;
214 | _arg0 = data.readString();
215 | int _arg1;
216 | _arg1 = data.readInt();
217 | int _arg2;
218 | _arg2 = data.readInt();
219 | this.onCharacteristicWrite(_arg0, _arg1, _arg2);
220 | reply.writeNoException();
221 | return true;
222 | }
223 | case TRANSACTION_onExecuteWrite: {
224 | data.enforceInterface(descriptor);
225 | String _arg0;
226 | _arg0 = data.readString();
227 | int _arg1;
228 | _arg1 = data.readInt();
229 | this.onExecuteWrite(_arg0, _arg1);
230 | reply.writeNoException();
231 | return true;
232 | }
233 | case TRANSACTION_onDescriptorRead: {
234 | data.enforceInterface(descriptor);
235 | String _arg0;
236 | _arg0 = data.readString();
237 | int _arg1;
238 | _arg1 = data.readInt();
239 | int _arg2;
240 | _arg2 = data.readInt();
241 | byte[] _arg3;
242 | _arg3 = data.createByteArray();
243 | this.onDescriptorRead(_arg0, _arg1, _arg2, _arg3);
244 | reply.writeNoException();
245 | return true;
246 | }
247 | case TRANSACTION_onDescriptorWrite: {
248 | data.enforceInterface(descriptor);
249 | String _arg0;
250 | _arg0 = data.readString();
251 | int _arg1;
252 | _arg1 = data.readInt();
253 | int _arg2;
254 | _arg2 = data.readInt();
255 | this.onDescriptorWrite(_arg0, _arg1, _arg2);
256 | reply.writeNoException();
257 | return true;
258 | }
259 | case TRANSACTION_onNotify: {
260 | data.enforceInterface(descriptor);
261 | String _arg0;
262 | _arg0 = data.readString();
263 | int _arg1;
264 | _arg1 = data.readInt();
265 | byte[] _arg2;
266 | _arg2 = data.createByteArray();
267 | this.onNotify(_arg0, _arg1, _arg2);
268 | reply.writeNoException();
269 | return true;
270 | }
271 | case TRANSACTION_onReadRemoteRssi: {
272 | data.enforceInterface(descriptor);
273 | String _arg0;
274 | _arg0 = data.readString();
275 | int _arg1;
276 | _arg1 = data.readInt();
277 | int _arg2;
278 | _arg2 = data.readInt();
279 | this.onReadRemoteRssi(_arg0, _arg1, _arg2);
280 | reply.writeNoException();
281 | return true;
282 | }
283 | case TRANSACTION_onConfigureMTU: {
284 | data.enforceInterface(descriptor);
285 | String _arg0;
286 | _arg0 = data.readString();
287 | int _arg1;
288 | _arg1 = data.readInt();
289 | int _arg2;
290 | _arg2 = data.readInt();
291 | this.onConfigureMTU(_arg0, _arg1, _arg2);
292 | reply.writeNoException();
293 | return true;
294 | }
295 | case TRANSACTION_onConnectionUpdated: {
296 | data.enforceInterface(descriptor);
297 | String _arg0;
298 | _arg0 = data.readString();
299 | int _arg1;
300 | _arg1 = data.readInt();
301 | int _arg2;
302 | _arg2 = data.readInt();
303 | int _arg3;
304 | _arg3 = data.readInt();
305 | int _arg4;
306 | _arg4 = data.readInt();
307 | this.onConnectionUpdated(_arg0, _arg1, _arg2, _arg3, _arg4);
308 | reply.writeNoException();
309 | return true;
310 | }
311 | case TRANSACTION_onScanResult: {
312 | data.enforceInterface(descriptor);
313 | android.bluetooth.le.ScanResult _arg0;
314 | if ((0 != data.readInt())) {
315 | _arg0 = android.bluetooth.le.ScanResult.CREATOR.createFromParcel(data);
316 | } else {
317 | _arg0 = null;
318 | }
319 | this.onScanResult(_arg0);
320 | reply.writeNoException();
321 | return true;
322 | }
323 | case TRANSACTION_onBatchScanResults: {
324 | data.enforceInterface(descriptor);
325 | java.util.List _arg0;
326 | _arg0 = data.createTypedArrayList(android.bluetooth.le.ScanResult.CREATOR);
327 | this.onBatchScanResults(_arg0);
328 | reply.writeNoException();
329 | return true;
330 | }
331 | case TRANSACTION_onMultiAdvertiseCallback: {
332 | data.enforceInterface(descriptor);
333 | int _arg0;
334 | _arg0 = data.readInt();
335 | boolean _arg1;
336 | _arg1 = (0 != data.readInt());
337 | android.bluetooth.le.AdvertiseSettings _arg2;
338 | if ((0 != data.readInt())) {
339 | _arg2 = android.bluetooth.le.AdvertiseSettings.CREATOR.createFromParcel(data);
340 | } else {
341 | _arg2 = null;
342 | }
343 | this.onMultiAdvertiseCallback(_arg0, _arg1, _arg2);
344 | reply.writeNoException();
345 | return true;
346 | }
347 | case TRANSACTION_onScanManagerErrorCallback: {
348 | data.enforceInterface(descriptor);
349 | int _arg0;
350 | _arg0 = data.readInt();
351 | this.onScanManagerErrorCallback(_arg0);
352 | reply.writeNoException();
353 | return true;
354 | }
355 | case TRANSACTION_onFoundOrLost: {
356 | data.enforceInterface(descriptor);
357 | boolean _arg0;
358 | _arg0 = (0 != data.readInt());
359 | android.bluetooth.le.ScanResult _arg1;
360 | if ((0 != data.readInt())) {
361 | _arg1 = android.bluetooth.le.ScanResult.CREATOR.createFromParcel(data);
362 | } else {
363 | _arg1 = null;
364 | }
365 | this.onFoundOrLost(_arg0, _arg1);
366 | reply.writeNoException();
367 | return true;
368 | }
369 | default: {
370 | return super.onTransact(code, data, reply, flags);
371 | }
372 | }
373 | }
374 |
375 | private static class Proxy implements IBluetoothGattCallback {
376 | private android.os.IBinder mRemote;
377 |
378 | Proxy(android.os.IBinder remote) {
379 | mRemote = remote;
380 | }
381 |
382 | @Override
383 | public android.os.IBinder asBinder() {
384 | return mRemote;
385 | }
386 |
387 | public String getInterfaceDescriptor() {
388 | return DESCRIPTOR;
389 | }
390 |
391 | @Override
392 | public void onClientRegistered(int status, int clientIf) throws android.os.RemoteException {
393 | android.os.Parcel _data = android.os.Parcel.obtain();
394 | android.os.Parcel _reply = android.os.Parcel.obtain();
395 | try {
396 | _data.writeInterfaceToken(DESCRIPTOR);
397 | _data.writeInt(status);
398 | _data.writeInt(clientIf);
399 | mRemote.transact(Stub.TRANSACTION_onClientRegistered, _data, _reply, 0);
400 | _reply.readException();
401 | } finally {
402 | _reply.recycle();
403 | _data.recycle();
404 | }
405 | }
406 |
407 | @Override
408 | public void onClientConnectionState(int status, int clientIf, boolean connected, String address) throws android.os.RemoteException {
409 | android.os.Parcel _data = android.os.Parcel.obtain();
410 | android.os.Parcel _reply = android.os.Parcel.obtain();
411 | try {
412 | _data.writeInterfaceToken(DESCRIPTOR);
413 | _data.writeInt(status);
414 | _data.writeInt(clientIf);
415 | _data.writeInt(((connected) ? (1) : (0)));
416 | _data.writeString(address);
417 | mRemote.transact(Stub.TRANSACTION_onClientConnectionState, _data, _reply, 0);
418 | _reply.readException();
419 | } finally {
420 | _reply.recycle();
421 | _data.recycle();
422 | }
423 | }
424 |
425 | @Override
426 | public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) throws android.os.RemoteException {
427 | android.os.Parcel _data = android.os.Parcel.obtain();
428 | android.os.Parcel _reply = android.os.Parcel.obtain();
429 | try {
430 | _data.writeInterfaceToken(DESCRIPTOR);
431 | _data.writeString(address);
432 | _data.writeInt(txPhy);
433 | _data.writeInt(rxPhy);
434 | _data.writeInt(status);
435 | mRemote.transact(Stub.TRANSACTION_onPhyUpdate, _data, _reply, 0);
436 | _reply.readException();
437 | } finally {
438 | _reply.recycle();
439 | _data.recycle();
440 | }
441 | }
442 |
443 | @Override
444 | public void onPhyRead(String address, int txPhy, int rxPhy, int status) throws android.os.RemoteException {
445 | android.os.Parcel _data = android.os.Parcel.obtain();
446 | android.os.Parcel _reply = android.os.Parcel.obtain();
447 | try {
448 | _data.writeInterfaceToken(DESCRIPTOR);
449 | _data.writeString(address);
450 | _data.writeInt(txPhy);
451 | _data.writeInt(rxPhy);
452 | _data.writeInt(status);
453 | mRemote.transact(Stub.TRANSACTION_onPhyRead, _data, _reply, 0);
454 | _reply.readException();
455 | } finally {
456 | _reply.recycle();
457 | _data.recycle();
458 | }
459 | }
460 |
461 | @Override
462 | public void onSearchComplete(String address, java.util.List services, int status) throws android.os.RemoteException {
463 | android.os.Parcel _data = android.os.Parcel.obtain();
464 | android.os.Parcel _reply = android.os.Parcel.obtain();
465 | try {
466 | _data.writeInterfaceToken(DESCRIPTOR);
467 | _data.writeString(address);
468 | _data.writeTypedList(services);
469 | _data.writeInt(status);
470 | mRemote.transact(Stub.TRANSACTION_onSearchComplete, _data, _reply, 0);
471 | _reply.readException();
472 | } finally {
473 | _reply.recycle();
474 | _data.recycle();
475 | }
476 | }
477 |
478 | @Override
479 | public void onCharacteristicRead(String address, int status, int handle, byte[] value) throws android.os.RemoteException {
480 | android.os.Parcel _data = android.os.Parcel.obtain();
481 | android.os.Parcel _reply = android.os.Parcel.obtain();
482 | try {
483 | _data.writeInterfaceToken(DESCRIPTOR);
484 | _data.writeString(address);
485 | _data.writeInt(status);
486 | _data.writeInt(handle);
487 | _data.writeByteArray(value);
488 | mRemote.transact(Stub.TRANSACTION_onCharacteristicRead, _data, _reply, 0);
489 | _reply.readException();
490 | } finally {
491 | _reply.recycle();
492 | _data.recycle();
493 | }
494 | }
495 |
496 | @Override
497 | public void onCharacteristicWrite(String address, int status, int handle) throws android.os.RemoteException {
498 | android.os.Parcel _data = android.os.Parcel.obtain();
499 | android.os.Parcel _reply = android.os.Parcel.obtain();
500 | try {
501 | _data.writeInterfaceToken(DESCRIPTOR);
502 | _data.writeString(address);
503 | _data.writeInt(status);
504 | _data.writeInt(handle);
505 | mRemote.transact(Stub.TRANSACTION_onCharacteristicWrite, _data, _reply, 0);
506 | _reply.readException();
507 | } finally {
508 | _reply.recycle();
509 | _data.recycle();
510 | }
511 | }
512 |
513 | @Override
514 | public void onExecuteWrite(String address, int status) throws android.os.RemoteException {
515 | android.os.Parcel _data = android.os.Parcel.obtain();
516 | android.os.Parcel _reply = android.os.Parcel.obtain();
517 | try {
518 | _data.writeInterfaceToken(DESCRIPTOR);
519 | _data.writeString(address);
520 | _data.writeInt(status);
521 | mRemote.transact(Stub.TRANSACTION_onExecuteWrite, _data, _reply, 0);
522 | _reply.readException();
523 | } finally {
524 | _reply.recycle();
525 | _data.recycle();
526 | }
527 | }
528 |
529 | @Override
530 | public void onDescriptorRead(String address, int status, int handle, byte[] value) throws android.os.RemoteException {
531 | android.os.Parcel _data = android.os.Parcel.obtain();
532 | android.os.Parcel _reply = android.os.Parcel.obtain();
533 | try {
534 | _data.writeInterfaceToken(DESCRIPTOR);
535 | _data.writeString(address);
536 | _data.writeInt(status);
537 | _data.writeInt(handle);
538 | _data.writeByteArray(value);
539 | mRemote.transact(Stub.TRANSACTION_onDescriptorRead, _data, _reply, 0);
540 | _reply.readException();
541 | } finally {
542 | _reply.recycle();
543 | _data.recycle();
544 | }
545 | }
546 |
547 | @Override
548 | public void onDescriptorWrite(String address, int status, int handle) throws android.os.RemoteException {
549 | android.os.Parcel _data = android.os.Parcel.obtain();
550 | android.os.Parcel _reply = android.os.Parcel.obtain();
551 | try {
552 | _data.writeInterfaceToken(DESCRIPTOR);
553 | _data.writeString(address);
554 | _data.writeInt(status);
555 | _data.writeInt(handle);
556 | mRemote.transact(Stub.TRANSACTION_onDescriptorWrite, _data, _reply, 0);
557 | _reply.readException();
558 | } finally {
559 | _reply.recycle();
560 | _data.recycle();
561 | }
562 | }
563 |
564 | @Override
565 | public void onNotify(String address, int handle, byte[] value) throws android.os.RemoteException {
566 | android.os.Parcel _data = android.os.Parcel.obtain();
567 | android.os.Parcel _reply = android.os.Parcel.obtain();
568 | try {
569 | _data.writeInterfaceToken(DESCRIPTOR);
570 | _data.writeString(address);
571 | _data.writeInt(handle);
572 | _data.writeByteArray(value);
573 | mRemote.transact(Stub.TRANSACTION_onNotify, _data, _reply, 0);
574 | _reply.readException();
575 | } finally {
576 | _reply.recycle();
577 | _data.recycle();
578 | }
579 | }
580 |
581 | @Override
582 | public void onReadRemoteRssi(String address, int rssi, int status) throws android.os.RemoteException {
583 | android.os.Parcel _data = android.os.Parcel.obtain();
584 | android.os.Parcel _reply = android.os.Parcel.obtain();
585 | try {
586 | _data.writeInterfaceToken(DESCRIPTOR);
587 | _data.writeString(address);
588 | _data.writeInt(rssi);
589 | _data.writeInt(status);
590 | mRemote.transact(Stub.TRANSACTION_onReadRemoteRssi, _data, _reply, 0);
591 | _reply.readException();
592 | } finally {
593 | _reply.recycle();
594 | _data.recycle();
595 | }
596 | }
597 |
598 | @Override
599 | public void onConfigureMTU(String address, int mtu, int status) throws android.os.RemoteException {
600 | android.os.Parcel _data = android.os.Parcel.obtain();
601 | android.os.Parcel _reply = android.os.Parcel.obtain();
602 | try {
603 | _data.writeInterfaceToken(DESCRIPTOR);
604 | _data.writeString(address);
605 | _data.writeInt(mtu);
606 | _data.writeInt(status);
607 | mRemote.transact(Stub.TRANSACTION_onConfigureMTU, _data, _reply, 0);
608 | _reply.readException();
609 | } finally {
610 | _reply.recycle();
611 | _data.recycle();
612 | }
613 | }
614 |
615 | @Override
616 | public void onConnectionUpdated(String address, int interval, int latency, int timeout, int status) throws android.os.RemoteException {
617 | android.os.Parcel _data = android.os.Parcel.obtain();
618 | android.os.Parcel _reply = android.os.Parcel.obtain();
619 | try {
620 | _data.writeInterfaceToken(DESCRIPTOR);
621 | _data.writeString(address);
622 | _data.writeInt(interval);
623 | _data.writeInt(latency);
624 | _data.writeInt(timeout);
625 | _data.writeInt(status);
626 | mRemote.transact(Stub.TRANSACTION_onConnectionUpdated, _data, _reply, 0);
627 | _reply.readException();
628 | } finally {
629 | _reply.recycle();
630 | _data.recycle();
631 | }
632 | }
633 |
634 | @Override
635 | public void onScanResult(android.bluetooth.le.ScanResult scanResult) throws android.os.RemoteException {
636 | android.os.Parcel _data = android.os.Parcel.obtain();
637 | android.os.Parcel _reply = android.os.Parcel.obtain();
638 | try {
639 | _data.writeInterfaceToken(DESCRIPTOR);
640 | if ((scanResult != null)) {
641 | _data.writeInt(1);
642 | scanResult.writeToParcel(_data, 0);
643 | } else {
644 | _data.writeInt(0);
645 | }
646 | mRemote.transact(Stub.TRANSACTION_onScanResult, _data, _reply, 0);
647 | _reply.readException();
648 | } finally {
649 | _reply.recycle();
650 | _data.recycle();
651 | }
652 | }
653 |
654 | @Override
655 | public void onBatchScanResults(java.util.List batchResults) throws android.os.RemoteException {
656 | android.os.Parcel _data = android.os.Parcel.obtain();
657 | android.os.Parcel _reply = android.os.Parcel.obtain();
658 | try {
659 | _data.writeInterfaceToken(DESCRIPTOR);
660 | _data.writeTypedList(batchResults);
661 | mRemote.transact(Stub.TRANSACTION_onBatchScanResults, _data, _reply, 0);
662 | _reply.readException();
663 | } finally {
664 | _reply.recycle();
665 | _data.recycle();
666 | }
667 | }
668 |
669 | @Override
670 | public void onMultiAdvertiseCallback(int status, boolean isStart, android.bluetooth.le.AdvertiseSettings advertiseSettings) throws android.os.RemoteException {
671 | android.os.Parcel _data = android.os.Parcel.obtain();
672 | android.os.Parcel _reply = android.os.Parcel.obtain();
673 | try {
674 | _data.writeInterfaceToken(DESCRIPTOR);
675 | _data.writeInt(status);
676 | _data.writeInt(((isStart) ? (1) : (0)));
677 | if ((advertiseSettings != null)) {
678 | _data.writeInt(1);
679 | advertiseSettings.writeToParcel(_data, 0);
680 | } else {
681 | _data.writeInt(0);
682 | }
683 | mRemote.transact(Stub.TRANSACTION_onMultiAdvertiseCallback, _data, _reply, 0);
684 | _reply.readException();
685 | } finally {
686 | _reply.recycle();
687 | _data.recycle();
688 | }
689 | }
690 |
691 | @Override
692 | public void onScanManagerErrorCallback(int errorCode) throws android.os.RemoteException {
693 | android.os.Parcel _data = android.os.Parcel.obtain();
694 | android.os.Parcel _reply = android.os.Parcel.obtain();
695 | try {
696 | _data.writeInterfaceToken(DESCRIPTOR);
697 | _data.writeInt(errorCode);
698 | mRemote.transact(Stub.TRANSACTION_onScanManagerErrorCallback, _data, _reply, 0);
699 | _reply.readException();
700 | } finally {
701 | _reply.recycle();
702 | _data.recycle();
703 | }
704 | }
705 |
706 | @Override
707 | public void onFoundOrLost(boolean onFound, android.bluetooth.le.ScanResult scanResult) throws android.os.RemoteException {
708 | android.os.Parcel _data = android.os.Parcel.obtain();
709 | android.os.Parcel _reply = android.os.Parcel.obtain();
710 | try {
711 | _data.writeInterfaceToken(DESCRIPTOR);
712 | _data.writeInt(((onFound) ? (1) : (0)));
713 | if ((scanResult != null)) {
714 | _data.writeInt(1);
715 | scanResult.writeToParcel(_data, 0);
716 | } else {
717 | _data.writeInt(0);
718 | }
719 | mRemote.transact(Stub.TRANSACTION_onFoundOrLost, _data, _reply, 0);
720 | _reply.readException();
721 | } finally {
722 | _reply.recycle();
723 | _data.recycle();
724 | }
725 | }
726 |
727 |
728 |
729 | public void onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid) throws android.os.RemoteException {
730 |
731 | }
732 |
733 |
734 | public void onGetIncludedService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid) throws android.os.RemoteException {
735 |
736 | }
737 |
738 |
739 | public void onGetCharacteristic(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps) throws android.os.RemoteException {
740 |
741 | }
742 |
743 |
744 | public void onGetDescriptor(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) throws android.os.RemoteException {
745 |
746 | }
747 |
748 |
749 | public void onSearchComplete(String address, int status) throws android.os.RemoteException {
750 |
751 | }
752 |
753 |
754 | public void onCharacteristicRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) throws android.os.RemoteException {
755 |
756 | }
757 |
758 |
759 | public void onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid) throws android.os.RemoteException {
760 |
761 | }
762 |
763 |
764 | public void onDescriptorRead(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid, byte[] value) throws android.os.RemoteException {
765 |
766 | }
767 |
768 |
769 | public void onDescriptorWrite(String address, int status, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid) throws android.os.RemoteException {
770 |
771 | }
772 |
773 |
774 | public void onNotify(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value) throws android.os.RemoteException {
775 |
776 | }
777 |
778 |
779 | public void onClientConnParamsChanged(String address, int interval, int status) throws android.os.RemoteException{
780 |
781 | }
782 |
783 | }
784 | }
785 |
786 | }
--------------------------------------------------------------------------------