Skip to content

Commit

Permalink
Merge pull request #60 from tianma8023/dev
Browse files Browse the repository at this point in the history
bump new version of 2.5.0
  • Loading branch information
tianma8023 authored Nov 6, 2023
2 parents fb2f4bb + 26365dd commit a7f9d84
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 31 deletions.
4 changes: 3 additions & 1 deletion LOG-CN.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# 更新日志
- 23.11.06 v2.5.0 需要重启
1. 变化: 适配 Android 14
- 22.09.15 v2.4.0 需要重启
1. 变化适配 Android 13,解决验证码无法自动输入问题
1. 变化: 适配 Android 13,解决验证码无法自动输入问题
- 22.05.25 v2.3.1 需要重启
1. 变化: 恢复 标记验证码已读 和 删除验证码短信 功能
2. 变化: 验证码历史记录支持复制短信文本 @fxdqe
Expand Down
2 changes: 2 additions & 0 deletions LOG-EN.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Update Logs
- 23.11.06 v2.5.0 Reboot required
1. Change: Adapt to Android 14.
- 22.09.15 v2.4.0 Reboot required
1. Change: Adapt to Android 13, fix the issue of cannot auto input SMS code
- 22.05.25 v2.3.1 Reboot required
Expand Down
24 changes: 13 additions & 11 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ def static releaseTime() {
return new Date().format("yyMMdd", TimeZone.default)
}

def VERSION_NAME = "2.4.0"
def VERSION_CODE = 50
def VERSION_NAME = "2.5.0"
def VERSION_CODE = 51

