├── LICENSE
├── README.md
├── app
├── assets
│ └── test.pdf
├── build.gradle
├── mk.sh
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── aidl
│ ├── android
│ │ └── media
│ │ │ ├── AttributionSourceState.aidl
│ │ │ ├── AudioAttributesInternal.aidl
│ │ │ ├── AudioClient.aidl
│ │ │ ├── AudioConfigBase.aidl
│ │ │ ├── AudioContentType.aidl
│ │ │ ├── AudioFormat.aidl
│ │ │ ├── AudioSourceType.aidl
│ │ │ ├── AudioUsage.aidl
│ │ │ ├── CreateRecordRequest.aidl
│ │ │ ├── CreateRecordResponse.aidl
│ │ │ └── SharedFileRegion.aidl
│ └── com
│ │ └── ifma
│ │ └── cmpt
│ │ └── demo
│ │ ├── IBinderTest.aidl
│ │ └── IBinderTestCallback.aidl
│ ├── java
│ └── com
│ │ └── ifma
│ │ └── cmpt
│ │ └── demo
│ │ ├── DemoApplication.java
│ │ ├── DemoComponentFactory.java
│ │ ├── FakeApplication.java
│ │ ├── NativeCall.java
│ │ ├── main
│ │ ├── ConsoleActivity.java
│ │ ├── MainActivity.java
│ │ ├── MainProvider.java
│ │ ├── MainReceiver.java
│ │ └── MainService.java
│ │ ├── module
│ │ ├── ClassDumper.java
│ │ ├── ClipboadData.java
│ │ ├── Consts.java
│ │ ├── LauncherMonitor.java
│ │ └── PackageDumper.java
│ │ ├── sub
│ │ ├── DocumentReceiverActivity.java
│ │ ├── SingleProvider.java
│ │ ├── SubActivity.java
│ │ ├── SubPermissionProvider.java
│ │ ├── SubProvider.java
│ │ ├── SubReceiver.java
│ │ └── SubService.java
│ │ └── test
│ │ ├── FireyerAccessibilityCase.java
│ │ ├── FireyerCaseConsts.java
│ │ ├── FireyerDeviceModelCase.java
│ │ ├── FireyerDevicePolicyManagerCase.java
│ │ ├── FireyerPackageCase.java
│ │ ├── FireyerRuntimeCase.java
│ │ └── FireyerStackCase.java
│ └── res
│ ├── drawable-hdpi
│ ├── activity.png
│ └── ic_launcher.png
│ ├── drawable
│ ├── list_item_bg_single_selected.xml
│ ├── list_item_bg_single_selector.xml
│ ├── list_item_bg_single_unselected.xml
│ └── welcome.png
│ ├── layout
│ ├── activity_console.xml
│ ├── activity_main.xml
│ ├── activity_sub.xml
│ ├── activity_test.xml
│ └── dialog_input.xml
│ ├── mipmap-hdpi
│ └── ic_launcher.png
│ ├── mipmap-mdpi
│ └── ic_launcher.png
│ ├── mipmap-xhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── mipmap-xxxhdpi
│ └── ic_launcher.png
│ ├── raw
│ └── testraw.txt
│ ├── values
│ ├── booleans.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── integers.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── test_provider.xml
├── build.gradle
├── cmpt-cocollider
├── build.gradle
├── mk.sh
├── pom.json
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── ifma
│ │ └── cmpt
│ │ └── cocollider
│ │ └── CoColliderManager.java
│ └── mk.sh
├── cmpt-fireyer
├── build.gradle
├── mk.sh
├── pom.json
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── ifma
│ │ └── cmpt
│ │ └── fireyer
│ │ ├── FireyerManager.java
│ │ ├── FireyerNative.java
│ │ └── FireyerUtils.java
│ ├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── CMakeLists.txt
│ ├── inc
│ │ ├── arch.h
│ │ ├── assembly-arm.h
│ │ ├── assembly-arm64.h
│ │ ├── assembly.h
│ │ └── fireyer_native.h
│ └── src
│ │ ├── fireyer_main.cpp
│ │ └── fireyer_native.cpp
│ └── mk.sh
├── cocollider.py
├── files
├── default.gradle
└── fireyer.keystore
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── img
├── 1.png
├── fireyer.svg
└── thanks.png
├── mk.py
├── proguard-rules.pro
└── settings.gradle
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 iofomo
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ## 说明
13 |
14 | `Fire` + `Eye` = `Fireyer`(火眼),`Fireyer`项目是我们在做虚拟化沙箱产品过程中的内部副产品。目的是为了校验我们的虚拟化环境构建是否存在漏洞。在内部作为我们产品的黑白检测工具应用,可以保障我们的每次更新的产品质量,提升开发效率。对于开发沙箱,虚拟化等相关场景产品的伙伴也可以提升开发效率,快速验证功能稳定性。`Fireyer`的检测项还在不断完善中,后续会持续同步更新。
15 |
16 | 已有的检测项:
17 |
18 | - 签名校验
19 | - 完整性校验
20 | - 属性校验
21 | - 运行内存校验
22 | - 本地数据校验
23 | - `API`权限校验
24 | - `HooK`校验
25 | - 注入校验
26 |
27 | 更详细的检测项,请查看我们的博客文章: [【Fireyer】一款Android平台环境检测应用](https://www.iofomo.com/blog/fireyer) 。
28 |
29 | 如果你也喜欢`Fireyer`,别忘了给我们点个星。
30 |
31 | ## 感谢小伙伴们
32 |
33 | 
34 |
35 | ## 许可
36 |
37 | This project is licensed under the terms of the `MIT` license. See the [LICENSE](LICENSE) file.
38 |
39 | > This project and all tools are open source under the MIT license, which means you have full access to the source code and can modify it to fit your own needs.
40 |
--------------------------------------------------------------------------------
/app/assets/test.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iofomo/fireyer/05b26b41c381a198ddfd7a6f9fa2d6ec694be9f1/app/assets/test.pdf
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply from: '../files/default.gradle'
3 |
4 | android {
5 | def globalConfig = rootProject.extensions.getByName("ext")
6 | buildToolsVersion globalConfig.getAt("androidBuildToolsVersion")
7 | compileSdkVersion globalConfig.getAt("androidCompileSdkVersion")
8 |
9 | defaultConfig {
10 | applicationId "com.ifma.cmpt.demo.fireyer"
11 | minSdkVersion globalConfig.getAt("androidMinSdkVersion")
12 | targetSdkVersion globalConfig.getAt("androidTargetSdkVersion")
13 | versionCode 3 // used in FireyerPackageCase.doCheckApplication(...)
14 | versionName "1.0.3" // used in FireyerPackageCase.doCheckApplication(...)
15 |
16 | testInstrumentationRunner globalConfig.getAt("testInstrumentationRunner")
17 |
18 | javaCompileOptions {
19 | annotationProcessorOptions {
20 | includeCompileClasspath = true
21 | }
22 | }
23 | // ndk {
24 | // abiFilters "armeabi-v7a", "arm64-v8a"
25 | // }
26 | }
27 |
28 | sourceSets {
29 | main {
30 | assets.srcDirs = ['assets']
31 | jniLibs.srcDirs = ['lib']
32 | aidl.srcDirs = ['src/main/aidl']
33 | }
34 | }
35 |
36 | signingConfigs {
37 | debug {
38 | storeFile file('../files/fireyer.keystore')
39 | storePassword 'e99c85dc41111f82f7c3290fc87c42bd'
40 | keyAlias 'ifmafireyer'
41 | keyPassword 'e99c85dc41111f82f7c3290fc87c42bd'
42 | }
43 | release {
44 | storeFile file('../files/fireyer.keystore')
45 | storePassword 'e99c85dc41111f82f7c3290fc87c42bd'
46 | keyAlias 'ifmafireyer'
47 | keyPassword 'e99c85dc41111f82f7c3290fc87c42bd'
48 | }
49 | }
50 |
51 | buildTypes {
52 | debug {
53 | minifyEnabled false
54 | jniDebuggable true
55 | signingConfig signingConfigs.debug
56 | }
57 | release {
58 | minifyEnabled false
59 | signingConfig signingConfigs.release
60 | // proguardFiles getDefaultProguardFile('proguard-android.txt'), '../proguard-rules.pro'
61 | // consumerProguardFiles '../proguard-rules.pro'
62 | }
63 | }
64 |
65 | compileOptions {
66 | sourceCompatibility JavaVersion.VERSION_1_8
67 | targetCompatibility JavaVersion.VERSION_1_8
68 | }
69 | }
70 |
71 | repositories {
72 | flatDir {
73 | dirs '../libs'
74 | }
75 | }
76 |
77 | dependencies {
78 | implementation fileTree(dir: 'libs', include: ['*.jar'])
79 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
80 |
81 | implementation 'androidx.appcompat:appcompat:1.0.0'
82 | implementation 'androidx.legacy:legacy-support-v4:1.0.0'
83 | implementation 'androidx.startup:startup-runtime:1.0.0'
84 |
85 | // add module depend
86 | implementation project(':cmpt-fireyer')
87 | implementation project(':cmpt-cocollider')
88 |
89 | // add maven depend
90 | implementation (name: 'cmpt-utils', ext: 'aar')
91 | implementation (name: 'cmpt-testin', ext: 'aar')
92 | }
93 |
--------------------------------------------------------------------------------
/app/mk.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | # @ date: 2020.07.27 17:19
4 | #
5 |
6 | set -u
7 | set -e
8 |
9 | LOCAL_PATH=`pwd`
10 | OUT_PATH=$1
11 | BUILD_TYPE=$2
12 | MODULE_NAME=$3
13 |
14 | # ----------------------------------------------------------------
15 | # pre
16 | # ----------------------------------------------------------------
17 | rm -rf libs
18 | if [ -d "$OUT_PATH/libs" ] ; then
19 | cp -rf $OUT_PATH/libs ./
20 | fi
21 |
22 | # ----------------------------------------------------------------
23 | # build
24 | # ----------------------------------------------------------------
25 | cd ..
26 | if [ $BUILD_TYPE = debug ] ; then
27 | ./gradlew :$MODULE_NAME:assembleDebug
28 | else
29 | ./gradlew :$MODULE_NAME:assembleRelease
30 | fi
31 | cd -
32 |
33 | # ----------------------------------------------------------------
34 | # build end
35 | # ----------------------------------------------------------------
36 | cp -f $LOCAL_PATH/build/outputs/apk/$BUILD_TYPE/*.apk $OUT_PATH/$MODULE_NAME.apk
37 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
38 |
39 |
40 |
41 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
122 |
123 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
178 |
179 |
180 |
181 |
188 |
189 |
190 |
194 |
195 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AttributionSourceState.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2021 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | /**
20 | * Payload for the {@link AttributionSource} class needed to interoperate
21 | * with different languages.
22 | *
23 | * {@hide}
24 | */
25 | parcelable AttributionSourceState {
26 | /** The PID that is accessing the permission protected data. */
27 | int pid = -1;
28 | /** The UID that is accessing the permission protected data. */
29 | int uid = -1;
30 | /** The package that is accessing the permission protected data. */
31 | String packageName;
32 | /** The attribution tag of the app accessing the permission protected data. */
33 | String attributionTag;
34 | /** Unique token for that source. */
35 | IBinder token;
36 | /** Permissions that should be considered revoked regardless if granted. */
37 | String[] renouncedPermissions;
38 | /** The next app to receive the permission protected data. */
39 | // TODO: We use an array as a workaround - the C++ backend doesn't
40 | // support referring to the parcelable as it expects ctor/dtor
41 | AttributionSourceState[] next;
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioAttributesInternal.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | import android.media.AudioContentType;
20 | import android.media.AudioSourceType;
21 | import android.media.AudioUsage;
22 |
23 | /**
24 | * The "Internal" suffix of this type name is to disambiguate it from the
25 | * android.media.AudioAttributes SDK type.
26 | * {@hide}
27 | */
28 | parcelable AudioAttributesInternal {
29 | AudioContentType contentType;
30 | AudioUsage usage;
31 | AudioSourceType source;
32 | // Bitmask, indexed by AudioFlag.
33 | int flags;
34 | String tags; /* UTF8 */
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioClient.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | import android.media.AttributionSourceState;
20 |
21 | /**
22 | * {@hide}
23 | */
24 | parcelable AudioClient {
25 | /** Interpreted as pid_t. */
26 | int clientTid;
27 | AttributionSourceState attributionSource;
28 | }
29 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioConfigBase.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | import android.media.AudioFormat;
20 |
21 | /**
22 | * {@hide}
23 | */
24 | parcelable AudioConfigBase {
25 | int sampleRate;
26 | /** Interpreted as audio_channel_mask_t. */
27 | int channelMask;
28 | AudioFormat format;
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioContentType.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package android.media;
17 |
18 | @Backing(type="int")
19 | enum AudioContentType {
20 | UNKNOWN = 0,
21 | SPEECH = 1,
22 | MUSIC = 2,
23 | MOVIE = 3,
24 | SONIFICATION = 4,
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioFormat.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | // This file has been semi-automatically generated using hidl2aidl from its counterpart in
18 | // hardware/interfaces/audio/common/5.0/types.hal
19 |
20 | package android.media;
21 |
22 | /**
23 | * Audio format is a 32-bit word that consists of:
24 | * main format field (upper 8 bits)
25 | * sub format field (lower 24 bits).
26 | *
27 | * The main format indicates the main codec type. The sub format field indicates
28 | * options and parameters for each format. The sub format is mainly used for
29 | * record to indicate for instance the requested bitrate or profile. It can
30 | * also be used for certain formats to give informations not present in the
31 | * encoded audio stream (e.g. octet alignement for AMR).
32 | *
33 | * {@hide}
34 | */
35 | @Backing(type="int")
36 | enum AudioFormat {
37 | INVALID = 0xFFFFFFFF,
38 | DEFAULT = 0,
39 | PCM = 0x00000000,
40 | MP3 = 0x01000000,
41 | AMR_NB = 0x02000000,
42 | AMR_WB = 0x03000000,
43 | AAC = 0x04000000,
44 | /**
45 | * Deprecated, Use AAC_HE_V1
46 | */
47 | HE_AAC_V1 = 0x05000000,
48 | /**
49 | * Deprecated, Use AAC_HE_V2
50 | */
51 | HE_AAC_V2 = 0x06000000,
52 | VORBIS = 0x07000000,
53 | OPUS = 0x08000000,
54 | AC3 = 0x09000000,
55 | E_AC3 = 0x0A000000,
56 | DTS = 0x0B000000,
57 | DTS_HD = 0x0C000000,
58 | /**
59 | * IEC61937 is encoded audio wrapped in 16-bit PCM.
60 | */
61 | IEC61937 = 0x0D000000,
62 | DOLBY_TRUEHD = 0x0E000000,
63 | EVRC = 0x10000000,
64 | EVRCB = 0x11000000,
65 | EVRCWB = 0x12000000,
66 | EVRCNW = 0x13000000,
67 | AAC_ADIF = 0x14000000,
68 | WMA = 0x15000000,
69 | WMA_PRO = 0x16000000,
70 | AMR_WB_PLUS = 0x17000000,
71 | MP2 = 0x18000000,
72 | QCELP = 0x19000000,
73 | DSD = 0x1A000000,
74 | FLAC = 0x1B000000,
75 | ALAC = 0x1C000000,
76 | APE = 0x1D000000,
77 | AAC_ADTS = 0x1E000000,
78 | SBC = 0x1F000000,
79 | APTX = 0x20000000,
80 | APTX_HD = 0x21000000,
81 | AC4 = 0x22000000,
82 | LDAC = 0x23000000,
83 | /**
84 | * Dolby Metadata-enhanced Audio Transmission
85 | */
86 | MAT = 0x24000000,
87 | AAC_LATM = 0x25000000,
88 | CELT = 0x26000000,
89 | APTX_ADAPTIVE = 0x27000000,
90 | LHDC = 0x28000000,
91 | LHDC_LL = 0x29000000,
92 | APTX_TWSP = 0x2A000000,
93 | /**
94 | * Deprecated
95 | */
96 | MAIN_MASK = 0xFF000000,
97 | SUB_MASK = 0x00FFFFFF,
98 | /**
99 | * Subformats
100 | */
101 | PCM_SUB_16_BIT = 0x1,
102 | PCM_SUB_8_BIT = 0x2,
103 | PCM_SUB_32_BIT = 0x3,
104 | PCM_SUB_8_24_BIT = 0x4,
105 | PCM_SUB_FLOAT = 0x5,
106 | PCM_SUB_24_BIT_PACKED = 0x6,
107 | MP3_SUB_NONE = 0x0,
108 | AMR_SUB_NONE = 0x0,
109 | AAC_SUB_MAIN = 0x1,
110 | AAC_SUB_LC = 0x2,
111 | AAC_SUB_SSR = 0x4,
112 | AAC_SUB_LTP = 0x8,
113 | AAC_SUB_HE_V1 = 0x10,
114 | AAC_SUB_SCALABLE = 0x20,
115 | AAC_SUB_ERLC = 0x40,
116 | AAC_SUB_LD = 0x80,
117 | AAC_SUB_HE_V2 = 0x100,
118 | AAC_SUB_ELD = 0x200,
119 | AAC_SUB_XHE = 0x300,
120 | VORBIS_SUB_NONE = 0x0,
121 | E_AC3_SUB_JOC = 0x1,
122 | MAT_SUB_1_0 = 0x1,
123 | MAT_SUB_2_0 = 0x2,
124 | MAT_SUB_2_1 = 0x3,
125 | // TODO(ytai): Aliases not currently supported in AIDL - can inline the values.
126 | // /**
127 | // * Aliases
128 | // *
129 | // *
130 | // * note != AudioFormat.ENCODING_PCM_16BIT
131 | // */
132 | // PCM_16_BIT = (PCM | PCM_SUB_16_BIT),
133 | // /**
134 | // * note != AudioFormat.ENCODING_PCM_8BIT
135 | // */
136 | // PCM_8_BIT = (PCM | PCM_SUB_8_BIT),
137 | // PCM_32_BIT = (PCM | PCM_SUB_32_BIT),
138 | // PCM_8_24_BIT = (PCM | PCM_SUB_8_24_BIT),
139 | // PCM_FLOAT = (PCM | PCM_SUB_FLOAT),
140 | // PCM_24_BIT_PACKED = (PCM | PCM_SUB_24_BIT_PACKED),
141 | // AAC_MAIN = (AAC | AAC_SUB_MAIN),
142 | // AAC_LC = (AAC | AAC_SUB_LC),
143 | // AAC_SSR = (AAC | AAC_SUB_SSR),
144 | // AAC_LTP = (AAC | AAC_SUB_LTP),
145 | // AAC_HE_V1 = (AAC | AAC_SUB_HE_V1),
146 | // AAC_SCALABLE = (AAC | AAC_SUB_SCALABLE),
147 | // AAC_ERLC = (AAC | AAC_SUB_ERLC),
148 | // AAC_LD = (AAC | AAC_SUB_LD),
149 | // AAC_HE_V2 = (AAC | AAC_SUB_HE_V2),
150 | // AAC_ELD = (AAC | AAC_SUB_ELD),
151 | // AAC_XHE = (AAC | AAC_SUB_XHE),
152 | // AAC_ADTS_MAIN = (AAC_ADTS | AAC_SUB_MAIN),
153 | // AAC_ADTS_LC = (AAC_ADTS | AAC_SUB_LC),
154 | // AAC_ADTS_SSR = (AAC_ADTS | AAC_SUB_SSR),
155 | // AAC_ADTS_LTP = (AAC_ADTS | AAC_SUB_LTP),
156 | // AAC_ADTS_HE_V1 = (AAC_ADTS | AAC_SUB_HE_V1),
157 | // AAC_ADTS_SCALABLE = (AAC_ADTS | AAC_SUB_SCALABLE),
158 | // AAC_ADTS_ERLC = (AAC_ADTS | AAC_SUB_ERLC),
159 | // AAC_ADTS_LD = (AAC_ADTS | AAC_SUB_LD),
160 | // AAC_ADTS_HE_V2 = (AAC_ADTS | AAC_SUB_HE_V2),
161 | // AAC_ADTS_ELD = (AAC_ADTS | AAC_SUB_ELD),
162 | // AAC_ADTS_XHE = (AAC_ADTS | AAC_SUB_XHE),
163 | // E_AC3_JOC = (E_AC3 | E_AC3_SUB_JOC),
164 | // MAT_1_0 = (MAT | MAT_SUB_1_0),
165 | // MAT_2_0 = (MAT | MAT_SUB_2_0),
166 | // MAT_2_1 = (MAT | MAT_SUB_2_1),
167 | // AAC_LATM_LC = (AAC_LATM | AAC_SUB_LC),
168 | // AAC_LATM_HE_V1 = (AAC_LATM | AAC_SUB_HE_V1),
169 | // AAC_LATM_HE_V2 = (AAC_LATM | AAC_SUB_HE_V2),
170 | }
171 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioSourceType.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package android.media;
17 |
18 | /**
19 | * {@hide}
20 | */
21 | @Backing(type="int")
22 | enum AudioSourceType {
23 | INVALID = -1,
24 | DEFAULT = 0,
25 | MIC = 1,
26 | VOICE_UPLINK = 2,
27 | VOICE_DOWNLINK = 3,
28 | VOICE_CALL = 4,
29 | CAMCORDER = 5,
30 | VOICE_RECOGNITION = 6,
31 | VOICE_COMMUNICATION = 7,
32 | REMOTE_SUBMIX = 8,
33 | UNPROCESSED = 9,
34 | VOICE_PERFORMANCE = 10,
35 | ECHO_REFERENCE = 1997,
36 | FM_TUNER = 1998,
37 | /**
38 | * A low-priority, preemptible audio source for for background software
39 | * hotword detection. Same tuning as VOICE_RECOGNITION.
40 | * Used only internally by the framework.
41 | */
42 | HOTWORD = 1999,
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/AudioUsage.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package android.media;
17 |
18 | /**
19 | * {@hide}
20 | */
21 | @Backing(type="int")
22 | enum AudioUsage {
23 | UNKNOWN = 0,
24 | MEDIA = 1,
25 | VOICE_COMMUNICATION = 2,
26 | VOICE_COMMUNICATION_SIGNALLING = 3,
27 | ALARM = 4,
28 | NOTIFICATION = 5,
29 | NOTIFICATION_TELEPHONY_RINGTONE = 6,
30 | NOTIFICATION_COMMUNICATION_REQUEST = 7,
31 | NOTIFICATION_COMMUNICATION_INSTANT = 8,
32 | NOTIFICATION_COMMUNICATION_DELAYED = 9,
33 | NOTIFICATION_EVENT = 10,
34 | ASSISTANCE_ACCESSIBILITY = 11,
35 | ASSISTANCE_NAVIGATION_GUIDANCE = 12,
36 | ASSISTANCE_SONIFICATION = 13,
37 | GAME = 14,
38 | VIRTUAL_SOURCE = 15,
39 | ASSISTANT = 16,
40 | CALL_ASSISTANT = 17,
41 | EMERGENCY = 1000,
42 | SAFETY = 1001,
43 | VEHICLE_STATUS = 1002,
44 | ANNOUNCEMENT = 1003,
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/CreateRecordRequest.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | import android.media.AudioAttributesInternal;
20 | import android.media.AudioClient;
21 | import android.media.AudioConfigBase;
22 |
23 | /**
24 | * CreateRecordRequest contains all input arguments sent by AudioRecord to AudioFlinger
25 | * when calling createRecord() including arguments that will be updated by AudioFlinger
26 | * and returned in CreateRecordResponse object.
27 | *
28 | * {@hide}
29 | */
30 | parcelable CreateRecordRequest {
31 | AudioAttributesInternal attr;
32 | AudioConfigBase config;
33 | AudioClient clientInfo;
34 | /** Interpreted as audio_unique_id_t. */
35 | int riid;
36 | int maxSharedAudioHistoryMs;
37 | /** Bitmask, indexed by AudioInputFlags. */
38 | int flags;
39 | long frameCount;
40 | long notificationFrameCount;
41 | /** Interpreted as audio_port_handle_t. */
42 | int selectedDeviceId;
43 | int sessionId;
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/CreateRecordResponse.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | import android.media.SharedFileRegion;
20 |
21 | /**
22 | * CreateRecordResponse contains all output arguments returned by AudioFlinger to AudioRecord
23 | * when calling createRecord() including arguments that were passed as I/O for update by
24 | * CreateRecordRequest.
25 | *
26 | * {@hide}
27 | */
28 | parcelable CreateRecordResponse {
29 | /** Bitmask, indexed by AudioInputFlags. */
30 | int flags;
31 | long frameCount;
32 | long notificationFrameCount;
33 | /** Interpreted as audio_port_handle_t. */
34 | int selectedDeviceId;
35 | int sessionId;
36 | int sampleRate;
37 | /** Interpreted as audio_io_handle_t. */
38 | int inputId;
39 | SharedFileRegion cblk;
40 | SharedFileRegion buffers;
41 | /** Interpreted as audio_port_handle_t. */
42 | int portId;
43 | /** The newly created record. */
44 | IBinder audioRecord;
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/aidl/android/media/SharedFileRegion.aidl:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package android.media;
18 |
19 | /**
20 | * A shared file region.
21 | *
22 | * This type contains the required information to share a region of a file between processes over
23 | * AIDL.
24 | * An instance of this type represents a valid FD. For representing a null SharedFileRegion, use a
25 | * @nullable SharedFileRegion.
26 | * Primarily, this is intended for shared memory blocks.
27 | *
28 | * @hide
29 | */
30 | parcelable SharedFileRegion {
31 | /** File descriptor of the region. Must be valid. */
32 | ParcelFileDescriptor fd;
33 | /** Offset, in bytes within the file of the start of the region. Must be non-negative. */
34 | long offset;
35 | /** Size, in bytes of the memory region. Must be non-negative. */
36 | long size;
37 | /** Whether the region is writeable. */
38 | boolean writeable;
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/aidl/com/ifma/cmpt/demo/IBinderTest.aidl:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo;
2 |
3 | import android.media.CreateRecordResponse;
4 | import android.media.CreateRecordRequest;
5 |
6 | interface IBinderTest {
7 | int callBinderTest1(String a, IBinder c, int d);
8 | int callBinderTest2(int a, IBinder b, String c);
9 | int callBinderTest(String a, String b, IBinder c, int d, String e, IBinder f, String g);
10 | CreateRecordResponse createRecord(in CreateRecordRequest request);
11 | }
12 |
--------------------------------------------------------------------------------
/app/src/main/aidl/com/ifma/cmpt/demo/IBinderTestCallback.aidl:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo;
2 |
3 | interface IBinderTestCallback {
4 | int handleBinderTestCallback(int a);
5 | }
6 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/DemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | import com.ifma.cmpt.demo.main.MainReceiver;
7 | import com.ifma.cmpt.demo.module.LauncherMonitor;
8 | import com.ifma.cmpt.demo.test.FireyerRuntimeCase;
9 | import com.ifma.cmpt.demo.test.FireyerStackCase;
10 | import com.ifma.cmpt.fireyer.FireyerManager;
11 | import com.ifma.cmpt.testin.env.TstEnv;
12 | import com.ifma.cmpt.utils.ReflectUtils;
13 |
14 | public class DemoApplication extends Application {
15 | private final static String TAG = "DemoApplication";
16 |
17 | @Override
18 | protected void attachBaseContext(Context base) {
19 | super.attachBaseContext(base);
20 | FireyerRuntimeCase.sDemoApplicationABC = true;
21 | FireyerRuntimeCase.sHiddenApi = FireyerManager.checkHiddenAPI();
22 | FireyerStackCase.dumpStackForApplication_attachBaseContext();
23 | TstEnv.init(this);
24 | MainReceiver.register(base);
25 | // dumpClassLoader(getClassLoader());
26 | LauncherMonitor.init();
27 |
28 | clearServiceManager();
29 | // TstClassPrinter.printStub("android.content.IContentProvider");
30 | // TstClassPrinter.printStubByCodes("android.content.pm.IPackageManager", 179);
31 | }
32 |
33 | public static void clearServiceManager() {
34 | Class> cls = ReflectUtils.findClass("android.os.ServiceManager");
35 | ReflectUtils.setStaticFieldValue(cls, "sServiceManager", null);
36 | }
37 |
38 | @Override
39 | public void onCreate() {
40 | super.onCreate();
41 | FireyerRuntimeCase.sDemoApplicationCreate = true;
42 | FireyerStackCase.dumpStackForApplication_onCreate();
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/DemoComponentFactory.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo;
2 |
3 | import android.app.Activity;
4 | import android.app.AppComponentFactory;
5 | import android.app.Application;
6 | import android.app.Service;
7 | import android.content.BroadcastReceiver;
8 | import android.content.ContentProvider;
9 | import android.content.Intent;
10 | import android.content.pm.ApplicationInfo;
11 | import android.text.TextUtils;
12 |
13 | import com.ifma.cmpt.demo.test.FireyerPackageCase;
14 | import com.ifma.cmpt.demo.test.FireyerRuntimeCase;
15 | import com.ifma.cmpt.demo.test.FireyerStackCase;
16 | import com.ifma.cmpt.testin.module.TstRunner;
17 |
18 | public class DemoComponentFactory extends AppComponentFactory {
19 |
20 | public ClassLoader instantiateClassLoader(ClassLoader cl, ApplicationInfo aInfo) {
21 | FireyerRuntimeCase.sAppComponentFactoryInitClass = true;
22 | FireyerPackageCase.doCheckApplicationInfo("ACF ", aInfo);
23 | FireyerPackageCase.dumpPackageInfo(aInfo);
24 | FireyerStackCase.dumpStackForInstantiateClassLoader();
25 | return cl;
26 | }
27 |
28 | public Application instantiateApplication(ClassLoader cl, String className)
29 | throws InstantiationException, IllegalAccessException, ClassNotFoundException {
30 | FireyerRuntimeCase.sAppComponentFactoryInitApp = true;
31 | FireyerStackCase.dumpStackForInstantiateApplication();
32 | TstRunner.print("instantiateApplication", "com.ifma.cmpt.demo.FakeApplication".equals(className));
33 | return (Application) cl.loadClass("com.ifma.cmpt.demo.DemoApplication").newInstance();
34 | }
35 |
36 | public Activity instantiateActivity(ClassLoader cl, String className, Intent intent)
37 | throws InstantiationException, IllegalAccessException, ClassNotFoundException {
38 | FireyerRuntimeCase.sAppComponentFactoryInitActivity = true;
39 | FireyerStackCase.dumpStackForInstantiateActivity();
40 | TstRunner.print("instantiateActivity",
41 | TextUtils.equals("com.ifma.cmpt.demo.main.MainActivity", className) ||
42 | TextUtils.equals("com.ifma.cmpt.demo.main.ConsoleActivity", className) ||
43 | TextUtils.equals("com.ifma.cmpt.demo.sub.SubActivity", className)
44 | );
45 | return (Activity) cl.loadClass(className).newInstance();
46 | }
47 |
48 | public BroadcastReceiver instantiateReceiver(ClassLoader cl, String className, Intent intent)
49 | throws InstantiationException, IllegalAccessException, ClassNotFoundException {
50 | TstRunner.print("instantiateReceiver",
51 | TextUtils.equals("com.ifma.cmpt.demo.main.MainReceiver", className) ||
52 | TextUtils.equals("com.ifma.cmpt.demo.sub.SubReceiver", className)
53 | );
54 | return (BroadcastReceiver) cl.loadClass(className).newInstance();
55 | }
56 |
57 | public Service instantiateService(ClassLoader cl, String className, Intent intent)
58 | throws InstantiationException, IllegalAccessException, ClassNotFoundException {
59 | TstRunner.print("instantiateService",
60 | TextUtils.equals("com.ifma.cmpt.demo.main.MainService", className) ||
61 | TextUtils.equals("com.ifma.cmpt.demo.sub.SubService", className)
62 | );
63 | return (Service) cl.loadClass(className).newInstance();
64 | }
65 |
66 | public ContentProvider instantiateProvider(ClassLoader cl, String className)
67 | throws InstantiationException, IllegalAccessException, ClassNotFoundException {
68 | FireyerRuntimeCase.sAppComponentFactoryInitProvider = true;
69 | TstRunner.print("instantiateProvider",
70 | TextUtils.equals("com.ifma.cmpt.demo.main.MainProvider", className) ||
71 | TextUtils.equals("com.ifma.cmpt.demo.sub.SubProvider", className) ||
72 | TextUtils.equals("com.ifma.cmpt.demo.sub.SubPermissionProvider", className) ||
73 | TextUtils.equals("androidx.startup.InitializationProvider", className)
74 | );
75 | FireyerStackCase.dumpStackForInstantiateProvider();
76 | return (ContentProvider) cl.loadClass(className).newInstance();
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/FakeApplication.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 |
6 | import com.ifma.cmpt.demo.test.FireyerRuntimeCase;
7 |
8 | public class FakeApplication extends Application {
9 |
10 | @Override
11 | protected void attachBaseContext(Context base) {
12 | super.attachBaseContext(base);
13 | FireyerRuntimeCase.sFakeApplicationABC = false;
14 | }
15 |
16 | @Override
17 | public void onCreate() {
18 | super.onCreate();
19 | FireyerRuntimeCase.sFakeApplicationCreate = false;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/NativeCall.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo;
2 |
3 | public class NativeCall {
4 | static {
5 | try {
6 | System.loadLibrary("fireyer-jni");
7 | } catch (Throwable e) {
8 | e.printStackTrace();
9 | }
10 | }
11 |
12 | public native Object callNative(int i, Object args);
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/main/ConsoleActivity.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.main;
2 |
3 | import android.app.Activity;
4 | import android.app.AlertDialog;
5 | import android.content.BroadcastReceiver;
6 | import android.content.DialogInterface;
7 | import android.graphics.Color;
8 | import android.os.Bundle;
9 | import android.os.Handler;
10 | import android.text.SpannableStringBuilder;
11 | import android.text.Spanned;
12 | import android.text.TextUtils;
13 | import android.text.method.ScrollingMovementMethod;
14 | import android.text.style.ForegroundColorSpan;
15 | import android.view.LayoutInflater;
16 | import android.view.View;
17 | import android.view.WindowManager;
18 | import android.widget.EditText;
19 | import android.widget.ScrollView;
20 | import android.widget.TextView;
21 |
22 | import com.ifma.cmpt.demo.fireyer.R;
23 | import com.ifma.cmpt.demo.module.ClipboadData;
24 | import com.ifma.cmpt.demo.test.FireyerCaseConsts;
25 | import com.ifma.cmpt.demo.test.FireyerPackageCase;
26 | import com.ifma.cmpt.demo.test.FireyerRuntimeCase;
27 | import com.ifma.cmpt.testin.env.TstConsts;
28 | import com.ifma.cmpt.testin.env.TstHandler;
29 | import com.ifma.cmpt.testin.module.TstRunner;
30 |
31 | import java.util.List;
32 | import java.util.concurrent.CopyOnWriteArrayList;
33 |
34 | public class ConsoleActivity extends Activity {
35 | private TextView mTextConsole;
36 | private ScrollView mScrollView;
37 | protected BroadcastReceiver mBR;
38 | private Handler mHandler = null;
39 |
40 | @Override
41 | public void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | setContentView(R.layout.activity_console);
44 | initView();
45 | initData();
46 |
47 | if (FireyerCaseConsts.isVirtualMode()) {
48 | showInputDialog();// got info from clipboard
49 | } else {
50 | initTest();
51 | }
52 | }
53 |
54 | protected void initView() {
55 | mHandler = new Handler();
56 | mTextConsole = (TextView) findViewById(R.id.console);
57 | mScrollView = (ScrollView) findViewById(R.id.scrollView);
58 | mTextConsole.setMovementMethod(ScrollingMovementMethod.getInstance());
59 | }
60 |
61 | protected void initData() {
62 | addMessage("Console started ...");
63 | if (FireyerCaseConsts.isSourceMode()) {
64 | addMessage("From source env");
65 | } else if (FireyerCaseConsts.isKonkerMode()) {
66 | addMessage("From konker env");
67 | } else if (FireyerCaseConsts.isPackerMode()) {
68 | addMessage("From packer env");
69 | }
70 | }
71 |
72 | protected void initTest() {
73 | final Bundle args = getIntent().getExtras();
74 | if (!TextUtils.equals(TstConsts.VALUE_UNITTEST, args.getString(TstConsts.KEY_TYPE))) return;
75 |
76 | TstRunner.runTest(args, new TstRunner.ITstPrinter() {
77 | @Override
78 | public void onTstStart() {
79 | if (FireyerCaseConsts.isVirtualMode()) {
80 | int cnt = ClipboadData.loadFromClipboard(getApplicationContext());
81 | addMessage("Load info from Clipboard: " + cnt);
82 | } else {
83 | FireyerRuntimeCase.dumpThread();
84 | FireyerPackageCase.dumpApk(getApplicationContext());
85 | }
86 | }
87 |
88 | @Override
89 | public void onTstDone() {
90 | if (FireyerCaseConsts.isSourceMode()) {
91 | mHandler.postDelayed(new Runnable() {
92 | @Override
93 | public void run() {
94 | showInputDialog();
95 | }
96 | }, 1000);
97 | }
98 | addMessage("[Info] passed " + TstRunner.getPassedCaseCount() + " cases");
99 | addMessage("[Info] failed " + TstRunner.getFailedCaseCount() + " cases");
100 | }
101 |
102 | @Override
103 | public void onTstPrint(String s) {
104 | addMessage(s);
105 | }
106 | });
107 | }
108 |
109 | private final List mMsgList = new CopyOnWriteArrayList<>();
110 |
111 | private Runnable mMsgRunner = new Runnable() {
112 | @Override
113 | public void run() {
114 | doPrint();
115 | }
116 | };
117 |
118 | protected void addMessage(String msg) {
119 | mMsgList.add(msg);
120 | if (TstHandler.isMainThread()) {
121 | doPrint();
122 | } else {
123 | TstHandler.postUi(mMsgRunner);
124 | }
125 | }
126 |
127 | public static final String TEXT_PRE_OK = "[O";
128 | public static final String TEXT_PRE_FAIL = "[F";
129 | public static final String TEXT_PRE_ERROR = "[E";
130 | public static final String TEXT_PRE_WARN = "[W";
131 | public static final String TEXT_PRE_INFO = "[I";
132 |
133 | private synchronized void doPrint() {
134 | while (!mMsgList.isEmpty()) {
135 | doPrint(mMsgList.remove(0));
136 | }
137 | }
138 |
139 | private void doPrint(String msg) {
140 | if (TextUtils.isEmpty(msg)) {
141 | mTextConsole.append("\n");
142 | return;
143 | }
144 | try {
145 | SpannableStringBuilder builder = new SpannableStringBuilder(msg);
146 | if (msg.startsWith(TEXT_PRE_OK)) {
147 | builder.setSpan(new ForegroundColorSpan(0xAA00FF00), 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
148 | } else if (msg.startsWith(TEXT_PRE_FAIL) || msg.startsWith(TEXT_PRE_ERROR)) {
149 | builder.setSpan(new ForegroundColorSpan(0xAAFF0000), 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
150 | } else if (msg.startsWith(TEXT_PRE_WARN)) {
151 | builder.setSpan(new ForegroundColorSpan(Color.YELLOW), 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
152 | } else if (msg.startsWith(TEXT_PRE_INFO)) {
153 | builder.setSpan(new ForegroundColorSpan(Color.WHITE), 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
154 | } else {
155 | builder.setSpan(new ForegroundColorSpan(0xAA000000), 0, msg.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
156 | }
157 | mTextConsole.append(builder);
158 | mTextConsole.append("\n");
159 | int offset = mTextConsole.getMeasuredHeight() - mScrollView.getMeasuredHeight();
160 | if (offset < 0) {
161 | mScrollView.scrollTo(0, 0);
162 | } else {
163 | mScrollView.scrollTo(0, offset);
164 | }
165 | } catch (Throwable e) {
166 | e.printStackTrace();
167 | }
168 | }
169 |
170 | protected void onDestroy() {
171 | if (null != mBR) {
172 | try {
173 | unregisterReceiver(mBR);
174 | } catch (Throwable e) {
175 | e.printStackTrace();
176 | } finally {
177 | mBR = null;
178 | }
179 | }
180 | TstRunner.cancel();
181 | super.onDestroy();
182 | }
183 |
184 | private void showInputDialog() {
185 | LayoutInflater inflater = LayoutInflater.from(this);
186 | final View dialogView = inflater.inflate(R.layout.dialog_input, null);
187 | final EditText editText = dialogView.findViewById(R.id.editText);
188 |
189 | final AlertDialog dialog = new AlertDialog.Builder(this)
190 | .setTitle("Got Focus")
191 | .setView(dialogView)
192 | .create();
193 |
194 | dialog.setOnShowListener(new DialogInterface.OnShowListener() {
195 | @Override
196 | public void onShow(DialogInterface dialogInterface) {
197 | editText.requestFocus();
198 | dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
199 |
200 | mHandler.postDelayed(new Runnable() {
201 | @Override
202 | public void run() {
203 | if (FireyerCaseConsts.isVirtualMode()) {
204 | ClipboadData.loadFromClipboard(getApplicationContext());
205 | initTest();// got info, then start to test
206 | } else {
207 | ClipboadData.saveToClipboard(getApplicationContext());
208 | }
209 | if (dialog.isShowing()) {
210 | dialog.dismiss();
211 | }
212 | }
213 | }, 1000);
214 | }
215 | });
216 |
217 | dialog.show();
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/main/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.main;
2 |
3 | import android.app.Activity;
4 | import android.app.PendingIntent;
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.IntentFilter;
9 | import android.hardware.usb.UsbAccessory;
10 | import android.hardware.usb.UsbDevice;
11 | import android.hardware.usb.UsbManager;
12 | import android.net.Uri;
13 | import android.os.Bundle;
14 | import android.view.View;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import androidx.core.content.FileProvider;
19 |
20 | import com.ifma.cmpt.demo.fireyer.BuildConfig;
21 | import com.ifma.cmpt.demo.fireyer.R;
22 | import com.ifma.cmpt.demo.test.FireyerCaseConsts;
23 | import com.ifma.cmpt.demo.test.FireyerStackCase;
24 | import com.ifma.cmpt.testin.env.TstConsts;
25 | import com.ifma.cmpt.testin.module.TstPermissionGrantor;
26 | import com.ifma.cmpt.utils.AssetsUtils;
27 |
28 | import java.io.File;
29 | import java.util.HashMap;
30 | import java.util.Iterator;
31 | //import com.ifma.cmpt.fireyer.FireyerNative;
32 |
33 |
34 | public class MainActivity extends Activity implements View.OnClickListener {
35 | private static final String TAG = "MainActivity";
36 |
37 | @Override
38 | public void onCreate(Bundle savedInstanceState) {
39 | FireyerStackCase.dumpStackForActivity_onCreate();
40 | super.onCreate(savedInstanceState);
41 | setContentView(R.layout.activity_main);
42 | initView();
43 | TstPermissionGrantor.grant(this);
44 | initData();
45 | }
46 |
47 | private void initView() {
48 | TextView text = (TextView) findViewById(R.id.main_version);
49 | text.setText("v" + BuildConfig.VERSION_NAME + "(" + BuildConfig.VERSION_CODE + ")");
50 | View v;
51 | v = findViewById(R.id.item_unittest_source);
52 | // v.setVisibility(View.GONE);
53 | v.setOnClickListener(this);
54 |
55 | v = findViewById(R.id.item_unittest_konker);
56 | // v.setVisibility(View.GONE);
57 | v.setOnClickListener(this);
58 |
59 | v = findViewById(R.id.item_shared);
60 | // v.setVisibility(View.GONE);
61 | v.setOnClickListener(this);
62 | }
63 |
64 | public void onClick(View v) {
65 | switch (v.getId()) {
66 | case R.id.item_unittest_source:
67 | {
68 | FireyerCaseConsts.setMode(FireyerCaseConsts.MODE_SOURCE);
69 | Intent i = new Intent(this, ConsoleActivity.class);
70 | i.putExtra(TstConsts.KEY_TYPE, TstConsts.VALUE_UNITTEST);
71 | startActivity(i);
72 | } break;
73 | case R.id.item_unittest_konker:
74 | {
75 | FireyerCaseConsts.setMode(FireyerCaseConsts.MODE_KONKER);
76 | Intent i = new Intent(this, ConsoleActivity.class);
77 | i.putExtra(TstConsts.KEY_TYPE, TstConsts.VALUE_UNITTEST);
78 | startActivity(i);
79 | } break;
80 | case R.id.item_shared:
81 | {
82 | File file = new File(getExternalCacheDir(), "test.pdf");
83 | if (AssetsUtils.copyAsset(getApplicationContext(), "test.pdf", file.getAbsolutePath())) {
84 | openFileWithInstalledApps(getApplicationContext(), file, "application/pdf");
85 | } else {
86 | Toast.makeText(getApplicationContext(), "test.pdf export fail", Toast.LENGTH_SHORT).show();
87 | }
88 | } break;
89 | default: break;
90 | }
91 | }
92 |
93 | public void openFileWithInstalledApps(Context context, File file, String mimeType) {
94 | Uri uri = FileProvider.getUriForFile(context, context.getPackageName() + ".SubProvider", file);
95 | Intent intent = new Intent(Intent.ACTION_VIEW);
96 | intent.setDataAndType(uri, mimeType);
97 | intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|Intent.FLAG_ACTIVITY_NEW_TASK);
98 | context.startActivity(intent);
99 | }
100 |
101 | private void initData() {
102 | initUsbPermission();
103 | // TstHandler.post(new Runnable() {
104 | // @Override
105 | // public void run() {
106 | // }
107 | // });
108 | }
109 |
110 | private static final String ACTION_USB_PERMISSION_DEVICE = "com.ifma.cmpt.demo.fireyer.USB_PERMISSION_DEVICE";
111 | private static final String ACTION_USB_PERMISSION_ACCESSORY = "com.ifma.cmpt.demo.fireyer.USB_PERMISSION_ACCESSORY";
112 |
113 | protected void initUsbPermission() {
114 | IntentFilter filter = new IntentFilter();
115 | filter.addAction(ACTION_USB_PERMISSION_DEVICE);
116 | filter.addAction(ACTION_USB_PERMISSION_ACCESSORY);
117 | registerReceiver(usbReceiver, filter);
118 |
119 | PendingIntent intent = PendingIntent.getBroadcast(this, 0,
120 | new Intent(ACTION_USB_PERMISSION_DEVICE), 0
121 | );
122 |
123 | UsbManager usbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
124 | HashMap deviceList = usbManager.getDeviceList();
125 | if (null != deviceList && 0 < deviceList.size()) {
126 | Iterator deviceIterator = deviceList.values().iterator();
127 | while (deviceIterator.hasNext()) {
128 | UsbDevice device = deviceIterator.next();
129 | boolean has = usbManager.hasPermission(device);
130 | Toast.makeText(getApplicationContext(), "usb-dev-pmt: " + has, Toast.LENGTH_SHORT).show();
131 | if (!has) {
132 | usbManager.requestPermission(device, intent);
133 | }
134 | }
135 | }
136 |
137 | intent = PendingIntent.getBroadcast(this, 0,
138 | new Intent(ACTION_USB_PERMISSION_ACCESSORY), 0
139 | );
140 | UsbAccessory[] accs = usbManager.getAccessoryList();
141 | if (null != accs && 0 < accs.length) {
142 | for (UsbAccessory acc: accs) {
143 | boolean has = usbManager.hasPermission(acc);
144 | Toast.makeText(getApplicationContext(), "usb-acc-pmt: " + has, Toast.LENGTH_SHORT).show();
145 | if (!has) {
146 | usbManager.requestPermission(acc, intent);
147 | }
148 | }
149 | }
150 | }
151 |
152 | private final BroadcastReceiver usbReceiver = new BroadcastReceiver() {
153 | public void onReceive(Context context, Intent intent) {
154 | String action = intent.getAction();
155 | if (ACTION_USB_PERMISSION_DEVICE.equals(action)) {
156 | UsbDevice dev = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
157 | if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
158 | Toast.makeText(getApplicationContext(), "usb-dev: " + dev.getSerialNumber(), Toast.LENGTH_SHORT).show();
159 | } else {
160 | Toast.makeText(getApplicationContext(), "usb-dev: fail", Toast.LENGTH_SHORT).show();
161 | }
162 | } else if (ACTION_USB_PERMISSION_ACCESSORY.equals(action)) {
163 | UsbAccessory acc = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
164 | if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
165 | Toast.makeText(getApplicationContext(), "usb-acc: " + acc.getSerial(), Toast.LENGTH_SHORT).show();
166 | } else {
167 | Toast.makeText(getApplicationContext(), "usb-dev: fail", Toast.LENGTH_SHORT).show();
168 | }
169 | }
170 | }
171 | };
172 |
173 | protected void onDestroy() {
174 | unregisterReceiver(usbReceiver);
175 | super.onDestroy();
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/main/MainProvider.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.main;
2 |
3 | import com.ifma.cmpt.cocollider.CoColliderManager;
4 | import com.ifma.cmpt.demo.module.ClassDumper;
5 | import com.ifma.cmpt.demo.module.Consts;
6 | import com.ifma.cmpt.demo.module.PackageDumper;
7 | import com.ifma.cmpt.demo.test.FireyerStackCase;
8 | import com.ifma.cmpt.testin.env.TstLogger;
9 | import android.content.ContentProvider;
10 | import android.content.ContentValues;
11 | import android.database.Cursor;
12 | import android.net.Uri;
13 | import android.os.Bundle;
14 | import android.text.TextUtils;
15 |
16 |
17 | public class MainProvider extends ContentProvider {
18 | private static final String TAG = MainProvider.class.getSimpleName();
19 |
20 | @Override
21 | public boolean onCreate() {
22 | FireyerStackCase.dumpStackForProvider_onCreate();
23 | TstLogger.e(TAG, "onCreate");
24 | getContext().getExternalCacheDir();
25 | return false;
26 | }
27 |
28 | @Override
29 | public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
30 | TstLogger.e(TAG, "query");
31 | return null;
32 | }
33 |
34 | @Override
35 | public String getType(Uri uri) {
36 | TstLogger.e(TAG, "getType");
37 | return "MainProvider";
38 | }
39 |
40 | @Override
41 | public Uri insert(Uri uri, ContentValues values) {
42 | TstLogger.e(TAG, "insert");
43 | return null;
44 | }
45 |
46 | @Override
47 | public int delete(Uri uri, String selection, String[] selectionArgs) {
48 | TstLogger.e(TAG, "delete");
49 | return 0;
50 | }
51 |
52 | @Override
53 | public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
54 | TstLogger.e(TAG, "update");
55 | return 0;
56 | }
57 |
58 | public Bundle call(String authority, String method, String arg, Bundle extras) {
59 | Bundle replyData = new Bundle();
60 | try {
61 | switch (method) {
62 | case "dump":
63 | handleDumpEvent(arg, extras, replyData);
64 | break;
65 | case "method":// for test case
66 | handleTestCaseEvent(authority, arg, extras, replyData);
67 | break;
68 | case "coco":
69 | CoColliderManager.handleCallEvent(getContext(), extras, replyData);
70 | break;
71 | default: break;
72 | }
73 | } catch (Throwable e) {
74 | e.printStackTrace();
75 | replyData.putInt(Consts.KEY_CODE, -9);
76 | replyData.putString(Consts.KEY_MSG, e.getMessage());
77 | }
78 | return replyData;
79 | }
80 |
81 | private void handleDumpEvent(String type, Bundle inData, Bundle replyData) throws Throwable {
82 | switch (type) {
83 | case "class":
84 | ClassDumper.handleCallEvent(getContext(), inData, replyData);
85 | break;
86 | case "pkg":
87 | PackageDumper.handleCallEvent(getContext(), inData, replyData);
88 | break;
89 | default: break;
90 | }
91 | }
92 |
93 | private void handleTestCaseEvent(String authority, String arg, Bundle extras, Bundle replyData) {
94 | boolean succ = false;
95 | do {
96 | if (!TextUtils.equals(authority, "com.ifma.cmpt.demo.fireyer.MainProvider")) break;
97 | if (!TextUtils.equals(arg, "arg")) break;
98 | if (1 != extras.size()) break;
99 | if (100 != extras.getInt("call")) break;
100 | succ = true;
101 | } while (false);
102 | replyData.putBoolean("call", succ);
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/main/MainReceiver.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.main;
2 |
3 | import com.ifma.cmpt.testin.env.TstConsts;
4 | import com.ifma.cmpt.testin.env.TstLogger;
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.IntentFilter;
9 |
10 |
11 | public class MainReceiver extends BroadcastReceiver {
12 | private static final String TAG = MainReceiver.class.getSimpleName();
13 |
14 | public static void register(Context ctx) {
15 | ctx.registerReceiver(new MainReceiver(), new IntentFilter(TstConsts.getActionReceiver()));
16 | }
17 |
18 | @Override
19 | public void onReceive(Context context, Intent intent) {
20 | TstLogger.bundle(TAG, intent.getExtras());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/main/MainService.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.main;
2 |
3 | import android.app.Service;
4 |
5 | import com.ifma.cmpt.testin.env.TstHandler;
6 | import com.ifma.cmpt.testin.env.TstLogger;
7 | import com.ifma.cmpt.utils.Logger;
8 | import com.ifma.cmpt.utils.MessengerUtils;
9 |
10 | import android.content.Intent;
11 | import android.os.Bundle;
12 | import android.os.IBinder;
13 | import android.os.Message;
14 |
15 | public class MainService extends Service implements MessengerUtils.IServiceCallback {
16 | private static final String TAG = MainService.class.getSimpleName();
17 |
18 | private MessengerUtils.ServiceMessenger mMessenger;
19 | public void onCreate() {
20 | super.onCreate();
21 | mMessenger = new MessengerUtils.ServiceMessenger(this, TstHandler.getLooper());
22 | }
23 |
24 | @Override
25 | public Message handleMessage(Message msg) {
26 | if (Logger.D) Logger.d(TAG, "handleMessage: " + msg.toString());
27 |
28 | final Bundle inData = msg.getData();
29 | final Bundle replyData = new Bundle();
30 | do {
31 | if (msg.what != inData.getInt("msg")) break;
32 | if (1 != inData.size()) break;
33 | replyData.putInt("call", msg.what);
34 | } while (false);
35 |
36 | Message outMessage = Message.obtain(null, msg.what);
37 | outMessage.setData(replyData);
38 | return outMessage;
39 | }
40 |
41 | @Override
42 | public IBinder onBind(Intent intent) {
43 | return mMessenger.getBinder();
44 | }
45 |
46 | @Override
47 | public void onDestroy() {
48 | super.onDestroy();
49 | }
50 |
51 | @Override
52 | public int onStartCommand(Intent intent, int flags, int startId) {
53 | TstLogger.d(TAG, intent.toString());
54 | return START_NOT_STICKY;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/module/ClassDumper.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.module;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.text.TextUtils;
6 |
7 | import com.ifma.cmpt.testin.utils.TstClassPrinter;
8 | import com.ifma.cmpt.utils.FileUtils;
9 | import com.ifma.cmpt.utils.Logger;
10 |
11 | import java.io.File;
12 | import java.io.FileOutputStream;
13 | import java.io.OutputStream;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | public class ClassDumper {
18 | private static final String TAG = "ClassDumper";
19 |
20 | public static void handleCallEvent(Context ctx, Bundle inData, Bundle replyData) {
21 | final String fileOrClass = inData.getString(Consts.KEY_IN_ARG1);
22 | final String outPath = inData.getString(Consts.KEY_IN_ARG2);
23 | final String mode = inData.getString(Consts.KEY_IN_ARG3);
24 |
25 | int failCnt;
26 | if (fileOrClass.startsWith("/") || fileOrClass.startsWith("\\")) {
27 | List lines = FileUtils.readLines(new File(fileOrClass));
28 | if (null == lines) {
29 | replyData.putInt(Consts.KEY_CODE, -1);
30 | replyData.putString(Consts.KEY_MSG, "Error: file not found " + fileOrClass);
31 | return;
32 | }
33 | if (lines.isEmpty()) {
34 | replyData.putInt(Consts.KEY_CODE, -2);
35 | replyData.putString(Consts.KEY_MSG, "Error: empty file");
36 | return;
37 | }
38 | failCnt = doParse(lines, outPath, mode);
39 | } else {
40 | failCnt = doParseClass(fileOrClass, outPath, mode) ? 0 : 1;
41 | }
42 | if (failCnt == 0) {
43 | replyData.putInt(Consts.KEY_CODE, 0);
44 | replyData.putString(Consts.KEY_MSG, "success");
45 | } else {
46 | replyData.putInt(Consts.KEY_CODE, failCnt);
47 | replyData.putString(Consts.KEY_MSG, "Error: " + failCnt + " class dump fail");
48 | }
49 | }
50 | private static final String TARGET_PRE = "target,";
51 | private static final String ONEWAY_PRE = "oneway,";
52 | public static int doParse(List lines, String outPath, String mode) {
53 | int failCnt = 0;
54 | for (String line : lines) {
55 | if (line.startsWith(TARGET_PRE)) {
56 | line = line.substring(TARGET_PRE.length());
57 | int pos = line.indexOf(',');
58 | if (!doParseClass(line.substring(pos+1), outPath, mode)) {
59 | failCnt += 1;
60 | }
61 | } else if (line.startsWith(ONEWAY_PRE)) {
62 | line = line.substring(TARGET_PRE.length());
63 | int pos = line.indexOf(',');
64 | if (!doParseClass(line.substring(pos+1), outPath, mode)) {
65 | failCnt += 1;
66 | }
67 | }
68 | }
69 | return failCnt;
70 | }
71 |
72 | private static boolean doParseClass(String classLine, String outPath, String mode) {
73 | List targetValues = new ArrayList();
74 | String[] items = classLine.split(",");
75 | if (!TextUtils.equals(mode, "all")) {
76 | if (null != items && items.length >= 2) {
77 | for (int i = 1; i < items.length; ++i) {
78 | targetValues.add(Integer.valueOf(items[i]));
79 | }
80 | }
81 | }
82 |
83 | int pos = items[0].lastIndexOf('.');
84 | String pathName = 0 < pos ? items[0].substring(0, pos) : "";
85 | String className = 0 < pos ? items[0].substring(pos+1) : items[0];
86 |
87 | OutputStream os = null;
88 | File file = new File(outPath + File.separator + className + ".java");
89 | FileUtils.mkParentDirs(file);
90 | try {
91 | os = new FileOutputStream(file);
92 | DumperWriter writer = new DumperWriter(pathName, className, os);
93 | TstClassPrinter.setCallback(writer);
94 |
95 | if (targetValues.isEmpty()) {
96 | TstClassPrinter.printStub(items[0]);
97 | } else {
98 | TstClassPrinter.printStub(items[0], targetValues);
99 | }
100 | if (0 < writer.getCount()) {
101 | writer.writeTailer();
102 | return true;
103 | }
104 |
105 | DumperInfoWriter infoWriter = new DumperInfoWriter(os);
106 | TstClassPrinter.printClass(items[0], true, infoWriter);
107 | if (0 < infoWriter.getCount()) {
108 | return true;
109 | }
110 | } catch (Throwable e) {
111 | e.printStackTrace();
112 | } finally {
113 | FileUtils.closeQuietly(os);
114 | }
115 | file.delete();
116 |
117 | Logger.e(TAG, "dump fail: " + items[0]);
118 | return false;
119 | }
120 |
121 | static class DumperWriter implements TstClassPrinter.IClassPrinter {
122 | private int mCount = 0;
123 | private final String mPathName, mClassName;
124 | private final OutputStream mStream;
125 |
126 | public DumperWriter(String pathName, String clsName, OutputStream stream) {
127 | mPathName = pathName;
128 | mClassName = clsName;
129 | mStream = stream;
130 | }
131 |
132 | public int getCount() { return mCount; }
133 |
134 | public void writeHeader() {
135 | try {
136 | mStream.write(("package " + mPathName + ";").getBytes());
137 | mStream.write("\n\n".getBytes());
138 | mStream.write(("interface " + mClassName + " {").getBytes());
139 | } catch (Throwable e) {
140 | e.printStackTrace();
141 | }
142 | }
143 |
144 | public void writeTailer() throws Throwable {
145 | mStream.write("\n}".getBytes());
146 | }
147 |
148 | @Override
149 | public void onTstClassPrinter(TstClassPrinter.TRANSACTION_Item item) {
150 | if (mCount <= 0) {
151 | writeHeader();
152 | }
153 | mCount += 1;
154 | try {
155 | mStream.write(("\n " + item.funcName + ";// " + item.code).getBytes());
156 | } catch (Throwable e) {
157 | e.printStackTrace();
158 | }
159 | }
160 | }
161 |
162 | static class DumperInfoWriter implements TstClassPrinter.IClassInfoPrinter {
163 | private int mCount = 0;
164 | private final OutputStream mStream;
165 |
166 | public DumperInfoWriter(OutputStream stream) {
167 | mStream = stream;
168 | }
169 |
170 | public int getCount() { return mCount; }
171 |
172 | @Override
173 | public void onTstClassInfoPrinter(String line) {
174 | mCount += 1;
175 | try {
176 | mStream.write("\n".getBytes());
177 | mStream.write(line.getBytes());
178 | } catch (Throwable e) {
179 | e.printStackTrace();
180 | }
181 | }
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/module/ClipboadData.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.module;
2 |
3 | import android.content.ClipData;
4 | import android.content.ClipboardManager;
5 | import android.content.Context;
6 | import android.text.TextUtils;
7 |
8 | import java.util.ArrayList;
9 | import java.util.HashMap;
10 | import java.util.List;
11 | import java.util.Map;
12 |
13 | public class ClipboadData {
14 | public static final int TYPE_InstantiateClassLoader = 1;
15 | public static final int TYPE_InstantiateApplication = 2;
16 | public static final int TYPE_InstantiateActivity = 3;
17 | public static final int TYPE_Application_attachBaseContext = 4;
18 | public static final int TYPE_Application_onCreate = 5;
19 | public static final int TYPE_Provider_onCreate = 6;
20 | public static final int TYPE_Activity_onCreate = 7;
21 | public static final int TYPE_Thread_Jvm = 8;
22 | public static final int TYPE_Thread_Native = 9;
23 | public static final int TYPE_InstantiateProvider = 10;
24 | public static final int TYPE_Source_APK = 11;
25 | public static final int TYPE_Package_Info = 12;
26 | public static final int TYPE_Usb_Info = 13;
27 |
28 | private static final String PRE = "tst:";
29 | private static final Map> sCache = new HashMap<>();
30 |
31 | public static void set(int type, String[] ss) {
32 | if (null == ss) return;
33 | List vv = new ArrayList<>();
34 | for (String s : ss) vv.add(s);
35 | sCache.put(type, vv);
36 | }
37 |
38 | public static void set(int type, List v) {
39 | sCache.put(type, v);
40 | }
41 |
42 | public static List get(int type) {
43 | return sCache.get(type);
44 | }
45 |
46 | public static void saveToClipboard(Context ctx) {
47 | StringBuilder sb = new StringBuilder();
48 | sb.append(PRE);
49 |
50 | List ss;
51 | for (Map.Entry> e : sCache.entrySet()) {
52 | ss = e.getValue();
53 | Integer key = e.getKey();
54 | for (String s : ss) {
55 | sb.append(key).append('=').append(s).append('\n');
56 | }
57 | }
58 | writeToClipboard(ctx, sb.toString());
59 | }
60 |
61 | public static int loadFromClipboard(Context ctx) {
62 | sCache.clear();
63 | String s = readFromClipboard(ctx);
64 | if (TextUtils.isEmpty(s) || !s.startsWith(PRE)) return 0;
65 |
66 | s = s.substring(PRE.length());
67 | String[] lines = s.split("\n");
68 |
69 | int pos;
70 | Integer lastKey = 0;
71 | List ss = new ArrayList<>();
72 | for (String item : lines) {
73 | pos = item.indexOf('=');
74 | if (pos <= 0) continue;
75 | Integer key = Integer.valueOf(item.substring(0, pos));
76 | if (key != lastKey) {
77 | if (0 < lastKey && 0 < ss.size()) {
78 | sCache.put(lastKey, ss);
79 | ss = new ArrayList<>();
80 | }
81 | lastKey = key;
82 | }
83 | ss.add(item.substring(pos+1));
84 | }
85 | if (0 < lastKey && 0 < ss.size()) {
86 | sCache.put(lastKey, ss);
87 | }
88 | return sCache.size();
89 | }
90 |
91 | private static void writeToClipboard(Context ctx, String text) {
92 | ClipboardManager clipboard = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
93 | ClipData clip = ClipData.newPlainText("text", text);
94 | clipboard.setPrimaryClip(clip);
95 | }
96 |
97 | private static String readFromClipboard(Context ctx) {
98 | ClipboardManager clipboard = (ClipboardManager) ctx.getSystemService(Context.CLIPBOARD_SERVICE);
99 | ClipData clip = clipboard.getPrimaryClip();
100 | if (clip != null && clip.getItemCount() > 0) {
101 | ClipData.Item item = clip.getItemAt(0);
102 | return item.getText().toString();
103 | }
104 | return null;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/module/Consts.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.module;
2 |
3 | public final class Consts {
4 | public static final String KEY_IN_ARG1 = "key-in-arg1";
5 | public static final String KEY_IN_ARG2 = "key-in-arg2";
6 | public static final String KEY_IN_ARG3 = "key-in-arg3";
7 | public static final String KEY_IN_ARG4 = "key-in-arg4";
8 |
9 | public static final String KEY_OUT_ARG1 = "key-out-arg1";
10 | public static final String KEY_OUT_ARG2 = "key-out-arg2";
11 | public static final String KEY_CODE = "key-code";
12 | public static final String KEY_MSG = "key-msg";
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/java/com/ifma/cmpt/demo/module/LauncherMonitor.java:
--------------------------------------------------------------------------------
1 | package com.ifma.cmpt.demo.module;
2 |
3 | import android.content.pm.ActivityInfo;
4 | import android.content.pm.ProviderInfo;
5 | import android.content.pm.ServiceInfo;
6 | import android.os.Handler;
7 | import android.os.Message;
8 |
9 | import com.ifma.cmpt.demo.test.FireyerPackageCase;
10 | import com.ifma.cmpt.demo.test.FireyerRuntimeCase;
11 | import com.ifma.cmpt.fireyer.FireyerManager;
12 | import com.ifma.cmpt.utils.ActivityThreadUtils;
13 | import com.ifma.cmpt.utils.Logger;
14 | import com.ifma.cmpt.utils.ReflectUtils;
15 |
16 | import java.lang.reflect.Method;
17 | import java.util.List;
18 |
19 | public class LauncherMonitor implements Handler.Callback {
20 | private int LAUNCH_ACTIVITY = 0;
21 | private int RELAUNCH_ACTIVITY = 0;
22 | private int CREATE_SERVICE = 0;
23 | private int INSTALL_PROVIDER = 0;
24 | private int EXECUTE_TRANSACTION = 0;
25 |
26 | private static LauncherMonitor sSelf = null;
27 | public static void init() {
28 | if (sSelf == null) {
29 | sSelf = new LauncherMonitor();
30 | }
31 | sSelf.startMonitor();
32 | }
33 |
34 | public void startMonitor() {
35 | Object objH = ActivityThreadUtils.getAtH();
36 | try {
37 | FireyerRuntimeCase.sAT_H_Callback = FireyerManager.checkHCallback();
38 |
39 | Class> cls = objH.getClass();
40 | Integer val = (Integer)ReflectUtils.getStaticFieldValue(cls, "LAUNCH_ACTIVITY");
41 | if (null != val) {
42 | this.LAUNCH_ACTIVITY = val;
43 | }
44 |
45 | val = (Integer)ReflectUtils.getStaticFieldValue(cls, "RELAUNCH_ACTIVITY");
46 | if (null != val) {
47 | this.RELAUNCH_ACTIVITY = val;
48 | }
49 |
50 | val = (Integer)ReflectUtils.getStaticFieldValue(cls, "CREATE_SERVICE");
51 | if (null != val) {
52 | this.CREATE_SERVICE = val;
53 | }
54 |
55 | val = (Integer)ReflectUtils.getStaticFieldValue(cls, "INSTALL_PROVIDER");
56 | if (null != val) {
57 | this.INSTALL_PROVIDER = val;
58 | }
59 |
60 | val = (Integer)ReflectUtils.getStaticFieldValue(cls, "EXECUTE_TRANSACTION");
61 | if (null != val) {
62 | this.EXECUTE_TRANSACTION = val;
63 | }
64 | ReflectUtils.setFieldValue(objH, "mCallback", this);
65 | } catch (Throwable var7) {
66 | Logger.e(var7);
67 | }
68 | }
69 |
70 | @Override
71 | public boolean handleMessage(Message msg) {
72 | try {
73 | if (LAUNCH_ACTIVITY == msg.what || RELAUNCH_ACTIVITY == msg.what) {// ActivityThread$ActivityClientRecord
74 | ActivityInfo ai = (ActivityInfo) ReflectUtils.getFieldValue(msg.obj, "activityInfo");
75 | FireyerPackageCase.doTestActivityInfo("hcb ", ai, false);
76 | } else if (CREATE_SERVICE == msg.what) {// ActivityThread$CreateServiceData
77 | ServiceInfo info = (ServiceInfo) ReflectUtils.getFieldValue(msg.obj, "info");
78 | FireyerPackageCase.doTestServiceInfo("hcb ", info, false);
79 | } else if (INSTALL_PROVIDER == msg.what) {
80 | FireyerPackageCase.doTestProviderInfo("hcb ", (ProviderInfo)msg.obj, false);
81 | } else if (EXECUTE_TRANSACTION == msg.what) {// for 9.0
82 | Method m = ReflectUtils.getDeclaredMethod(msg.obj, "getCallbacks");
83 | List