diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
new file mode 100644
index 0000000..2682de5
--- /dev/null
+++ b/.github/workflows/android.yml
@@ -0,0 +1,47 @@
+name: Android CI
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+jobs:
+ build:
+
+ name: Build Release
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - name: set up JDK 11
+ uses: actions/setup-java@v3
+ with:
+ java-version: '11'
+ distribution: 'temurin'
+ cache: gradle
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Lint
+ run: ./gradlew trustdevice:lint
+
+ - name: Test
+ run: ./gradlew trustdevice:test
+
+ - name: Build library
+ run: ./gradlew trustdevice:assembleRelease
+
+ - name: Save library to artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ path: trustdevice/build/outputs/aar/*
+
+ - name: Build App
+ run: ./gradlew app:assembleRelease
+
+ - name: Save application to artifacts
+ uses: actions/upload-artifact@v2
+ with:
+ path: app/build/outputs/apk/release/*
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..4affdc1
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,90 @@
+name: Release
+
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+
+ release:
+ name: Create Release
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: checkout code
+ uses: actions/checkout@v3
+ - name: set up JDK 11
+ uses: actions/setup-java@v3
+ with:
+ java-version: '11'
+ distribution: 'temurin'
+ cache: gradle
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Lint
+ run: ./gradlew trustdevice:lint
+
+ - name: Test
+ run: ./gradlew trustdevice:test
+
+ - name: Build library
+ run: ./gradlew trustdevice:assembleRelease
+
+# - name: Save library to artifacts
+# uses: actions/upload-artifact@v2
+# with:
+# path: trustdevice/build/outputs/aar/*
+
+ - name: Build App
+ run: ./gradlew app:assembleRelease
+
+# - name: Save application to artifacts
+# uses: actions/upload-artifact@v3
+# with:
+# path: app/build/outputs/apk/release/*
+
+# - name: Download artifact
+# uses: actions/download-artifact@v3
+
+ - name: Display structure of downloaded files
+ run: ls -R
+
+ - name: Set release name
+ run: echo RELEASE_NAME=${GITHUB_REF} >> $GITHUB_ENV
+
+ - name: Create Release
+ id: create_release
+ uses: actions/create-release@v1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ tag_name: ${{ github.ref }}
+ release_name: ${{ env.RELEASE_NAME }}
+ body:
+ The first version of trustdevice-android library.
+ draft: false
+ prerelease: false
+
+ - name: Upload aar to release
+ uses: actions/upload-release-asset@v1.0.1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./trustdevice/build/outputs/aar/trustdevice-release.aar
+ asset_name: trustdevice-release.aar
+ # Common MIME types:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
+ asset_content_type: application/zip
+
+ - name: Upload apk to release
+ uses: actions/upload-release-asset@v1.0.1
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ with:
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
+ asset_path: ./app/build/outputs/apk/release/TrustDevice-release-1.0.0.apk
+ asset_name: TrustDevice-release-1.0.0.apk
+ # Common MIME types:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types
+ asset_content_type: application/zip
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f2b2a70
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/.gradle/
+/.idea/
+/build/
+local.properties
diff --git a/README.md b/README.md
index 2f08c68..a7daedd 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,203 @@
-# trustdevice-android
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# TrustDevice-Android
+A lightweight library for determining device uniqueness and risk identification.
+
+Create a device identifier based on basic device information.
+
+Will remain the same after uninstalling and reinstalling or clearing app data.
+
+## Quick start
+
+### 1. Add repository
+
+Add these lines to your `build.gradle`.
+```groovy
+allprojects {
+ repositories {
+ maven { url 'https://jitpack.io' }
+ }
+}
+```
+
+If your version of Gradle is 7 or newer, add these lines to your `settings.gradle`:
+```groovy
+repositories {
+ ...
+ maven { url 'https://jitpack.io' }
+ }
+```
+
+### 2. Add dependency
+
+Add these lines to `build.gradle` of a module.
+```groovy
+dependencies {
+ ...
+ implementation 'com.github.trustdecision:trustdevice-android:1.0.0'
+}
+```
+
+### 3. Get deviceInfo
+
+DeviceInfo contains device id, risk information and device details.
+
+#### 3.1. Option 1
+
+```java
+// initialization
+TDRisk.init(context);
+
+// usage
+JSONObject deviceInfo = TDRisk.getBlackbox();
+// Obtain deviceid and risk information through deviceInfo
+String deviceID = deviceInfo.optString("device_id");
+JSONObject deviceRisk = deviceInfo.optJSONObject("device_risk_label");
+JSONObject deviceDetail = deviceInfo.optJSONObject("device_detail");
+```
+
+`getBlackbox` method executes in the calling thread and takes time to execute.
+
+#### 3.1.2. Option 2
+
+```java
+TDRisk.Builder builder = new TDRisk.Builder();
+builder.callback(new TDRiskCallback() {
+ @Override
+ public void onEvent(JSONObject deviceInfo) {
+ // Obtain deviceid and risk information through deviceInfo
+ String deviceID = deviceInfo.optString("device_id");
+ JSONObject deviceRisk = deviceInfo.optJSONObject("device_risk_label");
+ JSONObject deviceDetail = deviceInfo.optJSONObject("device_detail");
+ }
+});
+TDRisk.initWithOptions(context, builder);
+```
+
+`callback` is in a sub-thread, please do not perform UI operations.
+
+## Data Sample
+
+```json
+{
+ "device_id": "E9BE9A73B4AEA5A94B36FABC0BF5AF302DC332E4BCB7D10F5F5F7B507DF2A782",
+ "device_risk_label": {
+ "root": "false",
+ "debug": "true",
+ "multiple": "false"
+ },
+ "device_detail": {
+ "abiType": "arm64-v8a,armeabi-v7a,armeabi",
+ "accessibilityEnabled": "0",
+ "adbEnabled": "1",
+ "allowMockLocation": "0",
+ "androidId": "5fa5f2bdc283000c",
+ "androidVersion": "13",
+ "appList": "com.trustdevice.android",
+ "availableMemory": "2981945344",
+ "availableStorage": "50888110080",
+ "batteryHealthStatus": "good",
+ "batteryLevel": "76",
+ "batteryStatus": "charging",
+ "batteryTemp": "230",
+ "batteryTotalCapacity": "2800.0",
+ "brand": "google",
+ "coresCount": "8",
+ "country": "CN",
+ "cpuHardware": "Qualcomm Technologies, Inc SM8150",
+ "cpuProcessor": "AArch64 Processor rev 14 (aarch64)",
+ "dataRoaming": "0",
+ "debug": "true",
+ "defaultInputMethod": "com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME",
+ "developmentSettingEnabled": "1",
+ "display": "TP1A.220624.014",
+ "filesAbsolutePath": "/data/user/0/com.trustdevice.android/files",
+ "fingerprint": "google/flame/flame:13/TP1A.220624.014/8819323:user/release-keys",
+ "gsfId": "",
+ "hardware": "flame",
+ "host": "abfarm-release-rbe-64-00043",
+ "httpProxy": "null",
+ "kernelVersion": "4.14.276-g8ae7b4ca8564-ab8715030",
+ "language": "zh",
+ "manufacturer": "Google",
+ "mediaDrmId": "A069CC34B11C17F1C390575C794166F83CDE53B0887D2F718EDC901ED337FDF4",
+ "model": "Pixel 4",
+ "packageName": "com.trustdevice.android",
+ "product": "flame",
+ "root": "false",
+ "screenBrightness": "63",
+ "screenOffTimeout": "30000",
+ "screenResolution": "1080x2280",
+ "sdkVersion": "33",
+ "sensorsInfo": "LSM6DSR Accelerometer:STMicro,LIS2MDL Magnetometer:STMicro,LSM6DSR Gyroscope:STMicro,TMD3702V Ambient Light Sensor:AMS",
+ "systemAppList": "com.google.android.networkstack.tethering,com.google.omadm.trigger",
+ "timezone": "中国标准时间",
+ "totalMemory": "5730922496",
+ "totalStorage": "53684973568",
+ "touchExplorationEnabled": "0",
+ "vbMetaDigest": "4ab46ec3675c5251b815ce36de607abdab29cd827ed3bd99a24bd828597a712a"
+ }
+}
+```
+
+## Open Source Features
+
+- Basic device ID, This identifier is stable, it will remain the same even after uninstalling and reinstalling your app. But it will be different after factory reset of the device.
+- Basic equipment information, which can be used for simple data analysis
+- Basic risk identification ability
+
+| RiskLabel | Risk Description |
+| --------- | ------------------------------------------------------------ |
+| root | Attackers will have higher privileges and can install many cheating software to affect the normal development of application business. |
+| debug | Applications can be modified by attackers at will, and the program will return unexpected values. |
+| multiple | Attackers can clone multiple app. |
+
+Full product comparison:
+
+| | Open Source | Pro |
+| ----------------------------- | ----------- | ---------------- |
+| 100% open source | yes | no |
+| Device ID | Basic | Extremely stable |
+| Device Risk Label | Basic | Extremely rich |
+| Device Details | Basic | Extremely rich |
+| IP Location | - | ✓ |
+| Device Risk Score | - | ✓ |
+| Environment Risk Evaluation | - | ✓ |
+| Fraud Tools Detection | - | ✓ |
+| Behavioral Activity Capturing | - | ✓ |
+
+## Pro Introduction
+
+....
+
+## TrustDevice Android Demo App
+
+Try the library features in the [TrustDevice Android Demo App](https://github.com/trustdecision/trustdevice-android/releases/download/1.0.0/TrustDevice-release-1.0.0.apk).
+
+## Android API support
+
+trustdevice-android supports API versions from 21 (Android 5.0) and higher.
+
+## License
+This library is MIT licensed. Copyright trustdecision, Inc. 2022.
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..b399252
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,54 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ namespace 'com.trustdevice.android'
+ compileSdk 33
+
+ defaultConfig {
+ applicationId "com.trustdevice.android"
+ minSdk 21
+ targetSdk 33
+ versionCode 1
+ versionName "1.0.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ signingConfigs {
+ release {
+ storeFile file("demo_release.jks")
+ storePassword 'TRUSTDEVICE'
+ keyAlias 'TRUSTDEVICE_KEY_ALIAS'
+ keyPassword 'TRUSTDEVICE'
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ signingConfig signingConfigs.release
+ }
+ }
+ applicationVariants.all { variant ->
+ variant.outputs.all {
+ outputFileName = "TrustDevice-${variant.name}-${variant.versionName}.apk"
+ }
+ }
+}
+
+dependencies {
+ // implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"])
+ implementation project(path: ':trustdevice')
+ implementation 'com.jakewharton:butterknife:10.2.3'
+ annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
+ implementation 'androidx.appcompat:appcompat:1.5.1'
+ implementation 'androidx.recyclerview:recyclerview:1.2.1'
+ implementation 'com.google.android.material:material:1.5.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.4'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
\ No newline at end of file
diff --git a/app/demo_release.jks b/app/demo_release.jks
new file mode 100644
index 0000000..e81819a
Binary files /dev/null and b/app/demo_release.jks differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/app/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java b/app/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..82cc327
--- /dev/null
+++ b/app/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package cn.tongdun.android;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.trustdevice.android", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..c27d4ee
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/cn/tongdun/android/MyApplication.java b/app/src/main/java/cn/tongdun/android/MyApplication.java
new file mode 100644
index 0000000..253c21d
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/MyApplication.java
@@ -0,0 +1,14 @@
+package cn.tongdun.android;
+
+
+import android.app.Application;
+
+import cn.tongdun.mobrisk.TDRisk;
+
+public class MyApplication extends Application {
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ TDRisk.init(this);
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/activity/MainActivity.java b/app/src/main/java/cn/tongdun/android/activity/MainActivity.java
new file mode 100644
index 0000000..50c2b70
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/activity/MainActivity.java
@@ -0,0 +1,110 @@
+package cn.tongdun.android.activity;
+
+import android.text.TextUtils;
+import android.util.Pair;
+
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.trustdevice.android.R;
+
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import butterknife.BindView;
+import cn.tongdun.android.adapter.DeviceModuleItemAdapter;
+import cn.tongdun.android.base.BaseActivity;
+import cn.tongdun.android.beans.DetailsItemBean;
+import cn.tongdun.android.beans.DeviceModuleItemBean;
+import cn.tongdun.mobrisk.TDRisk;
+import cn.tongdun.mobrisk.TDRiskCallback;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+import cn.tongdun.mobrisk.providers.applist.AppListProvider;
+import cn.tongdun.mobrisk.providers.battery.BatteryInfoProvider;
+import cn.tongdun.mobrisk.providers.build.BuildInfoProvider;
+import cn.tongdun.mobrisk.providers.cpu.CpuInfoProvider;
+import cn.tongdun.mobrisk.providers.device_id.DeviceIdProvider;
+import cn.tongdun.mobrisk.providers.memory.MemoryInfoProvider;
+import cn.tongdun.mobrisk.providers.risk.RiskInfoProvider;
+import cn.tongdun.mobrisk.providers.screen.ScreenInfoProvider;
+import cn.tongdun.mobrisk.providers.sensor.SensorInfoProvider;
+import cn.tongdun.mobrisk.providers.setting.SettingInfoProvider;
+
+public class MainActivity extends BaseActivity {
+
+ @BindView(R.id.device_info_container)
+ RecyclerView rvDeviceInfoContainer;
+ private DeviceModuleItemAdapter mAdapter;
+ private List mItemData = new ArrayList<>();
+
+ @Override
+ protected int getContentViewResId() {
+ return R.layout.activity_main;
+ }
+
+ @Override
+ protected void initData() {
+ createDeviceInfo();
+// TDRisk.Builder builder = new TDRisk.Builder();
+// builder.callback(new TDRiskCallback() {
+// @Override
+// public void onEvent(JSONObject deviceInfo) {
+// String deviceID = deviceInfo.optString("device_id");
+// JSONObject deviceRisk = deviceInfo.optJSONObject("device_risk_label");
+// JSONObject deviceDetail = deviceInfo.optJSONObject("device_detail");
+// }
+// });
+// TDRisk.initWithOptions(this, builder);
+ }
+
+ @Override
+ protected void initView() {
+ LinearLayoutManager manager = new LinearLayoutManager(this);
+ manager.setOrientation(GridLayoutManager.VERTICAL);
+ rvDeviceInfoContainer.setLayoutManager(manager);
+ mAdapter = new DeviceModuleItemAdapter(mItemData);
+ rvDeviceInfoContainer.setAdapter(mAdapter);
+ }
+
+ private void createDeviceInfo() {
+ JSONObject deviceInfo = TDRisk.getBlackbox();
+ createData(deviceInfo);
+ }
+
+ private void createData(JSONObject deviceInfo) {
+ createItemInfo(new DeviceIdProvider(deviceInfo));
+ createItemInfo(new RiskInfoProvider(deviceInfo));
+ createItemInfo(new BuildInfoProvider(deviceInfo));
+ createItemInfo(new ScreenInfoProvider(deviceInfo));
+ createItemInfo(new BatteryInfoProvider(deviceInfo));
+ createItemInfo(new SettingInfoProvider(deviceInfo));
+ createItemInfo(new CpuInfoProvider(deviceInfo));
+ createItemInfo(new MemoryInfoProvider(deviceInfo));
+ createItemInfo(new SensorInfoProvider(deviceInfo));
+ createAppList(new AppListProvider(deviceInfo));
+ }
+
+ private void createItemInfo(InfoProvider infoProvider) {
+ List detailsItemBeanList = new ArrayList<>();
+ for (Pair infos : infoProvider.getRawData()) {
+ detailsItemBeanList.add(new DetailsItemBean(infos.first, infos.second));
+ }
+ mItemData.add(new DeviceModuleItemBean(infoProvider.getProviderName(), detailsItemBeanList));
+ }
+
+ private void createAppList(InfoProvider appListProvider) {
+ for (Pair infos : appListProvider.getRawData()) {
+ List appListDetailsItemList = new ArrayList<>();
+ for (String appInfo : infos.second) {
+ if (TextUtils.isEmpty(appInfo)) {
+ continue;
+ }
+ appListDetailsItemList.add(new DetailsItemBean(appInfo, ""));
+ }
+ mItemData.add(new DeviceModuleItemBean(infos.first, appListDetailsItemList));
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/cn/tongdun/android/adapter/BaseRecyclerViewAdapter.java b/app/src/main/java/cn/tongdun/android/adapter/BaseRecyclerViewAdapter.java
new file mode 100644
index 0000000..b78efa5
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/adapter/BaseRecyclerViewAdapter.java
@@ -0,0 +1,75 @@
+package cn.tongdun.android.adapter;
+
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.List;
+
+/**
+ * @description: RecyclerView Adapter
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public abstract class BaseRecyclerViewAdapter extends RecyclerView.Adapter {
+
+ public List mData;
+
+ public BaseRecyclerViewAdapter(List data) {
+ this.mData = data;
+ }
+
+ public abstract int getLayoutId(int viewType);
+
+ @Override
+ public BaseViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ return BaseViewHolder.get(parent, getLayoutId(viewType));
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull BaseViewHolder holder, int position) {
+ convert(holder, mData.get(position), position);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mData.size();
+ }
+
+ public abstract void convert(BaseViewHolder holder, T data, int position);
+
+ static class BaseViewHolder extends RecyclerView.ViewHolder {
+ private SparseArray mViews;
+ private View mConvertView;
+
+ private BaseViewHolder(View v) {
+ super(v);
+ mConvertView = v;
+ mViews = new SparseArray<>();
+ }
+
+ public static BaseViewHolder get(ViewGroup parent, int layoutId) {
+ View convertView = LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false);
+ return new BaseViewHolder(convertView);
+ }
+
+ public T getView(int id) {
+ View v = mViews.get(id);
+ if (v == null) {
+ v = mConvertView.findViewById(id);
+ mViews.put(id, v);
+ }
+ return (T) v;
+ }
+
+ public void setText(int id, String value) {
+ TextView view = getView(id);
+ view.setText(value);
+ }
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/adapter/DetailsItemAdapter.java b/app/src/main/java/cn/tongdun/android/adapter/DetailsItemAdapter.java
new file mode 100644
index 0000000..0b83b02
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/adapter/DetailsItemAdapter.java
@@ -0,0 +1,39 @@
+package cn.tongdun.android.adapter;
+
+import android.text.TextUtils;
+import android.view.View;
+import android.widget.TextView;
+
+import com.trustdevice.android.R;
+import cn.tongdun.android.beans.DetailsItemBean;
+
+import java.util.List;
+
+/**
+ * @description: Details Item Adapter
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DetailsItemAdapter extends BaseRecyclerViewAdapter {
+
+ public DetailsItemAdapter(List data) {
+ super(data);
+ }
+
+ @Override
+ public int getLayoutId(int viewType) {
+ return R.layout.item_details;
+ }
+
+ @Override
+ public void convert(BaseViewHolder holder, DetailsItemBean data, int position) {
+ TextView name = holder.getView(R.id.tv_name);
+ name.setText(data.getName());
+ TextView value = holder.getView(R.id.tv_value);
+ if (TextUtils.isEmpty(data.getValue())) {
+ value.setVisibility(View.GONE);
+ } else {
+ value.setText(data.getValue());
+ }
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/adapter/DeviceModuleItemAdapter.java b/app/src/main/java/cn/tongdun/android/adapter/DeviceModuleItemAdapter.java
new file mode 100644
index 0000000..9215739
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/adapter/DeviceModuleItemAdapter.java
@@ -0,0 +1,59 @@
+package cn.tongdun.android.adapter;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.trustdevice.android.R;
+import cn.tongdun.android.beans.DeviceModuleItemBean;
+import cn.tongdun.android.view.DeviceDetailsItemView;
+
+import java.util.List;
+
+/**
+ * @description: Device Module RecyclerView Adapter
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DeviceModuleItemAdapter extends RecyclerView.Adapter {
+
+ private List mData;
+
+ public DeviceModuleItemAdapter(List data) {
+ mData = data;
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ DeviceDetailsItemView convertView = (DeviceDetailsItemView) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_device_module, parent, false);
+ return new ViewHolder(convertView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ DeviceModuleItemBean deviceModuleItemBean = mData.get(position);
+ if (position==0){
+ holder.deviceDetailsItemView.setExpanded(true);
+ }
+ holder.deviceDetailsItemView.setModuleName(deviceModuleItemBean.getModuleName());
+ holder.deviceDetailsItemView.setDescribe(deviceModuleItemBean.getDescribe());
+ holder.deviceDetailsItemView.setDetailsContainer(deviceModuleItemBean.getDetailsItemBeans());
+ }
+
+ @Override
+ public int getItemCount() {
+ return mData == null ? 0 : mData.size();
+ }
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ DeviceDetailsItemView deviceDetailsItemView;
+
+ public ViewHolder(@NonNull DeviceDetailsItemView itemView) {
+ super(itemView);
+ deviceDetailsItemView = itemView;
+ }
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/base/BaseActivity.java b/app/src/main/java/cn/tongdun/android/base/BaseActivity.java
new file mode 100644
index 0000000..b7eef49
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/base/BaseActivity.java
@@ -0,0 +1,45 @@
+package cn.tongdun.android.base;
+
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+
+
+/**
+ * @description: BaseActivity
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public abstract class BaseActivity extends AppCompatActivity {
+
+ private Unbinder mUnbinder;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(getContentViewResId());
+ getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
+ mUnbinder = ButterKnife.bind(this);
+ initData();
+ initView();
+ }
+
+ protected abstract int getContentViewResId();
+
+ protected abstract void initData();
+
+ protected abstract void initView();
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mUnbinder != null) {
+ mUnbinder.unbind();
+ }
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/beans/DetailsItemBean.java b/app/src/main/java/cn/tongdun/android/beans/DetailsItemBean.java
new file mode 100644
index 0000000..d868bdd
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/beans/DetailsItemBean.java
@@ -0,0 +1,32 @@
+package cn.tongdun.android.beans;
+
+/**
+ * @description: DetailsBean
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DetailsItemBean {
+ private String name;
+ private String value;
+
+ public DetailsItemBean(String name, String value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/beans/DeviceModuleItemBean.java b/app/src/main/java/cn/tongdun/android/beans/DeviceModuleItemBean.java
new file mode 100644
index 0000000..8a3694f
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/beans/DeviceModuleItemBean.java
@@ -0,0 +1,50 @@
+package cn.tongdun.android.beans;
+
+import java.util.List;
+
+/**
+ * @description: Device Module ItemBean
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DeviceModuleItemBean {
+
+ private String moduleName;
+ private String describe;
+ private List detailsItemBeans;
+
+ public DeviceModuleItemBean(String moduleName, List detailsItemBeans) {
+ this.moduleName = moduleName;
+ this.detailsItemBeans = detailsItemBeans;
+ }
+
+ public DeviceModuleItemBean(String moduleName, String describe, List detailsItemBeans) {
+ this.moduleName = moduleName;
+ this.describe = describe;
+ this.detailsItemBeans = detailsItemBeans;
+ }
+
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ public void setModuleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ public String getDescribe() {
+ return describe;
+ }
+
+ public void setDescribe(String describe) {
+ this.describe = describe;
+ }
+
+ public List getDetailsItemBeans() {
+ return detailsItemBeans;
+ }
+
+ public void setDetailsItemBeans(List detailsItemBeans) {
+ this.detailsItemBeans = detailsItemBeans;
+ }
+}
diff --git a/app/src/main/java/cn/tongdun/android/view/DeviceDetailsItemView.java b/app/src/main/java/cn/tongdun/android/view/DeviceDetailsItemView.java
new file mode 100644
index 0000000..243abc5
--- /dev/null
+++ b/app/src/main/java/cn/tongdun/android/view/DeviceDetailsItemView.java
@@ -0,0 +1,94 @@
+package cn.tongdun.android.view;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.recyclerview.widget.DividerItemDecoration;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.trustdevice.android.R;
+import cn.tongdun.android.adapter.DetailsItemAdapter;
+import cn.tongdun.android.beans.DetailsItemBean;
+
+import java.util.List;
+
+/**
+ * @description: Device Details Item View
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DeviceDetailsItemView extends ConstraintLayout {
+
+ private boolean isExpanded = false;
+ private TextView tvModuleName;
+ private TextView tvDescribe;
+ private ImageView ivArrow;
+ private RecyclerView rvDetailsContainer;
+
+ public DeviceDetailsItemView(@NonNull Context context) {
+ super(context);
+ }
+
+ public DeviceDetailsItemView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public DeviceDetailsItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public void setExpanded(boolean expanded) {
+ isExpanded = expanded;
+ }
+
+ public void setModuleName(String name) {
+ tvModuleName = findViewById(R.id.tv_module_name);
+ tvModuleName.setText(name);
+ }
+
+ public void setDescribe(String desc) {
+ tvDescribe = findViewById(R.id.tv_module_des);
+ if (TextUtils.isEmpty(desc)) {
+ tvDescribe.setVisibility(GONE);
+ } else {
+ tvDescribe.setText(desc);
+ }
+ }
+
+ public void setDetailsContainer(List list) {
+ ivArrow = findViewById(R.id.iv_arrow);
+ rvDetailsContainer = findViewById(R.id.rv_details_container);
+ LinearLayoutManager manager = new LinearLayoutManager(this.getContext());
+ manager.setOrientation(GridLayoutManager.VERTICAL);
+ rvDetailsContainer.setLayoutManager(manager);
+ DetailsItemAdapter adapter = new DetailsItemAdapter(list);
+ rvDetailsContainer.setAdapter(adapter);
+ DividerItemDecoration decoration = new DividerItemDecoration(this.getContext(), DividerItemDecoration.VERTICAL);
+ decoration.setDrawable(getResources().getDrawable(R.drawable.detail_item_divider));
+ rvDetailsContainer.addItemDecoration(decoration);
+ if (isExpanded){
+ rvDetailsContainer.setVisibility(VISIBLE);
+ ivArrow.setImageResource(R.drawable.ic_up_arrow);
+ }
+ setOnClickListener(v -> toggleExpanding());
+ }
+
+ private void toggleExpanding() {
+ if (!isExpanded) {
+ rvDetailsContainer.setVisibility(VISIBLE);
+ ivArrow.setImageResource(R.drawable.ic_up_arrow);
+ } else {
+ rvDetailsContainer.setVisibility(GONE);
+ ivArrow.setImageResource(R.drawable.ic_down_arrow);
+ }
+ isExpanded = !isExpanded;
+ }
+}
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/detail_item_divider.xml b/app/src/main/res/drawable/detail_item_divider.xml
new file mode 100644
index 0000000..12b80b6
--- /dev/null
+++ b/app/src/main/res/drawable/detail_item_divider.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_down_arrow.xml b/app/src/main/res/drawable/ic_down_arrow.xml
new file mode 100644
index 0000000..22c401f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_down_arrow.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..07d5da9
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_up_arrow.xml b/app/src/main/res/drawable/ic_up_arrow.xml
new file mode 100644
index 0000000..92bc86d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_up_arrow.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/item_card_background.xml b/app/src/main/res/drawable/item_card_background.xml
new file mode 100644
index 0000000..e77ee6d
--- /dev/null
+++ b/app/src/main/res/drawable/item_card_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..c9cfc53
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_details.xml b/app/src/main/res/layout/item_details.xml
new file mode 100644
index 0000000..754f975
--- /dev/null
+++ b/app/src/main/res/layout/item_details.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_device_module.xml b/app/src/main/res/layout/item_device_module.xml
new file mode 100644
index 0000000..43c8332
--- /dev/null
+++ b/app/src/main/res/layout/item_device_module.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..3a3a167
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..8d41b3f
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..6cc3c90
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..a3a4db5
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..e248413
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml
new file mode 100644
index 0000000..fe90369
--- /dev/null
+++ b/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..8e12ff4
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,13 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+ #F5F5F5
+ #6E6E6E
+ #F2F2F2
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..9e6f283
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ TrustDevice
+
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
new file mode 100644
index 0000000..6b2a6bc
--- /dev/null
+++ b/app/src/main/res/values/themes.xml
@@ -0,0 +1,18 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 0000000..fa0f996
--- /dev/null
+++ b/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 0000000..9ee9997
--- /dev/null
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/test/java/cn/tongdun/android/ExampleUnitTest.java b/app/src/test/java/cn/tongdun/android/ExampleUnitTest.java
new file mode 100644
index 0000000..ef6e78b
--- /dev/null
+++ b/app/src/test/java/cn/tongdun/android/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package cn.tongdun.android;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..71b99f4
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '7.3.1' apply false
+ id 'com.android.library' version '7.3.1' apply false
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..3e927b1
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..e708b1c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..b811099
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Dec 05 18:57:14 CST 2022
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..4f906e0
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..107acd3
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/jitpack.yml b/jitpack.yml
new file mode 100644
index 0000000..3887c40
--- /dev/null
+++ b/jitpack.yml
@@ -0,0 +1,6 @@
+jdk:
+ - openjdk11
+install:
+ - ./gradlew clean
+ - ./gradlew trustdevice:assembleRelease
+ - ./gradlew trustdevice:publishMavenJavaPublicationToMavenLocal
\ No newline at end of file
diff --git a/resources/demo.gif b/resources/demo.gif
new file mode 100644
index 0000000..32e44f5
Binary files /dev/null and b/resources/demo.gif differ
diff --git a/resources/logo_dark.png b/resources/logo_dark.png
new file mode 100644
index 0000000..0b9aba9
Binary files /dev/null and b/resources/logo_dark.png differ
diff --git a/resources/logo_light.png b/resources/logo_light.png
new file mode 100644
index 0000000..4929deb
Binary files /dev/null and b/resources/logo_light.png differ
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..7f8ef7b
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,19 @@
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ google()
+ mavenCentral()
+ maven { url 'https://jitpack.io' }
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ maven { url 'https://jitpack.io' }
+ }
+}
+rootProject.name = "trustdevice-android"
+include ':app'
+include ':trustdevice'
diff --git a/trustdevice/.gitignore b/trustdevice/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/trustdevice/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/trustdevice/build.gradle b/trustdevice/build.gradle
new file mode 100644
index 0000000..f1aaa1f
--- /dev/null
+++ b/trustdevice/build.gradle
@@ -0,0 +1,48 @@
+plugins {
+ id 'com.android.library'
+ id 'maven-publish'
+ id 'signing'
+}
+
+group = 'com.github.trustdecision'
+
+afterEvaluate {
+ publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ groupId = 'com.github.trustdecision'
+ artifactId = "trustdevice-android"
+ version = '1.0.0'
+ artifact("$buildDir/outputs/aar/trustdevice-release.aar")
+ }
+ }
+ }
+}
+
+android {
+ namespace 'cn.tongdun.mobrisk'
+ compileSdk 33
+
+ defaultConfig {
+ minSdk 21
+ targetSdk 33
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+
+ }
+}
+
+dependencies {
+ implementation 'androidx.appcompat:appcompat:1.5.1'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.4'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
\ No newline at end of file
diff --git a/trustdevice/consumer-rules.pro b/trustdevice/consumer-rules.pro
new file mode 100644
index 0000000..494fbe8
--- /dev/null
+++ b/trustdevice/consumer-rules.pro
@@ -0,0 +1 @@
+-keep class cn.tongdun.**{*;}
\ No newline at end of file
diff --git a/trustdevice/proguard-rules.pro b/trustdevice/proguard-rules.pro
new file mode 100644
index 0000000..cc74cb8
--- /dev/null
+++ b/trustdevice/proguard-rules.pro
@@ -0,0 +1,32 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+-verbose
+-dontusemixedcaseclassnames
+
+#-dontskipnonpubliclibraryclasses
+-dontoptimize
+-dontnote java.**, javax.**, org.**
+-dontwarn android.support.**
+#-overloadaggressively
+
+#-allowaccessmodification
+
+#-useuniqueclassmembernames
+
+-keepattributes SourceFile, LineNumberTable, *Annotation*, Exceptions, InnerClasses
+
+-keep class cn.tongdun.mobrisk.TDRisk {
+ public static *;
+ public *;
+}
+-keep class cn.tongdun.mobrisk.TDRisk$Builder {
+ public static *;
+ public *;
+}
+-keep class cn.tongdun.mobrisk.beans.DeviceInfo {
+ private *;
+}
+-keep class cn.tongdun.mobrisk.providers.** {
+ public *;
+}
+-keep interface cn.tongdun.mobrisk.TDRiskCallback {*;}
\ No newline at end of file
diff --git a/trustdevice/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java b/trustdevice/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java
new file mode 100644
index 0000000..ee411e0
--- /dev/null
+++ b/trustdevice/src/androidTest/java/cn/tongdun/android/ExampleInstrumentedTest.java
@@ -0,0 +1,25 @@
+package cn.tongdun.android;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("cn.tongdun.android.test", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/trustdevice/src/main/AndroidManifest.xml b/trustdevice/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a5918e6
--- /dev/null
+++ b/trustdevice/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRisk.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRisk.java
new file mode 100644
index 0000000..65aa879
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRisk.java
@@ -0,0 +1,54 @@
+package cn.tongdun.mobrisk;
+
+import android.content.Context;
+
+import org.json.JSONObject;
+
+import cn.tongdun.mobrisk.core.FMCore;
+
+/**
+ * @description: fingerprint entry class
+ * @author: wuzuchang
+ * @date: 2022/12/5
+ */
+public class TDRisk {
+
+ public static void init(final Context context) {
+ initWithOptions(context, null);
+ }
+
+ public static void initWithOptions(final Context context, Builder builder) {
+ if (context == null) {
+ return;
+ }
+ FMCore.getInstance().init(context, builder == null ? null : builder.build());
+ }
+
+ public static JSONObject getBlackbox() {
+
+ return FMCore.getInstance().getDeviceInfo();
+ }
+
+ public static class Builder {
+
+ private String partnerCode;
+ private TDRiskCallback callback;
+
+ public Builder partner(String partner) {
+ partnerCode = partner;
+ return this;
+ }
+
+ public Builder callback(TDRiskCallback TDRiskCallback) {
+ callback = TDRiskCallback;
+ return this;
+ }
+
+ public TDRiskOption build() {
+ TDRiskOption options = new TDRiskOption();
+ options.setPartnerCode(partnerCode);
+ options.setCallback(callback);
+ return options;
+ }
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskCallback.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskCallback.java
new file mode 100644
index 0000000..e50f4dd
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskCallback.java
@@ -0,0 +1,7 @@
+package cn.tongdun.mobrisk;
+
+import org.json.JSONObject;
+
+public interface TDRiskCallback {
+ void onEvent(JSONObject deviceInfo);
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskOption.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskOption.java
new file mode 100644
index 0000000..f45ce4c
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/TDRiskOption.java
@@ -0,0 +1,31 @@
+package cn.tongdun.mobrisk;
+
+
+/**
+ * @description: Option
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class TDRiskOption {
+ private String partnerCode; //td partner
+ private TDRiskCallback callback;
+
+ public TDRiskOption() {
+ }
+
+ public String getPartnerCode() {
+ return partnerCode;
+ }
+
+ public void setPartnerCode(String partnerCode) {
+ this.partnerCode = partnerCode;
+ }
+
+ public TDRiskCallback getCallback() {
+ return callback;
+ }
+
+ public void setCallback(TDRiskCallback callback) {
+ this.callback = callback;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/beans/DeviceInfo.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/beans/DeviceInfo.java
new file mode 100644
index 0000000..db27f89
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/beans/DeviceInfo.java
@@ -0,0 +1,255 @@
+package cn.tongdun.mobrisk.beans;
+
+/**
+ * @description: DeviceInfo
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DeviceInfo {
+
+ private String androidId;
+ private String gsfId;
+ private String mediaDrmId;
+ private String vbMetaDigest;
+ private String model;
+ private String manufacturer;
+ private String androidVersion;
+ private String sdkVersion;
+ private String kernelVersion;
+ private String fingerprint;
+ private String hardware;
+ private String product;
+ private String brand;
+ private String display;
+ private String host;
+ private String batteryHealthStatus;
+ private String batteryStatus;
+ private String batteryLevel;
+ private String batteryTemp;
+ private String batteryTotalCapacity;
+ private String cpuProcessor;
+ private String cpuHardware;
+ private String coresCount;
+ private String abiType;
+ private boolean debug;
+ private boolean root;
+ private String country;
+ private String language;
+ private String timezone;
+ private String totalMemory;
+ private String availableMemory;
+ private String totalStorage;
+ private String availableStorage;
+ private String appList;
+ private String systemAppList;
+ private String sensorsInfo;
+ private String adbEnabled;
+ private String developmentSettingEnabled;
+ private String httpProxy;
+ private String dataRoaming;
+ private String allowMockLocation;
+ private String accessibilityEnabled;
+ private String defaultInputMethod;
+ private String touchExplorationEnabled;
+ private String screenBrightness;
+ private String screenOffTimeout;
+ private String screenResolution;
+ private String filesAbsolutePath;
+ private String packageName;
+
+ public void setModel(String model) {
+ this.model = model;
+ }
+
+ public void setManufacturer(String manufacturer) {
+ this.manufacturer = manufacturer;
+ }
+
+ public void setAndroidVersion(String androidVersion) {
+ this.androidVersion = androidVersion;
+ }
+
+ public void setVbMetaDigest(String vbMetaDigest) {
+ this.vbMetaDigest = vbMetaDigest;
+ }
+
+ public void setSdkVersion(String sdkVersion) {
+ this.sdkVersion = sdkVersion;
+ }
+
+ public void setKernelVersion(String kernelVersion) {
+ this.kernelVersion = kernelVersion;
+ }
+
+ public void setFingerprint(String fingerprint) {
+ this.fingerprint = fingerprint;
+ }
+
+ public void setHardware(String hardware) {
+ this.hardware = hardware;
+ }
+
+ public void setProduct(String product) {
+ this.product = product;
+ }
+
+ public void setBrand(String brand) {
+ this.brand = brand;
+ }
+
+ public void setDisplay(String display) {
+ this.display = display;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public void setBatteryHealthStatus(String batteryHealthStatus) {
+ this.batteryHealthStatus = batteryHealthStatus;
+ }
+
+ public void setBatteryStatus(String batteryStatus) {
+ this.batteryStatus = batteryStatus;
+ }
+
+ public void setBatteryLevel(String batteryLevel) {
+ this.batteryLevel = batteryLevel;
+ }
+
+ public void setBatteryTemp(String batteryTemp) {
+ this.batteryTemp = batteryTemp;
+ }
+
+ public void setBatteryTotalCapacity(String batteryTotalCapacity) {
+ this.batteryTotalCapacity = batteryTotalCapacity;
+ }
+
+ public void setCpuProcessor(String cpuProcessor) {
+ this.cpuProcessor = cpuProcessor;
+ }
+
+ public void setCpuHardware(String cpuHardware) {
+ this.cpuHardware = cpuHardware;
+ }
+
+ public void setCoresCount(String coresCount) {
+ this.coresCount = coresCount;
+ }
+
+ public void setAbiType(String abiType) {
+ this.abiType = abiType;
+ }
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public void setRoot(boolean root) {
+ this.root = root;
+ }
+
+ public void setAndroidId(String androidId) {
+ this.androidId = androidId;
+ }
+
+ public void setGsfId(String gsfId) {
+ this.gsfId = gsfId;
+ }
+
+ public void setMediaDrmId(String mediaDrmId) {
+ this.mediaDrmId = mediaDrmId;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ public void setTimezone(String timezone) {
+ this.timezone = timezone;
+ }
+
+ public void setTotalMemory(String totalMemory) {
+ this.totalMemory = totalMemory;
+ }
+
+ public void setAvailableMemory(String availableMemory) {
+ this.availableMemory = availableMemory;
+ }
+
+ public void setTotalStorage(String totalStorage) {
+ this.totalStorage = totalStorage;
+ }
+
+ public void setAvailableStorage(String availableStorage) {
+ this.availableStorage = availableStorage;
+ }
+
+ public void setAppList(String appList) {
+ this.appList = appList;
+ }
+
+ public void setSystemAppList(String systemAppList) {
+ this.systemAppList = systemAppList;
+ }
+
+ public void setSensorsInfo(String sensorsInfo) {
+ this.sensorsInfo = sensorsInfo;
+ }
+
+ public void setAdbEnabled(String adbEnabled) {
+ this.adbEnabled = adbEnabled;
+ }
+
+ public void setDevelopmentSettingEnabled(String developmentSettingEnabled) {
+ this.developmentSettingEnabled = developmentSettingEnabled;
+ }
+
+ public void setHttpProxy(String httpProxy) {
+ this.httpProxy = httpProxy;
+ }
+
+ public void setDataRoaming(String dataRoaming) {
+ this.dataRoaming = dataRoaming;
+ }
+
+ public void setAllowMockLocation(String allowMockLocation) {
+ this.allowMockLocation = allowMockLocation;
+ }
+
+ public void setAccessibilityEnabled(String accessibilityEnabled) {
+ this.accessibilityEnabled = accessibilityEnabled;
+ }
+
+ public void setDefaultInputMethod(String defaultInputMethod) {
+ this.defaultInputMethod = defaultInputMethod;
+ }
+
+ public void setTouchExplorationEnabled(String touchExplorationEnabled) {
+ this.touchExplorationEnabled = touchExplorationEnabled;
+ }
+
+ public void setScreenBrightness(String screenBrightness) {
+ this.screenBrightness = screenBrightness;
+ }
+
+ public void setScreenOffTimeout(String screenOffTimeout) {
+ this.screenOffTimeout = screenOffTimeout;
+ }
+
+ public void setScreenResolution(String screenResolution) {
+ this.screenResolution = screenResolution;
+ }
+
+ public void setFilesAbsolutePath(String filesAbsolutePath) {
+ this.filesAbsolutePath = filesAbsolutePath;
+ }
+
+ public void setPackageName(String packageName) {
+ this.packageName = packageName;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/FMCore.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/FMCore.java
new file mode 100644
index 0000000..d302915
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/FMCore.java
@@ -0,0 +1,195 @@
+package cn.tongdun.mobrisk.core;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.hardware.SensorManager;
+
+import org.json.JSONObject;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import cn.tongdun.mobrisk.TDRiskCallback;
+import cn.tongdun.mobrisk.TDRiskOption;
+import cn.tongdun.mobrisk.beans.DeviceInfo;
+import cn.tongdun.mobrisk.core.collectors.AppListCollector;
+import cn.tongdun.mobrisk.core.collectors.BatteryInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.BuildInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.CpuInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.DebugInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.DeviceBaseInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.DeviceIdCollector;
+import cn.tongdun.mobrisk.core.collectors.DevicePersonalizationInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.MemoryInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.RootCollector;
+import cn.tongdun.mobrisk.core.collectors.SensorsInfoCollector;
+import cn.tongdun.mobrisk.core.collectors.SettingInfoCollector;
+import cn.tongdun.mobrisk.core.utils.DeviceInfoUtils;
+import cn.tongdun.mobrisk.core.utils.LogUtils;
+
+
+public class FMCore {
+
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private final CountDownLatch countDownLatch = new CountDownLatch(1);
+ private Context mContext;
+ private DeviceInfo mDeviceInfo;
+ private String mDeviceId;
+ private TDRiskCallback mCallback = null;
+
+ private FMCore() {
+ }
+
+ private static class SingletonHolder {
+ @SuppressLint("StaticFieldLeak")
+ private static final FMCore instance = new FMCore();
+ }
+
+ public static FMCore getInstance() {
+ return SingletonHolder.instance;
+ }
+
+ public void init(Context context, TDRiskOption option) {
+ if (context == null) {
+ return;
+ }
+ if (mDeviceInfo == null) {
+ mDeviceInfo = new DeviceInfo();
+ }
+ if (option != null) {
+ mCallback = option.getCallback();
+ }
+ mContext = context.getApplicationContext();
+ executor.execute(() -> {
+ collectorDeviceId();
+ collectorDebugInfo();
+ collectorRoot();
+ collectorBuildInfo();
+ collectorDeviceBaseInfo();
+ collectorDevicePersonalizationInfo();
+ collectorMemoryInfo();
+ collectorCpuInfo();
+ collectorBatteryInfo();
+ collectorSettingInfo();
+ collectorSensorInfo();
+ collectorPackageListInfo();
+ countDownLatch.countDown();
+ if (mCallback !=null){
+ mCallback.onEvent(getDeviceInfo());
+ }
+ });
+ }
+
+ private void collectorDeviceId() {
+ DeviceIdCollector deviceIdCollector = new DeviceIdCollector(mContext.getContentResolver());
+ mDeviceId = deviceIdCollector.getDeviceId();
+ mDeviceInfo.setAndroidId(deviceIdCollector.getAndroidId());
+ mDeviceInfo.setGsfId(deviceIdCollector.getGsfId());
+ mDeviceInfo.setMediaDrmId(deviceIdCollector.getMediaDrmId());
+ mDeviceInfo.setVbMetaDigest(deviceIdCollector.getVbMetaDigest());
+ }
+
+ private void collectorDebugInfo() {
+ DebugInfoCollector debugInfoCollector = new DebugInfoCollector();
+ mDeviceInfo.setDebug(debugInfoCollector.getDebug());
+ }
+
+ private void collectorRoot() {
+ RootCollector rootCollector = new RootCollector();
+ mDeviceInfo.setRoot(rootCollector.getRoot());
+ }
+
+ private void collectorBuildInfo() {
+ BuildInfoCollector buildInfoCollector = new BuildInfoCollector();
+ mDeviceInfo.setModel(buildInfoCollector.getModel());
+ mDeviceInfo.setManufacturer(buildInfoCollector.getManufacturer());
+ mDeviceInfo.setAndroidVersion(buildInfoCollector.getAndroidVersion());
+ mDeviceInfo.setSdkVersion(buildInfoCollector.getSdkVersion());
+ mDeviceInfo.setKernelVersion(buildInfoCollector.getKernelVersion());
+ mDeviceInfo.setFingerprint(buildInfoCollector.getFingerprint());
+ mDeviceInfo.setHardware(buildInfoCollector.getHardware());
+ mDeviceInfo.setProduct(buildInfoCollector.getProduct());
+ mDeviceInfo.setBrand(buildInfoCollector.getBrand());
+ mDeviceInfo.setHost(buildInfoCollector.getHost());
+ mDeviceInfo.setDisplay(buildInfoCollector.getDisplay());
+ mDeviceInfo.setHost(buildInfoCollector.getHost());
+ }
+
+ private void collectorDeviceBaseInfo() {
+ DeviceBaseInfoCollector deviceBaseInfoCollector = new DeviceBaseInfoCollector(mContext);
+ mDeviceInfo.setScreenResolution(deviceBaseInfoCollector.getScreenResolution());
+ mDeviceInfo.setFilesAbsolutePath(deviceBaseInfoCollector.getFilesAbsolutePath());
+ mDeviceInfo.setPackageName(deviceBaseInfoCollector.getPackageName());
+ }
+
+ private void collectorDevicePersonalizationInfo() {
+ DevicePersonalizationInfoCollector devicePersonalizationInfoCollector = new DevicePersonalizationInfoCollector();
+ mDeviceInfo.setCountry(devicePersonalizationInfoCollector.getLocaleCountry());
+ mDeviceInfo.setLanguage(devicePersonalizationInfoCollector.getDefaultLanguage());
+ mDeviceInfo.setTimezone(devicePersonalizationInfoCollector.getTimezone());
+ }
+
+ private void collectorMemoryInfo() {
+ ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ MemoryInfoCollector memoryInfoCollector = new MemoryInfoCollector(activityManager);
+ mDeviceInfo.setTotalMemory(String.valueOf(memoryInfoCollector.getTotalMemory()));
+ mDeviceInfo.setAvailableMemory(String.valueOf(memoryInfoCollector.getAvailableMemory()));
+ mDeviceInfo.setTotalStorage(String.valueOf(memoryInfoCollector.getTotalStorage()));
+ mDeviceInfo.setAvailableStorage(String.valueOf(memoryInfoCollector.getAvailableStorage()));
+ }
+
+ private void collectorCpuInfo() {
+ CpuInfoCollector cpuInfoCollector = new CpuInfoCollector();
+ mDeviceInfo.setCoresCount(cpuInfoCollector.availableProcessors());
+ mDeviceInfo.setCpuHardware(cpuInfoCollector.getCpuHardware());
+ mDeviceInfo.setCpuProcessor(cpuInfoCollector.getCpuProcessor());
+ mDeviceInfo.setAbiType(cpuInfoCollector.getAbiType());
+ }
+
+ private void collectorBatteryInfo() {
+ BatteryInfoCollector batteryInfoCollector = new BatteryInfoCollector(mContext);
+ mDeviceInfo.setBatteryHealthStatus(batteryInfoCollector.getBatteryHealthStatus());
+ mDeviceInfo.setBatteryStatus(batteryInfoCollector.getBatteryStatus());
+ mDeviceInfo.setBatteryLevel(String.valueOf(batteryInfoCollector.getBatteryLevel()));
+ mDeviceInfo.setBatteryTemp(String.valueOf(batteryInfoCollector.getBatteryTemp()));
+ mDeviceInfo.setBatteryTotalCapacity(batteryInfoCollector.getBatteryTotalCapacity());
+ }
+
+ private void collectorSettingInfo() {
+ SettingInfoCollector settingInfoCollector = new SettingInfoCollector(mContext.getContentResolver());
+ mDeviceInfo.setAdbEnabled(settingInfoCollector.getAdbEnabled());
+ mDeviceInfo.setDevelopmentSettingEnabled(settingInfoCollector.getDevelopmentSettingEnabled());
+ mDeviceInfo.setHttpProxy(settingInfoCollector.getHttpProxy());
+ mDeviceInfo.setDataRoaming(settingInfoCollector.getDataRoaming());
+ mDeviceInfo.setAllowMockLocation(settingInfoCollector.getAllowMockLocation());
+ mDeviceInfo.setAccessibilityEnabled(settingInfoCollector.getAccessibilityEnabled());
+ mDeviceInfo.setDefaultInputMethod(settingInfoCollector.getDefaultInputMethod());
+ mDeviceInfo.setTouchExplorationEnabled(settingInfoCollector.getTouchExplorationEnabled());
+ mDeviceInfo.setScreenBrightness(settingInfoCollector.getScreenBrightness());
+ mDeviceInfo.setScreenOffTimeout(settingInfoCollector.getScreenOffTimeout());
+ }
+
+ private void collectorSensorInfo() {
+ SensorManager sensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ SensorsInfoCollector sensorsInfoCollector = new SensorsInfoCollector(sensorManager);
+ mDeviceInfo.setSensorsInfo(sensorsInfoCollector.getSensorList());
+ }
+
+ private void collectorPackageListInfo() {
+ AppListCollector appListCollector = new AppListCollector(mContext.getPackageManager());
+ mDeviceInfo.setAppList(appListCollector.getAppList());
+ mDeviceInfo.setSystemAppList(appListCollector.getSystemAppList());
+ }
+
+ public JSONObject getDeviceInfo() {
+ try {
+ countDownLatch.await(1000L, TimeUnit.MILLISECONDS);
+ } catch (Throwable e) {
+ LogUtils.e("getDeviceInfo await exception e:" + e.getMessage());
+ }
+ return DeviceInfoUtils.format(mDeviceId, mDeviceInfo);
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/AppListCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/AppListCollector.java
new file mode 100644
index 0000000..d7f0c53
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/AppListCollector.java
@@ -0,0 +1,46 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.annotation.SuppressLint;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @description: PackageListInfo
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class AppListCollector {
+ private List appList = new ArrayList<>();
+ private List systemAppList = new ArrayList<>();
+
+ @SuppressLint("QueryPermissionsNeeded")
+ public AppListCollector(PackageManager packageManager) {
+ List packageInfoList = packageManager.getInstalledPackages(0);
+ for (PackageInfo packageInfo : packageInfoList) {
+ if (isSystemApp(packageInfo)) {
+ systemAppList.add(packageInfo.packageName);
+ } else {
+ appList.add(packageInfo.packageName);
+ }
+ }
+ }
+
+ public String getAppList() {
+ return TextUtils.join(",", appList);
+ }
+
+ public String getSystemAppList() {
+ return TextUtils.join(",", systemAppList);
+ }
+
+ private boolean isSystemApp(PackageInfo packageInfo) {
+ boolean isSysApp = (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == ApplicationInfo.FLAG_SYSTEM;
+ boolean isSysUpd = (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+ return isSysApp || isSysUpd;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BatteryInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BatteryInfoCollector.java
new file mode 100644
index 0000000..aa2344d
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BatteryInfoCollector.java
@@ -0,0 +1,123 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+
+import java.lang.reflect.Method;
+
+/**
+ * @description: Battery Info
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class BatteryInfoCollector {
+
+ private static final String POWER_PROFILE_CLASS_NAME = "com.android.internal.os.PowerProfile";
+ private static final String BATTERY_CAPACITY_METHOD_NAME = "getBatteryCapacity";
+
+ private final Context mContext;
+ private String batteryHealthStatus;
+ private String batteryStatus;
+ private int batteryLevel;
+ private int batteryTemp;
+
+ public BatteryInfoCollector(Context context) {
+ mContext = context;
+ getBatteryInfo();
+ }
+
+ private void getBatteryInfo() {
+ Intent intent = mContext.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED), "com.permission.broadcast.td", null);
+ if (intent==null){
+ return;
+ }
+ int health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, -1);
+ batteryHealthStatus = batteryHealthStatus(health);
+ int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, 0);
+ batteryStatus = batteryStatus(status);
+ batteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
+ batteryTemp = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0);
+ }
+
+ private String batteryHealthStatus(int batteryHealth) {
+ String type;
+ switch (batteryHealth) {
+ case BatteryManager.BATTERY_HEALTH_GOOD:
+ type = "good";
+ break;
+ case BatteryManager.BATTERY_HEALTH_OVERHEAT:
+ type = "overheat";
+ break;
+ case BatteryManager.BATTERY_HEALTH_COLD:
+ type = "cold";
+ break;
+ case BatteryManager.BATTERY_HEALTH_DEAD:
+ type = "dead";
+ break;
+ case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
+ type = "over voltage";
+ break;
+ case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
+ type = "unspecified failure";
+ break;
+ default:
+ type = "unknown";
+ break;
+ }
+ return type;
+ }
+
+ private String batteryStatus(int status) {
+ String statusStr;
+ switch (status) {
+ case BatteryManager.BATTERY_STATUS_CHARGING:
+ statusStr = "charging";
+ break;
+ case BatteryManager.BATTERY_STATUS_DISCHARGING:
+ statusStr = "discharging";
+ break;
+ case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
+ statusStr = "not charging";
+ break;
+ case BatteryManager.BATTERY_STATUS_FULL:
+ statusStr = "full";
+ break;
+ default:
+ statusStr = "unknown";
+ break;
+ }
+ return statusStr;
+ }
+
+ public String getBatteryHealthStatus() {
+ return batteryHealthStatus;
+ }
+
+ public String getBatteryStatus() {
+ return batteryStatus;
+ }
+
+ public int getBatteryLevel() {
+ return batteryLevel;
+ }
+
+ public int getBatteryTemp() {
+ return batteryTemp;
+ }
+
+ @SuppressLint("PrivateApi")
+ public String getBatteryTotalCapacity() {
+ try {
+ Class> powerProfileClass = Class.forName(POWER_PROFILE_CLASS_NAME);
+ Object object = powerProfileClass.getConstructor(Context.class).newInstance(mContext);
+ Method getBatteryCapacity = powerProfileClass.getMethod(BATTERY_CAPACITY_METHOD_NAME);
+ double totalCapacity = (double) getBatteryCapacity.invoke(object);
+ return String.valueOf(totalCapacity);
+ } catch (Throwable ignored) {
+ }
+ return "";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BuildInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BuildInfoCollector.java
new file mode 100644
index 0000000..f7ef462
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/BuildInfoCollector.java
@@ -0,0 +1,100 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.os.Build;
+
+/**
+ * @description: BuildInfo
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class BuildInfoCollector {
+
+ public String getModel() {
+ try {
+ return Build.MODEL;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getManufacturer() {
+ try {
+ return Build.MANUFACTURER;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getAndroidVersion() {
+ try {
+ return Build.VERSION.RELEASE;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getSdkVersion() {
+ try {
+ return String.valueOf(Build.VERSION.SDK_INT);
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getKernelVersion() {
+ try {
+ return System.getProperty("os.version");
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getFingerprint() {
+ try {
+ return Build.FINGERPRINT;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getHardware() {
+ try {
+ return Build.HARDWARE;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getBrand() {
+ try {
+ return Build.BRAND;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getHost() {
+ try {
+ return Build.HOST;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getDisplay() {
+ try {
+ return Build.DISPLAY;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getProduct() {
+ try {
+ return Build.PRODUCT;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/CpuInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/CpuInfoCollector.java
new file mode 100644
index 0000000..1be3fac
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/CpuInfoCollector.java
@@ -0,0 +1,62 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.os.Build;
+import android.text.TextUtils;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cn.tongdun.mobrisk.core.utils.FileUtils;
+
+/**
+ * @description: Cpu info
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class CpuInfoCollector {
+ private static final List keyList = Arrays.asList("Processor", "Hardware");
+ private static final String CPU_INFO_PATH = "/proc/cpuinfo";
+ private static final String KEY_VALUE_DELIMITER = ": ";
+ private Map mCpuInfo = new HashMap<>();
+
+ public CpuInfoCollector() {
+ try {
+ mCpuInfo = FileUtils.readFileByKey(CPU_INFO_PATH, keyList, KEY_VALUE_DELIMITER);
+ } catch (Exception ignored) {
+ }
+ }
+
+ public String getCpuProcessor() {
+ try {
+ return mCpuInfo.get(keyList.get(0));
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getCpuHardware() {
+ try {
+ return mCpuInfo.get(keyList.get(1));
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getAbiType() {
+ try {
+ return TextUtils.join(",", Build.SUPPORTED_ABIS);
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String availableProcessors() {
+ try {
+ return String.valueOf(Runtime.getRuntime().availableProcessors());
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DebugInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DebugInfoCollector.java
new file mode 100644
index 0000000..d5f0819
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DebugInfoCollector.java
@@ -0,0 +1,13 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+/**
+ * @description: Debug Info
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DebugInfoCollector {
+
+ public boolean getDebug(){
+ return android.os.Debug.isDebuggerConnected();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceBaseInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceBaseInfoCollector.java
new file mode 100644
index 0000000..6e77f7d
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceBaseInfoCollector.java
@@ -0,0 +1,46 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.content.Context;
+import android.util.DisplayMetrics;
+import android.view.WindowManager;
+
+/**
+ * @description: DevicePersonalizationInfoCollector
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DeviceBaseInfoCollector {
+
+ private Context mContext;
+
+ public DeviceBaseInfoCollector(Context context) {
+ mContext = context;
+ }
+
+ public String getScreenResolution() {
+ try {
+ WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ DisplayMetrics outMetrics = new DisplayMetrics();
+ windowManager.getDefaultDisplay().getRealMetrics(outMetrics);
+ return outMetrics.widthPixels + "x" + outMetrics.heightPixels;
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getFilesAbsolutePath() {
+ try {
+ return mContext.getFilesDir().getAbsolutePath();
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String getPackageName() {
+ try {
+ return mContext.getPackageName();
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceIdCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceIdCollector.java
new file mode 100644
index 0000000..dbf46a0
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DeviceIdCollector.java
@@ -0,0 +1,118 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.media.MediaDrm;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import java.util.UUID;
+
+import cn.tongdun.mobrisk.core.utils.MessageDigestUtils;
+
+/**
+ * @description: Device id
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DeviceIdCollector {
+
+ private static final String URI_GSF_CONTENT_PROVIDER = "content://com.google.android.gsf.gservices";
+ private static final String GSF_ID_KEY = "android_id";
+ private ContentResolver mContentResolver;
+ private String androidId;
+ private String gsfId;
+ private String mediaDrmId;
+
+ public DeviceIdCollector(ContentResolver contentResolver) {
+ mContentResolver = contentResolver;
+ }
+
+ public String getDeviceId() {
+
+ if (androidId == null) {
+ androidId = getAndroidId();
+ }
+ if (!TextUtils.isEmpty(androidId)) {
+ return MessageDigestUtils.hash("SHA-256", androidId);
+ }
+ if (gsfId == null) {
+ gsfId = getGsfId();
+ }
+ if (!TextUtils.isEmpty(gsfId)) {
+ return MessageDigestUtils.hash("SHA-256", gsfId);
+ }
+ if (mediaDrmId != null) {
+ return mediaDrmId;
+ }
+ return MessageDigestUtils.hash("SHA-256", getMediaDrmId() + getVbMetaDigest());
+ }
+
+ public String getAndroidId() {
+ if (androidId != null) {
+ return androidId;
+ }
+ try {
+ androidId = Settings.Secure.getString(mContentResolver, Settings.Secure.ANDROID_ID);
+ } catch (Exception ignored) {
+ }
+ return androidId;
+ }
+
+ public String getMediaDrmId() {
+ if (mediaDrmId != null) {
+ return mediaDrmId;
+ }
+ mediaDrmId = "";
+ MediaDrm drm = null;
+ try {
+ UUID uuid = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
+ drm = new MediaDrm(uuid);
+ byte[] bytes = drm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
+ mediaDrmId = MessageDigestUtils.hash("SHA-256", bytes);
+ } catch (Throwable ignored) {
+ } finally {
+ if (drm != null) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ drm.close();
+ } else {
+ drm.release();
+ }
+ }
+ }
+ return mediaDrmId;
+ }
+
+ public String getGsfId() {
+ if (gsfId != null) {
+ return gsfId;
+ }
+ gsfId = "";
+ try {
+ Uri uri = Uri.parse(URI_GSF_CONTENT_PROVIDER);
+ Cursor cursor = mContentResolver.query(uri, null, null, new String[]{GSF_ID_KEY}, null);
+ if (cursor == null) {
+ return null;
+ }
+ if (!cursor.moveToFirst() || cursor.getColumnCount() < 2) {
+ cursor.close();
+ return null;
+ }
+ try {
+ gsfId = cursor.getString(1);
+ cursor.close();
+ } catch (Throwable e) {
+ cursor.close();
+ }
+ } catch (Throwable e) {
+ }
+ return gsfId;
+ }
+
+ public String getVbMetaDigest(){
+ SystemPropertyInfoCollector systemPropertyInfoCollector = new SystemPropertyInfoCollector();
+ return systemPropertyInfoCollector.getMetaDigest();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DevicePersonalizationInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DevicePersonalizationInfoCollector.java
new file mode 100644
index 0000000..259c740
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/DevicePersonalizationInfoCollector.java
@@ -0,0 +1,27 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * @description: DevicePersonalizationInfoCollector
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class DevicePersonalizationInfoCollector {
+
+ public DevicePersonalizationInfoCollector() {
+ }
+
+ public String getLocaleCountry() {
+ return Locale.getDefault().getCountry();
+ }
+
+ public String getDefaultLanguage() {
+ return Locale.getDefault().getLanguage();
+ }
+
+ public String getTimezone() {
+ return TimeZone.getDefault().getDisplayName();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/MemoryInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/MemoryInfoCollector.java
new file mode 100644
index 0000000..db10f5e
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/MemoryInfoCollector.java
@@ -0,0 +1,64 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.app.ActivityManager;
+import android.os.Environment;
+import android.os.StatFs;
+
+import java.io.File;
+
+/**
+ * @description: Memory Info
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class MemoryInfoCollector {
+
+ private long mAvailableMemory;
+ private long mTotalMemory;
+ private long mAvailableStorage;
+ private long mTotalStorage;
+
+ public MemoryInfoCollector(ActivityManager activityManager) {
+ getMemoryInfo(activityManager);
+ getStorageInfo();
+ }
+
+ private void getMemoryInfo(ActivityManager activityManager) {
+ try {
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ activityManager.getMemoryInfo(memoryInfo);
+ mAvailableMemory = memoryInfo.availMem;
+ mTotalMemory = memoryInfo.totalMem;
+ } catch (Exception ignored) {
+ }
+ }
+
+ public void getStorageInfo() {
+ try {
+ File path = Environment.getDataDirectory();
+ StatFs stat = new StatFs(path.getPath());
+ long blockSize = stat.getBlockSizeLong();
+ long availableBlocks = stat.getAvailableBlocksLong();
+ long totalBlocks = stat.getBlockCountLong();
+ mTotalStorage = totalBlocks * blockSize;
+ mAvailableStorage = availableBlocks * blockSize;
+ } catch (Exception ignored) {
+ }
+ }
+
+ public long getTotalMemory() {
+ return mTotalMemory;
+ }
+
+ public long getAvailableMemory() {
+ return mAvailableMemory;
+ }
+
+ public long getAvailableStorage() {
+ return mAvailableStorage;
+ }
+
+ public long getTotalStorage() {
+ return mTotalStorage;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/RootCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/RootCollector.java
new file mode 100644
index 0000000..e691ca7
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/RootCollector.java
@@ -0,0 +1,31 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.text.TextUtils;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+ * @description: Root
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class RootCollector {
+
+ public boolean getRoot() {
+ Map envMap = System.getenv();
+ String path = envMap.get("PATH");
+ if (TextUtils.isEmpty(path)) {
+ return false;
+ }
+ String[] paths = path.split(":");
+ for (String suDir : paths) {
+ String suPath = suDir + File.separator + "su";
+ File file = new File(suPath);
+ if (file.exists()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SensorsInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SensorsInfoCollector.java
new file mode 100644
index 0000000..eca1c79
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SensorsInfoCollector.java
@@ -0,0 +1,35 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @description: Sensors Info
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class SensorsInfoCollector {
+
+ private SensorManager mSensorManager;
+
+ public SensorsInfoCollector(SensorManager sensorManager) {
+ mSensorManager = sensorManager;
+ }
+
+ public String getSensorList() {
+ try {
+ List sensorInfos = new ArrayList<>();
+ List sensorList = mSensorManager.getSensorList(Sensor.TYPE_ALL);
+ for (Sensor sensor : sensorList) {
+ sensorInfos.add(sensor.getName() + ":" + sensor.getVendor());
+ }
+ return TextUtils.join(",", sensorInfos);
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SettingInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SettingInfoCollector.java
new file mode 100644
index 0000000..efea107
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SettingInfoCollector.java
@@ -0,0 +1,81 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.content.ContentResolver;
+import android.provider.Settings;
+
+/**
+ * @description: Setting Info
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class SettingInfoCollector {
+ private ContentResolver mContentResolver;
+
+ public SettingInfoCollector(ContentResolver contentResolver) {
+ mContentResolver = contentResolver;
+ }
+
+ public String getAdbEnabled() {
+ return extractGlobalSettingsParam(Settings.Global.ADB_ENABLED);
+ }
+
+ public String getDevelopmentSettingEnabled() {
+ return extractGlobalSettingsParam(Settings.Global.DEVELOPMENT_SETTINGS_ENABLED);
+ }
+
+ public String getHttpProxy() {
+ return extractGlobalSettingsParam(Settings.Global.HTTP_PROXY);
+ }
+
+ public String getDataRoaming() {
+ return extractGlobalSettingsParam(Settings.Global.DATA_ROAMING);
+ }
+
+ public String getAllowMockLocation() {
+ return extractSecureSettingsParam(Settings.Secure.ALLOW_MOCK_LOCATION);
+ }
+
+ public String getAccessibilityEnabled() {
+ return extractSecureSettingsParam(Settings.Secure.ACCESSIBILITY_ENABLED);
+ }
+
+ public String getDefaultInputMethod() {
+ return extractSecureSettingsParam(Settings.Secure.DEFAULT_INPUT_METHOD);
+ }
+
+ public String getTouchExplorationEnabled() {
+ return extractSecureSettingsParam(Settings.Secure.TOUCH_EXPLORATION_ENABLED);
+ }
+
+ public String getScreenBrightness() {
+ return extractSystemSettingsParam(Settings.System.SCREEN_BRIGHTNESS);
+ }
+
+ public String getScreenOffTimeout() {
+ return extractSystemSettingsParam(Settings.System.SCREEN_OFF_TIMEOUT);
+ }
+
+ public String extractGlobalSettingsParam(String key) {
+ try {
+ return Settings.Global.getString(mContentResolver, key);
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String extractSecureSettingsParam(String key) {
+ try {
+ return Settings.Secure.getString(mContentResolver, key);
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+
+ public String extractSystemSettingsParam(String key) {
+ try {
+ return Settings.System.getString(mContentResolver, key);
+ } catch (Exception ignored) {
+ }
+ return "";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SystemPropertyInfoCollector.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SystemPropertyInfoCollector.java
new file mode 100644
index 0000000..285d638
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/collectors/SystemPropertyInfoCollector.java
@@ -0,0 +1,31 @@
+package cn.tongdun.mobrisk.core.collectors;
+
+import android.annotation.SuppressLint;
+
+/**
+ * @description: SystemProperyInfoCollector
+ * @author: wuzuchang
+ * @date: 2022/12/8
+ */
+public class SystemPropertyInfoCollector {
+
+
+ public SystemPropertyInfoCollector() {
+ }
+
+ public String getMetaDigest(){
+ return getProperty("ro.boot.vbmeta.digest");
+ }
+
+ public String getProperty(String propertyName) {
+
+ String value = "";
+ try {
+ @SuppressLint("PrivateApi")
+ Class> systemPropertyClass = Class.forName("android.os.SystemProperties");
+ value = (String) systemPropertyClass.getMethod("get", String.class).invoke(systemPropertyClass, propertyName);
+ } catch (Exception ignored) {
+ }
+ return value;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/Constants.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/Constants.java
new file mode 100644
index 0000000..1057951
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/Constants.java
@@ -0,0 +1,62 @@
+package cn.tongdun.mobrisk.core.utils;
+
+/**
+ * @description: constant
+ * @author: wuzuchang
+ * @date: 2022/12/7
+ */
+public class Constants {
+ public static final String KEY_DEVICE_ID = "device_id";
+ public static final String KEY_DEVICE_RISK_LABEL = "device_risk_label";
+ public static final String KEY_DEVICE_DETAIL = "device_detail";
+ public static final String KEY_ANDROID_ID = "androidId";
+ public static final String KEY_GSF_ID = "gsfId";
+ public static final String KEY_MEDIA_DRM_ID = "mediaDrmId";
+ public static final String KEY_VB_META_DIGEST = "vbMetaDigest";
+ public static final String KEY_MODEL = "model";
+ public static final String KEY_MANUFACTURER = "manufacturer";
+ public static final String KEY_ANDROID_VERSION = "androidVersion";
+ public static final String KEY_SDK_VERSION = "sdkVersion";
+ public static final String KEY_KERNEL_VERSION = "kernelVersion";
+ public static final String KEY_FINGERPRINT = "fingerprint";
+ public static final String KEY_HARDWARE = "HARDWARE";
+ public static final String KEY_DISPLAY = "display";
+ public static final String KEY_HOST = "host";
+ public static final String KEY_BRAND = "brand";
+ public static final String KEY_PRODUCT = "product";
+ public static final String KEY_BATTERY_HEALTH_STATUS = "batteryHealthStatus";
+ public static final String KEY_BATTERY_STATUS = "batteryStatus";
+ public static final String KEY_BATTERY_LEVEL = "batteryLevel";
+ public static final String KEY_BATTERY_TEMP = "batteryTemp";
+ public static final String KEY_BATTERY_TOTAL_CAPACITY = "batteryTotalCapacity";
+ public static final String KEY_CPU_PROCESSOR = "cpuProcessor";
+ public static final String KEY_CPU_HARDWARE = "cpuHardware";
+ public static final String KEY_CORES_COUNT = "coresCount";
+ public static final String KEY_ABI_TYPE = "abiType";
+ public static final String KEY_DEBUG = "debug";
+ public static final String KEY_MULTIPLE = "multiple";
+ public static final String KEY_ROOT = "root";
+ public static final String KEY_COUNTRY = "country";
+ public static final String KEY_LANGUAGE = "language";
+ public static final String KEY_TIMEZONE = "timezone";
+ public static final String KEY_TOTAL_MEMORY = "totalMemory";
+ public static final String KEY_AVAILABLE_MEMORY = "availableMemory";
+ public static final String KEY_TOTAL_STORAGE = "totalStorage";
+ public static final String KEY_AVAILABLE_STORAGE = "availableStorage";
+ public static final String KEY_APP_LIST = "appList";
+ public static final String KEY_SYSTEM_APP_LIST = "systemAppList";
+ public static final String KEY_SENSORS_INFO = "sensorsInfo";
+ public static final String KEY_ADB_ENABLED = "adbEnabled";
+ public static final String KEY_DEVELOPMENT_SETTING_ENABLED = "developmentSettingEnabled";
+ public static final String KEY_HTTP_PROXY = "httpProxy";
+ public static final String KEY_DATA_ROAMING = "dataRoaming";
+ public static final String KEY_ALLOW_MOCK_LOCATION = "allowMockLocation";
+ public static final String KEY_ACCESSIBILITY_ENABLED = "accessibilityEnabled";
+ public static final String KEY_DEFAULT_INPUTMETHOD = "defaultInputMethod";
+ public static final String KEY_TOUCH_EXPLORATION_ENABLED = "touchExplorationEnabled";
+ public static final String KEY_SCREEN_BRIGHTNESS = "screenBrightness";
+ public static final String KEY_SCREEN_OFF_TIMEOUT = "screenOffTimeout";
+ public static final String KEY_SCREEN_RESOLUTION = "screenResolution";
+ public static final String KEY_FILES_ABSOLUTE_PATH = "filesAbsolutePath";
+ public static final String KEY_PACKAGE_NAME = "packageName";
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/DeviceInfoUtils.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/DeviceInfoUtils.java
new file mode 100644
index 0000000..869b45b
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/DeviceInfoUtils.java
@@ -0,0 +1,79 @@
+package cn.tongdun.mobrisk.core.utils;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.lang.reflect.Field;
+
+import cn.tongdun.mobrisk.beans.DeviceInfo;
+
+/**
+ * @description: format device info
+ * @author: wuzuchang
+ * @date: 2022/12/7
+ */
+public class DeviceInfoUtils {
+
+ public static JSONObject format(String deviceId, DeviceInfo deviceInfo) {
+ if (deviceInfo == null) {
+ return new JSONObject();
+ }
+ JSONObject result = new JSONObject();
+ JSONObject detail = new JSONObject();
+ Field[] fields = deviceInfo.getClass().getDeclaredFields();
+ for (Field field : fields) {
+ try {
+ field.setAccessible(true);
+ String key = field.getName();
+ Object object = field.get(deviceInfo);
+ detail.put(key, String.valueOf(object));
+ } catch (Exception ignored) {
+ }
+ }
+ try {
+ result.put(Constants.KEY_DEVICE_ID, deviceId);
+ result.put(Constants.KEY_DEVICE_RISK_LABEL, deviceRisk(detail));
+ result.put(Constants.KEY_DEVICE_DETAIL, detail);
+ } catch (JSONException ignored) {
+ }
+ return result;
+ }
+
+ private static JSONObject deviceRisk(JSONObject data) {
+ JSONObject risk = new JSONObject();
+ if (data == null) {
+ return risk;
+ }
+ try {
+ risk.put(Constants.KEY_ROOT, data.opt(Constants.KEY_ROOT));
+ risk.put(Constants.KEY_DEBUG, data.opt(Constants.KEY_DEBUG));
+ risk.put(Constants.KEY_MULTIPLE, getMultiple(data));
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return risk;
+ }
+
+ private static String getMultiple(JSONObject data) {
+
+ if (data == null) {
+ return "false";
+ }
+ String filePath = data.optString(Constants.KEY_FILES_ABSOLUTE_PATH);
+ String packageName = data.optString(Constants.KEY_PACKAGE_NAME);
+ String dir = filePath.split(packageName)[0];
+ int riskLength = 3;
+ if (dir.startsWith(File.separator)) {
+ riskLength = 4;
+ }
+ String[] dirs = dir.split(File.separator);
+ if (dirs.length > riskLength) {
+ return "true";
+ }
+ if (!"0".equals(dirs[dirs.length - 1])) {
+ return "true";
+ }
+ return "false";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/FileUtils.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/FileUtils.java
new file mode 100644
index 0000000..30a843e
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/FileUtils.java
@@ -0,0 +1,62 @@
+package cn.tongdun.mobrisk.core.utils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @description: file util
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class FileUtils {
+
+ public static Map readFileByKey(String fileName, List keys, String sep) {
+ Map info = new HashMap<>();
+ BufferedReader br = null;
+ if ((fileName != null) && (keys != null) && (new File(fileName).exists())) {
+ try {
+ br = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), StandardCharsets.UTF_8));
+ String raw;
+ while ((raw = br.readLine()) != null) {
+ String paramValue = "";
+ if (!StringUtils.isEmpty(sep)) {
+ List params;
+ String paramName;
+ params = StringUtils.splitNonRegex(raw, sep);
+ if (!params.isEmpty() && (paramName = params.get(0).trim()).length() != 0) {
+ if (keys.contains(paramName)) {
+ if (params.size() > 1) {
+ paramValue = params.get(1).trim();
+ info.put(paramName, paramValue);
+ }
+ }
+ }
+ } else {
+ for (String k : keys) {
+ if (raw.contains(k)) {
+ info.put(k, raw);
+ }
+ }
+ }
+ }
+ br.close();
+ } catch (Exception ignored) {
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+ return info;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/LogUtils.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/LogUtils.java
new file mode 100644
index 0000000..67e10e8
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/LogUtils.java
@@ -0,0 +1,21 @@
+package cn.tongdun.mobrisk.core.utils;
+
+import android.util.Log;
+
+/**
+ * @description: log util
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class LogUtils {
+
+ private static final String LOG_TAG = "TrustDevice";
+
+ public static void d(String message) {
+ Log.d(LOG_TAG, message);
+ }
+
+ public static void e(String message) {
+ Log.e(LOG_TAG, message);
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/MessageDigestUtils.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/MessageDigestUtils.java
new file mode 100644
index 0000000..b037a6e
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/MessageDigestUtils.java
@@ -0,0 +1,32 @@
+package cn.tongdun.mobrisk.core.utils;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+
+/**
+ * @description: Message Digest utils
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class MessageDigestUtils {
+
+ public static String hash(String algorithm, byte[] bytes) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ md.update(bytes);
+ return StringUtils.byteToHexString(md.digest());
+ } catch (Throwable ignored) {
+ }
+ return "";
+ }
+
+ public static String hash(String algorithm, String str) {
+ try {
+ MessageDigest md = MessageDigest.getInstance(algorithm);
+ md.update(str.getBytes(StandardCharsets.UTF_8));
+ return StringUtils.byteToHexString(md.digest());
+ } catch (Throwable ignored) {
+ }
+ return "";
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/StringUtils.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/StringUtils.java
new file mode 100644
index 0000000..5314187
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/core/utils/StringUtils.java
@@ -0,0 +1,53 @@
+package cn.tongdun.mobrisk.core.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @description: string util
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+public class StringUtils {
+
+ public static boolean isEmpty(String str) {
+ return ((str == null) || ("".equals(str.trim()) || str.length() == 0));
+ }
+
+ public static List splitNonRegex(String input, String delim) {
+ List list = new ArrayList<>();
+ if (input == null || input.length() == 0) {
+ return list;
+ }
+ if (delim == null || delim.length() == 0) {
+ list.add(input);
+ return list;
+ }
+ if(input.equals(delim)){
+ return list;
+ }
+ while (true) {
+ int index;
+ index = input.indexOf(delim);
+ if (index == -1) {
+ if (!isEmpty(input)) {
+ list.add(input);
+ }
+ return list;
+ }
+ if (index != 0) {
+ list.add(input.substring(0, index));
+ }
+ input = input.substring(index + delim.length());
+ }
+ }
+
+ public static String byteToHexString(byte[] data){
+ StringBuilder hex = new StringBuilder();
+ // Iterating through each byte in the array
+ for (byte i : data) {
+ hex.append(String.format("%02X", i));
+ }
+ return hex.toString();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/InfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/InfoProvider.java
new file mode 100644
index 0000000..27d573c
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/InfoProvider.java
@@ -0,0 +1,17 @@
+package cn.tongdun.mobrisk.providers;
+
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * @description: Provider
+ * @author: wuzuchang
+ * @date: 2022/12/8
+ */
+@Deprecated(since = "pro no such class")
+public abstract class InfoProvider {
+
+ public abstract String getProviderName();
+ public abstract List> getRawData();
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/RawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/RawData.java
new file mode 100644
index 0000000..e725250
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/RawData.java
@@ -0,0 +1,15 @@
+package cn.tongdun.mobrisk.providers;
+
+import android.util.Pair;
+
+import java.util.List;
+
+/**
+ * @description: RawData
+ * @author: wuzuchang
+ * @date: 2022/12/8
+ */
+@Deprecated(since = "pro no such class")
+public abstract class RawData {
+ public abstract List> loadData();
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/applist/AppListProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/applist/AppListProvider.java
new file mode 100644
index 0000000..99a2d2a
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/applist/AppListProvider.java
@@ -0,0 +1,48 @@
+package cn.tongdun.mobrisk.providers.applist;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: Risk info Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class AppListProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+
+ public AppListProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getAppList() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_APP_LIST);
+ }
+
+ private String getSystemAppList() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_SYSTEM_APP_LIST);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "App list";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new AppListRawData(getAppList(), getSystemAppList()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/applist/AppListRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/applist/AppListRawData.java
new file mode 100644
index 0000000..cbe4319
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/applist/AppListRawData.java
@@ -0,0 +1,40 @@
+package cn.tongdun.mobrisk.providers.applist;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: RiskInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class AppListRawData extends RawData {
+ private String appList;
+ private String systemAppList;
+
+ public AppListRawData(String appList, String systemAppList) {
+ this.appList = appList;
+ this.systemAppList = systemAppList;
+ }
+
+ private String[] getAppList() {
+ return appList.split(",");
+ }
+
+ private String[] getSystemAppList() {
+ return systemAppList.split(",");
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("App list", getAppList()));
+ data.add(new Pair<>("System app list", getSystemAppList()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/battery/BatteryInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/battery/BatteryInfoProvider.java
new file mode 100644
index 0000000..d08e80e
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/battery/BatteryInfoProvider.java
@@ -0,0 +1,70 @@
+package cn.tongdun.mobrisk.providers.battery;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: BatteryInfo Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class BatteryInfoProvider extends InfoProvider {
+
+ private final JSONObject mDeviceInfo;
+
+ public BatteryInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Battery info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new BatteryInfoRawData(getHealth(), getStatus(), getLevel(), getTemp(), getTotalCapacity()).loadData();
+ }
+
+ private String getHealth() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_BATTERY_HEALTH_STATUS);
+ }
+
+ private String getStatus() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_BATTERY_STATUS);
+ }
+
+ private String getLevel() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_BATTERY_LEVEL);
+ }
+
+ private String getTemp() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_BATTERY_TEMP);
+ }
+
+ private String getTotalCapacity() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_BATTERY_TOTAL_CAPACITY);
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/battery/BatteryInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/battery/BatteryInfoRawData.java
new file mode 100644
index 0000000..96ede59
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/battery/BatteryInfoRawData.java
@@ -0,0 +1,61 @@
+package cn.tongdun.mobrisk.providers.battery;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: BatteryInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class BatteryInfoRawData extends RawData {
+ private String health;
+ private String status;
+ private String level;
+ private String temp;
+ private String totalCapacity;
+
+ public BatteryInfoRawData(String health, String status, String level, String temp, String totalCapacity) {
+ this.health = health;
+ this.status = status;
+ this.level = level;
+ this.temp = temp;
+ this.totalCapacity = totalCapacity;
+ }
+
+ private String getHealth() {
+ return health;
+ }
+
+ private String getStatus() {
+ return status;
+ }
+
+ private String getLevel() {
+ return level;
+ }
+
+ private String getTemp() {
+ return temp;
+ }
+
+ private String getTotalCapacity() {
+ return totalCapacity;
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("health", getHealth()));
+ data.add(new Pair<>("status", getStatus()));
+ data.add(new Pair<>("level", getLevel()));
+ data.add(new Pair<>("temp", getTemp()));
+ data.add(new Pair<>("total capacity", getTotalCapacity()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/build/BuildInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/build/BuildInfoProvider.java
new file mode 100644
index 0000000..40b17e3
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/build/BuildInfoProvider.java
@@ -0,0 +1,90 @@
+package cn.tongdun.mobrisk.providers.build;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: BuildInfo Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class BuildInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+
+ public BuildInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getModel() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_MODEL);
+ }
+
+ private String getBrand() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_BRAND);
+ }
+
+ private String getManufacturer() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_MANUFACTURER);
+ }
+
+ private String getAndroidVersion() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_ANDROID_VERSION);
+ }
+
+ public String getSdkVersion() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_SDK_VERSION);
+ }
+
+ private String getKernelVersion() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_KERNEL_VERSION);
+ }
+
+ private String getFingerprint() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_FINGERPRINT);
+ }
+
+ private String getHost() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_HOST);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Build info ";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new BuildInfoRawData(getModel(), getBrand(), getManufacturer(), getAndroidVersion(), getSdkVersion(), getKernelVersion(), getFingerprint(), getHost()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/build/BuildInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/build/BuildInfoRawData.java
new file mode 100644
index 0000000..a53426d
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/build/BuildInfoRawData.java
@@ -0,0 +1,82 @@
+package cn.tongdun.mobrisk.providers.build;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: BuildInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class BuildInfoRawData extends RawData {
+ private String model;
+ private String brand;
+ private String manufacturer;
+ private String androidVersion;
+ private String sdkVersion;
+ private String kernelVersion;
+ private String fingerprint;
+ private String host;
+
+ public BuildInfoRawData(String model,String brand, String manufacturer, String androidVersion, String sdkVersion, String kernelVersion, String fingerprint, String host) {
+ this.model = model;
+ this.brand = brand;
+ this.manufacturer = manufacturer;
+ this.androidVersion = androidVersion;
+ this.sdkVersion = sdkVersion;
+ this.kernelVersion = kernelVersion;
+ this.fingerprint = fingerprint;
+ this.host = host;
+ }
+
+ private String getModel() {
+ return model;
+ }
+
+ private String getBrand() {
+ return brand;
+ }
+
+ private String getManufacturer() {
+ return manufacturer;
+ }
+
+ private String getAndroidVersion() {
+ return androidVersion;
+ }
+
+ private String getSdkVersion() {
+ return sdkVersion;
+ }
+
+ private String getKernelVersion() {
+ return kernelVersion;
+ }
+
+ private String getFingerprint() {
+ return fingerprint;
+ }
+
+ private String getHost() {
+ return host;
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("model", getModel()));
+ data.add(new Pair<>("brand", getBrand()));
+ data.add(new Pair<>("manufacturer", getManufacturer()));
+ data.add(new Pair<>("android version", getAndroidVersion()));
+ data.add(new Pair<>("sdk version", getSdkVersion()));
+ data.add(new Pair<>("kernel version", getKernelVersion()));
+ data.add(new Pair<>("fingerprint", getFingerprint()));
+ data.add(new Pair<>("host", getHost()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/cpu/CpuInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/cpu/CpuInfoProvider.java
new file mode 100644
index 0000000..bfb6923
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/cpu/CpuInfoProvider.java
@@ -0,0 +1,62 @@
+package cn.tongdun.mobrisk.providers.cpu;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: CpuInfo Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class CpuInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+
+ public CpuInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getCpuHardware() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_CPU_HARDWARE);
+ }
+
+ private String getCpuProcessor() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_CPU_PROCESSOR);
+ }
+
+ private String getAbiType() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_ABI_TYPE);
+ }
+
+ private String getCoresCount() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_CORES_COUNT);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Cpu info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new CpuInfoRawData(getCpuHardware(), getCpuProcessor(), getAbiType(), getCoresCount()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/cpu/CpuInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/cpu/CpuInfoRawData.java
new file mode 100644
index 0000000..6168c73
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/cpu/CpuInfoRawData.java
@@ -0,0 +1,54 @@
+package cn.tongdun.mobrisk.providers.cpu;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: CpuInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class CpuInfoRawData extends RawData {
+ private String cpuHardware;
+ private String cpuProcessor;
+ private String abiType;
+ private String coresCount;
+
+ public CpuInfoRawData(String cpuHardware, String cpuProcessor, String abiType, String coresCount) {
+ this.cpuHardware = cpuHardware;
+ this.cpuProcessor = cpuProcessor;
+ this.abiType = abiType;
+ this.coresCount = coresCount;
+ }
+
+ private String getCpuHardware() {
+ return cpuHardware;
+ }
+
+ private String getCpuProcessor() {
+ return cpuProcessor;
+ }
+
+ private String getAbiType() {
+ return abiType;
+ }
+
+ private String getCoresCount() {
+ return coresCount;
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("hardware", getCpuHardware()));
+ data.add(new Pair<>("processor", getCpuProcessor()));
+ data.add(new Pair<>("abi type", getAbiType()));
+ data.add(new Pair<>("cores count", getCoresCount()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/device_id/DeviceIdProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/device_id/DeviceIdProvider.java
new file mode 100644
index 0000000..e31f977
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/device_id/DeviceIdProvider.java
@@ -0,0 +1,85 @@
+package cn.tongdun.mobrisk.providers.device_id;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: DeviceId Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class DeviceIdProvider extends InfoProvider {
+
+ private JSONObject mDeviceInfo;
+
+ public DeviceIdProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo;
+ }
+
+ private String getDeviceId() {
+
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_DEVICE_ID);
+ }
+
+ private String getAndroidId() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ JSONObject deviceDetail = mDeviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ if (deviceDetail == null) {
+ return "";
+ }
+ return getData(Constants.KEY_ANDROID_ID);
+ }
+
+ private String getGsfId() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ JSONObject deviceDetail = mDeviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ if (deviceDetail == null) {
+ return "";
+ }
+ return getData(Constants.KEY_GSF_ID);
+ }
+
+ private String getMediaDrmId() {
+ return getData(Constants.KEY_MEDIA_DRM_ID);
+ }
+
+ private String getVbMetaDigest() {
+ return getData(Constants.KEY_VB_META_DIGEST);
+ }
+
+
+ private String getData(String Key) {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ JSONObject deviceDetail = mDeviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ if (deviceDetail == null) {
+ return "";
+ }
+ return deviceDetail.optString(Key);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Device id";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new DeviceIdRawData(getDeviceId(), getAndroidId(), getGsfId(), getMediaDrmId(), getVbMetaDigest()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/device_id/DeviceIdRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/device_id/DeviceIdRawData.java
new file mode 100644
index 0000000..4b34cfb
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/device_id/DeviceIdRawData.java
@@ -0,0 +1,66 @@
+package cn.tongdun.mobrisk.providers.device_id;
+
+import android.text.TextUtils;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: DeviceIdRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class DeviceIdRawData extends RawData {
+ private String deviceId;
+ private String androidId;
+ private String gsfId;
+ private String mediaDrmId;
+ private String vbMetaDigest;
+
+ public DeviceIdRawData(String deviceId, String android_id, String gsf_id, String mediaDrm_id, String vb_meta_digest) {
+ this.deviceId = deviceId;
+ this.androidId = android_id;
+ this.gsfId = gsf_id;
+ this.mediaDrmId = mediaDrm_id;
+ this.vbMetaDigest = vb_meta_digest;
+ }
+
+ private String getDeviceId() {
+ return deviceId;
+ }
+
+ private String getAndroidId() {
+ return androidId;
+ }
+
+ private String getGsfId() {
+ if (TextUtils.isEmpty(gsfId) || "null".equals(gsfId)) {
+ return "";
+ }
+ return gsfId;
+ }
+
+ private String getMediaDrmId() {
+ return mediaDrmId;
+ }
+
+ private String getVbMetaDigest() {
+ return vbMetaDigest;
+ }
+
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("device id", getDeviceId()));
+ data.add(new Pair<>("android id", getAndroidId()));
+ data.add(new Pair<>("gsf id", getGsfId()));
+ data.add(new Pair<>("media drm id", getMediaDrmId()));
+ data.add(new Pair<>("vbmeta digest", getVbMetaDigest()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/memory/MemoryInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/memory/MemoryInfoProvider.java
new file mode 100644
index 0000000..47cf06a
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/memory/MemoryInfoProvider.java
@@ -0,0 +1,61 @@
+package cn.tongdun.mobrisk.providers.memory;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: Memory info Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class MemoryInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+ public MemoryInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getTotalMemory() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_TOTAL_MEMORY);
+ }
+
+ private String getAvailableMemory() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_AVAILABLE_MEMORY);
+ }
+
+ private String getTotalStorage() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_TOTAL_STORAGE);
+ }
+
+ private String getAvailableStorage() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_AVAILABLE_STORAGE);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Memory info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new MemoryInfoRawData(getTotalMemory(), getAvailableMemory(),getTotalStorage(),getAvailableStorage()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/memory/MemoryInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/memory/MemoryInfoRawData.java
new file mode 100644
index 0000000..38aa49d
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/memory/MemoryInfoRawData.java
@@ -0,0 +1,54 @@
+package cn.tongdun.mobrisk.providers.memory;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: MemoryInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class MemoryInfoRawData extends RawData {
+ String totalMemory;
+ String availableMemory;
+ String totalStorage;
+ String availableStorage;
+
+ public MemoryInfoRawData(String totalMemory, String availableMemory, String totalStorage, String availableStorage) {
+ this.totalMemory = totalMemory;
+ this.availableMemory = availableMemory;
+ this.totalStorage = totalStorage;
+ this.availableStorage = availableStorage;
+ }
+
+ private String getTotalMemory() {
+ return totalMemory;
+ }
+
+ private String getAvailableMemory() {
+ return availableMemory;
+ }
+
+ private String getTotalStorage() {
+ return totalStorage;
+ }
+
+ private String getAvailableStorage() {
+ return availableStorage;
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("total memory", getTotalMemory()));
+ data.add(new Pair<>("available memory", getAvailableMemory()));
+ data.add(new Pair<>("total storage", getTotalStorage()));
+ data.add(new Pair<>("available storage", getAvailableStorage()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/risk/RiskInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/risk/RiskInfoProvider.java
new file mode 100644
index 0000000..bf4bb4d
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/risk/RiskInfoProvider.java
@@ -0,0 +1,55 @@
+package cn.tongdun.mobrisk.providers.risk;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: Risk info Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class RiskInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+
+ public RiskInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_RISK_LABEL);
+ }
+
+ private String getRoot() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_ROOT);
+ }
+
+ private String getDebug() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_DEBUG);
+ }
+
+ private String getMultiple() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_MULTIPLE);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Risk info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new RiskInfoRawData(getRoot(), getDebug(), getMultiple()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/risk/RiskInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/risk/RiskInfoRawData.java
new file mode 100644
index 0000000..d65870b
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/risk/RiskInfoRawData.java
@@ -0,0 +1,49 @@
+package cn.tongdun.mobrisk.providers.risk;
+
+import android.util.Pair;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: RiskInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class RiskInfoRawData extends RawData {
+ private String root;
+ private String debug;
+ private String multiple;
+
+ public RiskInfoRawData(String root, String debug, String multiple) {
+ this.root = root;
+ this.debug = debug;
+ this.multiple = multiple;
+ }
+
+ private String getRoot() {
+ return root;
+ }
+
+ private String getDebug() {
+ return debug;
+ }
+
+ private String getMultiple() {
+
+ return multiple;
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("root", getRoot()));
+ data.add(new Pair<>("debug", getDebug()));
+ data.add(new Pair<>("multiple", getMultiple()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/screen/ScreenInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/screen/ScreenInfoProvider.java
new file mode 100644
index 0000000..86890f1
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/screen/ScreenInfoProvider.java
@@ -0,0 +1,54 @@
+package cn.tongdun.mobrisk.providers.screen;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: Screen info Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class ScreenInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+ public ScreenInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getScreenResolution() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_SCREEN_RESOLUTION);
+ }
+
+ private String getScreenBrightness() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_SCREEN_BRIGHTNESS);
+ }
+
+ private String getScreenOffTimeout() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_SCREEN_OFF_TIMEOUT);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Screen info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new ScreenInfoRawData(getScreenResolution(), getScreenBrightness(), getScreenOffTimeout()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/screen/ScreenInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/screen/ScreenInfoRawData.java
new file mode 100644
index 0000000..7eb4725
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/screen/ScreenInfoRawData.java
@@ -0,0 +1,47 @@
+package cn.tongdun.mobrisk.providers.screen;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: ScreenInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class ScreenInfoRawData extends RawData {
+ private String screenResolution;
+ private String screenBrightness;
+ private String screenOffTimeout;
+
+ public ScreenInfoRawData(String screenResolution, String screenBrightness, String screenOffTimeout) {
+ this.screenResolution = screenResolution;
+ this.screenBrightness = screenBrightness;
+ this.screenOffTimeout = screenOffTimeout;
+ }
+
+ private String getScreenResolution() {
+ return screenResolution;
+ }
+
+ private String getScreenBrightness() {
+ return screenBrightness;
+ }
+
+ private String getScreenOffTimeout() {
+ return screenOffTimeout;
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("screen resolution", getScreenResolution()));
+ data.add(new Pair<>("screen brightness", getScreenBrightness()));
+ data.add(new Pair<>("screen Off timeout", getScreenOffTimeout()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/sensor/SensorInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/sensor/SensorInfoProvider.java
new file mode 100644
index 0000000..2a773d0
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/sensor/SensorInfoProvider.java
@@ -0,0 +1,41 @@
+package cn.tongdun.mobrisk.providers.sensor;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: Sensor info provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class SensorInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+
+ public SensorInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getSensorInfo() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_SENSORS_INFO);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Sensor info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new SensorInfoRawData(getSensorInfo()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/sensor/SensorInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/sensor/SensorInfoRawData.java
new file mode 100644
index 0000000..ef3b31f
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/sensor/SensorInfoRawData.java
@@ -0,0 +1,38 @@
+package cn.tongdun.mobrisk.providers.sensor;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: SensorInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class SensorInfoRawData extends RawData {
+ private String sensorInfo;
+
+ public SensorInfoRawData(String sensorInfo) {
+ this.sensorInfo = sensorInfo;
+ }
+
+ private String[] getSensorInfo() {
+ return sensorInfo.split(",");
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ for (String sensorInfo : getSensorInfo()) {
+ String[] sensor = sensorInfo.split(":");
+ if (sensor.length >= 2) {
+ data.add(new Pair<>(sensor[0], sensor[1]));
+ }
+ }
+ return data;
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/setting/SettingInfoProvider.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/setting/SettingInfoProvider.java
new file mode 100644
index 0000000..49e2055
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/setting/SettingInfoProvider.java
@@ -0,0 +1,90 @@
+package cn.tongdun.mobrisk.providers.setting;
+
+import android.util.Pair;
+
+import org.json.JSONObject;
+
+import java.util.List;
+
+import cn.tongdun.mobrisk.core.utils.Constants;
+import cn.tongdun.mobrisk.providers.InfoProvider;
+
+/**
+ * @description: Setting Provider
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class SettingInfoProvider extends InfoProvider {
+ private final JSONObject mDeviceInfo;
+
+ public SettingInfoProvider(JSONObject deviceInfo) {
+ mDeviceInfo = deviceInfo.optJSONObject(Constants.KEY_DEVICE_DETAIL);
+ }
+
+ private String getAdbEnable() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_ADB_ENABLED);
+ }
+
+ private String getDevelopmentSettingEnabled() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_DEVELOPMENT_SETTING_ENABLED);
+ }
+
+ private String getHttpProxy() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_HTTP_PROXY);
+ }
+
+ private String getDataRoaming() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_DATA_ROAMING);
+ }
+
+ private String getAllowMockLocation() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_ALLOW_MOCK_LOCATION);
+ }
+
+ private String getAccessibilityEnabled() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_ACCESSIBILITY_ENABLED);
+ }
+
+ private String getDefaultInputMethod() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_DEFAULT_INPUTMETHOD);
+ }
+
+ private String getTouchExplorationEnabled() {
+ if (mDeviceInfo == null) {
+ return "";
+ }
+ return mDeviceInfo.optString(Constants.KEY_TOUCH_EXPLORATION_ENABLED);
+ }
+
+ @Override
+ public String getProviderName() {
+ return "Setting info";
+ }
+
+ @Override
+ public List> getRawData() {
+ return new SettingInfoRawData(getAdbEnable(), getDevelopmentSettingEnabled(), getHttpProxy(), getDataRoaming(), getAllowMockLocation(), getAccessibilityEnabled(), getDefaultInputMethod(), getTouchExplorationEnabled()).loadData();
+ }
+}
diff --git a/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/setting/SettingInfoRawData.java b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/setting/SettingInfoRawData.java
new file mode 100644
index 0000000..c5e6575
--- /dev/null
+++ b/trustdevice/src/main/java/cn/tongdun/mobrisk/providers/setting/SettingInfoRawData.java
@@ -0,0 +1,86 @@
+package cn.tongdun.mobrisk.providers.setting;
+
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import cn.tongdun.mobrisk.providers.RawData;
+
+/**
+ * @description: SettingInfoRawData
+ * @author: wuzuchang
+ * @date: 2022/12/6
+ */
+@Deprecated(since = "pro no such class")
+public class SettingInfoRawData extends RawData {
+ private String adbEnable;
+ private String developmentSettingEnabled;
+ private String httpProxy;
+ private String dataRoaming;
+ private String allowMockLocation;
+ private String accessibilityEnabled;
+ private String defaultInputMethod;
+ private String touchExplorationEnabled;
+
+ public SettingInfoRawData(String adbEnable, String developmentSettingEnabled, String httpProxy, String dataRoaming, String allowMockLocation, String accessibilityEnabled, String defaultInputMethod, String touchExplorationEnabled) {
+ this.adbEnable = adbEnable;
+ this.developmentSettingEnabled = developmentSettingEnabled;
+ this.httpProxy = httpProxy;
+ this.dataRoaming = dataRoaming;
+ this.allowMockLocation = allowMockLocation;
+ this.accessibilityEnabled = accessibilityEnabled;
+ this.defaultInputMethod = defaultInputMethod;
+ this.touchExplorationEnabled = touchExplorationEnabled;
+ }
+
+ private String getAdbEnable() {
+ return formatSwitch(adbEnable);
+ }
+
+ private String getDevelopmentSettingEnabled() {
+ return formatSwitch(developmentSettingEnabled);
+ }
+
+ private String getHttpProxy() {
+ return httpProxy;
+ }
+
+ private String getDataRoaming() {
+ return formatSwitch(dataRoaming);
+ }
+
+ private String getAllowMockLocation() {
+ return formatSwitch(allowMockLocation);
+ }
+
+ private String getAccessibilityEnabled() {
+ return formatSwitch(accessibilityEnabled);
+ }
+
+ private String getDefaultInputMethod() {
+ return defaultInputMethod;
+ }
+
+ private String getTouchExplorationEnabled() {
+ return formatSwitch(touchExplorationEnabled);
+ }
+
+ private String formatSwitch(String data) {
+ return "1".equals(data) ? "open" : "close";
+ }
+
+ @Override
+ public List> loadData() {
+ List> data = new ArrayList<>();
+ data.add(new Pair<>("adb", getAdbEnable()));
+ data.add(new Pair<>("development setting", getDevelopmentSettingEnabled()));
+ data.add(new Pair<>("data roaming", getDataRoaming()));
+ data.add(new Pair<>("mock location", getAllowMockLocation()));
+ data.add(new Pair<>("accessibility", getAccessibilityEnabled()));
+ data.add(new Pair<>("touch exploration", getTouchExplorationEnabled()));
+ data.add(new Pair<>("http proxy", getHttpProxy()));
+ data.add(new Pair<>("default inputMethod", getDefaultInputMethod()));
+ return data;
+ }
+}
diff --git a/trustdevice/src/test/java/cn/tongdun/android/ExampleUnitTest.java b/trustdevice/src/test/java/cn/tongdun/android/ExampleUnitTest.java
new file mode 100644
index 0000000..ef6e78b
--- /dev/null
+++ b/trustdevice/src/test/java/cn/tongdun/android/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package cn.tongdun.android;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file