android {
compileSdkVersion 33
namespace 'com.github.tianma8023.xposed.smscode'

compileSdkVersion 34
defaultConfig {
applicationId "com.github.tianma8023.xposed.smscode"
minSdkVersion 23
Expand All @@ -28,10 +30,10 @@ android {

buildConfigField("String", "LOG_TAG", "\"XSmsCode\"")
buildConfigField("int", "MODULE_VERSION", "" + VERSION_CODE)
resConfigs 'en', 'zh-rCN', 'zh-rTW'

// vectorDrawables.generatedDensities = ['hdpi']

resConfigs("en", "zh-rCN", "zh-rTW")

javaCompileOptions {
annotationProcessorOptions {
Expand Down Expand Up @@ -144,12 +146,12 @@ ext {

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "androidx.appcompat:appcompat:1.4.1"
implementation "com.google.android.material:material:1.6.0" // material design support
implementation "androidx.recyclerview:recyclerview:1.2.1" // recycler view
implementation "androidx.browser:browser:1.4.0" // custom tabs
implementation "androidx.preference:preference:1.2.0" // preference support
implementation "androidx.constraintlayout:constraintlayout:2.1.3" // constraint layout
implementation "androidx.appcompat:appcompat:1.6.1"
implementation "com.google.android.material:material:1.10.0" // material design support
implementation "androidx.recyclerview:recyclerview:1.3.2" // recycler view
implementation "androidx.browser:browser:1.6.0" // custom tabs
implementation "androidx.preference:preference:1.2.1" // preference support
implementation "androidx.constraintlayout:constraintlayout:2.1.4" // constraint layout
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" // swipe refresh layout

// ButterKnife
Expand All @@ -158,7 +160,7 @@ dependencies {

// Xposed
compileOnly 'de.robv.android.xposed:api:82'
compileOnly 'de.robv.android.xposed:api:82:sources'
// compileOnly 'de.robv.android.xposed:api:82:sources'

// Material Dialogs
implementation "com.afollestad.material-dialogs:core:$materialDialogVersion"
Expand Down
3 changes: 1 addition & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.github.tianma8023.xposed.smscode">
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET"/>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,16 @@ public interface SmsCodeConst {
};

String VERIFICATION_KEYWORDS_REGEX =
/**/ "验证码|校验码|检验码|确认码|激活码|动态码|安全码" +
/**/ "|验证代码|校验代码|检验代码|激活代码|确认代码|动态代码|安全代码" +
/**/ "|登入码|认证码|识别码" +
/**/ "|短信口令|动态密码|交易码|上网密码|随机码|动态口令" +
/**/ "|驗證碼|校驗碼|檢驗碼|確認碼|激活碼|動態碼" +
/**/ "|驗證代碼|校驗代碼|檢驗代碼|確認代碼|激活代碼|動態代碼" +
/**/ "|登入碼|認證碼|識別碼" +
/**/ "|Code|code|CODE";
/**/ "验证码|校验码|检验码|确认码|激活码|动态码|安全码" +
/**/ "|验证代码|校验代码|检验代码|激活代码|确认代码|动态代码|安全代码" +
/**/ "|登入码|认证码|识别码" +
/**/ "|短信口令|动态密码|交易码|上网密码|随机码|动态口令" +
/**/ "|驗證碼|校驗碼|檢驗碼|確認碼|激活碼|動態碼" +
/**/ "|驗證代碼|校驗代碼|檢驗代碼|確認代碼|激活代碼|動態代碼" +
/**/ "|登入碼|認證碼|識別碼" +
/*English*/ "|Code|code|CODE" +
/*Russian*/ "|Код|код|КОД|Пароль|пароль|ПАРОЛЬ|Kod|kod|KOD" +
/*Vietnamese*/ "|Ma|Mã|OTP";

String[] VERIFICATION_KEY_WORDS_EN = {
"Code",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@ public class CopyCodeReceiver extends BroadcastReceiver {
private static final String ACTION_COPY_CODE = BuildConfig.APPLICATION_ID + ".ACTION_COPY_CODE";
private static final String EXTRA_KEY_CODE = "extra_key_code";

private static class CopyCodeReceiverHolder {
private static final CopyCodeReceiver INSTANCE = new CopyCodeReceiver();
}

public static CopyCodeReceiver newInstance() {
return CopyCodeReceiverHolder.INSTANCE;
}

public static Intent createIntent(String smsCode) {
Intent intent = new Intent(ACTION_COPY_CODE);
intent.putExtra(EXTRA_KEY_CODE, smsCode);
return intent;
}

public static void registerMe(Context context) {
CopyCodeReceiver receiver = new CopyCodeReceiver();
CopyCodeReceiver receiver = CopyCodeReceiver.newInstance();
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_COPY_CODE);
context.registerReceiver(receiver, filter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ private void hookSmsHandler(ClassLoader classloader) {
}

private void hookConstructor(ClassLoader classloader) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
// Android 14+
hookConstructor34(classloader);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Android 11+
hookConstructor30(classloader);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Expand All @@ -92,6 +95,23 @@ private void hookConstructor(ClassLoader classloader) {
}
}

// Android 14+
private void hookConstructor34(ClassLoader classLoader) {
XLog.i("Hooking InboundSmsHandler constructor for android v34+");
// XposedHelpers.findAndHookConstructor(SMS_HANDLER_CLASS, classLoader,
// /* name */ String.class,
// /* context */ Context.class,
// /* storageMonitor */ TELEPHONY_PACKAGE + ".SmsStorageMonitor",
// /* phone */ TELEPHONY_PACKAGE + ".Phone",
// /* cellBroadcastHandler */ TELEPHONY_PACKAGE + ".CellBroadcastHandler",
// /* smsDispatchersController */ TELEPHONY_PACKAGE + ".SmsDispatchersController",
// new ConstructorHook());
Class<?> smsHandlerClazz = XposedWrapper.findClass(SMS_HANDLER_CLASS, classLoader);
if (smsHandlerClazz != null) {
XposedBridge.hookAllConstructors(smsHandlerClazz, new ConstructorHook());
}
}

// Android 11+
private void hookConstructor30(ClassLoader classloader) {
XLog.i("Hooking InboundSmsHandler constructor for android v30+");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@ public void onLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
if (ANDROID_PACKAGE.equals(lpparam.packageName) && ANDROID_PACKAGE.equals(lpparam.processName)) {
ClassLoader classLoader = lpparam.classLoader;

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){ // Android 13+
final int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
new PermissionManagerServiceHook34(classLoader).startHook();
} else if (sdkInt >= Build.VERSION_CODES.TIRAMISU){ // Android 13+
new PermissionManagerServiceHook33(classLoader).startHook();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // Android 12~12L
} else if (sdkInt >= Build.VERSION_CODES.S) { // Android 12~12L
new PermissionManagerServiceHook31(classLoader).startHook();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R){ // Android 11
} else if (sdkInt >= Build.VERSION_CODES.R){ // Android 11
new PermissionManagerServiceHook30(classLoader).startHook();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { // Android 9.0~10
} else if (sdkInt >= Build.VERSION_CODES.P) { // Android 9.0~10
new PermissionManagerServiceHook(classLoader).startHook();
} else { // Android 5.0 ~ 8.1
new PackageManagerServiceHook(classLoader).startHook();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package com.tianma.xsmscode.xp.hook.permission;

import static com.tianma.xsmscode.common.constant.PermConst.PACKAGE_PERMISSIONS;

import android.os.Build;
import android.os.UserHandle;

import androidx.annotation.RequiresApi;

import com.tianma.xsmscode.common.utils.XLog;
import com.tianma.xsmscode.xp.helper.MethodHookWrapper;
import com.tianma.xsmscode.xp.hook.BaseSubHook;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;

/**
* Since Android 14(API 34+)<br/>
* Hook com.android.server.pm.permission.PermissionManagerServiceImpl
*/
public class PermissionManagerServiceHook34 extends BaseSubHook {
// IMPORTANT: There are two types of permissions: install and runtime.

// Android 14, API 34
private static final String CLASS_PERMISSION_MANAGER_SERVICE = "com.android.server.pm.permission.PermissionManagerServiceImpl";

private static final String CLASS_ANDROID_PACKAGE = "com.android.server.pm.pkg.AndroidPackage";
private static final String CLASS_PERMISSION_CALLBACK = CLASS_PERMISSION_MANAGER_SERVICE + ".PermissionCallback";


public PermissionManagerServiceHook34(ClassLoader classLoader) {
super(classLoader);
}

@RequiresApi(Build.VERSION_CODES.TIRAMISU)
@Override
public void startHook() {
try {
hookGrantPermissions();
} catch (Throwable e) {
XLog.e("Failed to hook PermissionManagerService", e);
}
}

private void hookGrantPermissions() {
XLog.d("Hooking grantPermissions() for Android 34+");
Method method = findTargetMethod();
if (method == null) {
XLog.e("Cannot find the method to grant relevant permission");
return;
}
XposedBridge.hookMethod(method, new MethodHookWrapper() {
@Override
protected void after(MethodHookParam param) throws Throwable {
afterRestorePermissionStateSinceAndroid14(param);
}
});
}

private Method findTargetMethod() {
Class<?> pmsClass = XposedHelpers.findClass(CLASS_PERMISSION_MANAGER_SERVICE, mClassLoader);
Class<?> androidPackageClass = XposedHelpers.findClass(CLASS_ANDROID_PACKAGE, mClassLoader);
Class<?> callbackClass = XposedHelpers.findClassIfExists(CLASS_PERMISSION_CALLBACK, mClassLoader);

// 精确匹配
Method method = XposedHelpers.findMethodExactIfExists(pmsClass, "restorePermissionState",
/* AndroidPackage pkg */ androidPackageClass,
/* boolean replace */ boolean.class,
/* String packageOfInterest */ String.class,
/* PermissionCallback callback */ callbackClass,
/* int filterUserId */ int.class);

if (method == null) { // method restorePermissionState() not found
// 参数类型精确匹配
Method[] _methods = XposedHelpers.findMethodsByExactParameters(pmsClass, Void.TYPE,
/* AndroidPackage pkg */ androidPackageClass,
/* boolean replace */ boolean.class,
/* String packageOfInterest */ String.class,
/* PermissionCallback callback */ callbackClass,
/* int filterUserId */ int.class);
if (_methods != null && _methods.length > 0) {
method = _methods[0];
}
}
return method;
}

@SuppressWarnings("unchecked")
private void afterRestorePermissionStateSinceAndroid14(XC_MethodHook.MethodHookParam param) {
// com.android.server.pm.pkg.AndroidPackage 对象
Object pkg = param.args[0];

final String _packageName = (String) XposedHelpers.callMethod(pkg, "getPackageName");

Set<String> packageSet = PACKAGE_PERMISSIONS.keySet();
for (String packageName : packageSet) {
if (packageName.equals(_packageName)) {
XLog.d("PackageName: %s", packageName);

// PermissionManagerServiceImpl 对象
Object pmsImpl = param.thisObject;

// UserHandle.USER_ALL
int filterUserId = (int) param.args[4];
final int USER_ALL = XposedHelpers.getStaticIntField(UserHandle.class, "USER_ALL");
final int[] userIds = filterUserId == USER_ALL
? (int[]) XposedHelpers.callMethod(pmsImpl, "getAllUserIds")
: new int[]{filterUserId};

List<String> permissionsToGrant = PACKAGE_PERMISSIONS.get(packageName);

if (userIds != null) {
// PackageManagerInternal 对象 mPackageManagerInt
Object mPackageManagerInt = XposedHelpers.getObjectField(pmsImpl, "mPackageManagerInt");

// PackageStateInternal 对象 ps
// final PackageStateInternal ps = mPackageManagerInt.getPackageStateInternal(pkg.getPackageName());
final Object ps = XposedHelpers.callMethod(mPackageManagerInt, "getPackageStateInternal", packageName);

// Manifest.xml 中声明的permission列表
// List<String> requestPermissions = pkg.getRequestedPermissions();
final List<String> requestedPermissions = (List<String>)
XposedHelpers.callMethod(pkg, "getRequestedPermissions");

// com.android.server.pm.permission.DevicePermissionState 对象
final Object mState = XposedHelpers.getObjectField(pmsImpl, "mState");

// com.android.server.pm.permission.PermissionRegistry 对象
Object mRegistry = XposedHelpers.getObjectField(pmsImpl, "mRegistry");

for (final int userId : userIds) {
// com.android.server.pm.permission.UserPermissionState 对象
Object userState = XposedHelpers.callMethod(mState, "getOrCreateUserState", userId);
int appId = (int) XposedHelpers.callMethod(ps, "getAppId");
// com.android.server.pm.permission.UidPermissionState 对象
Object uidState = XposedHelpers.callMethod(userState, "getOrCreateUidState", appId);

for (String permissionToGrant : permissionsToGrant) {
if (!requestedPermissions.contains(permissionToGrant)) {
boolean granted = (boolean) XposedHelpers.callMethod(uidState, "isPermissionGranted", permissionToGrant);
if (!granted) {
// permission not grant before
// final Permission bp = mRegistry.getPermission(permName);
final Object bpToGrant = XposedHelpers.callMethod(mRegistry, "getPermission", permissionToGrant);
// uidState.grantPermission(bp)
boolean result = (boolean) XposedHelpers.callMethod(uidState, "grantPermission", bpToGrant);
XLog.d("Add " + permissionToGrant + "; result = " + result);
} else {
// permission has been granted already
XLog.d("Already have " + permissionToGrant + " permission");
}
}
}
}
}
}
}
}


}
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ buildscript {
mavenCentral() // add repository
}
dependencies {
classpath 'com.android.tools.build:gradle:7.0.4'
classpath 'com.android.tools.build:gradle:7.4.2'


// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0' // greenDao plugin

classpath 'io.github.leon406:AndResGuard-gradle-plugin:1.2.22.6' // AndResGuard
classpath 'io.github.leon406:AndResGuard-gradle-plugin:1.2.23' // AndResGuard
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

0 comments on commit a7f9d84

Please sign in to comment.