Skip to content

Commit

Permalink
fix: 桌面-快速切换上一个应用导致无法操作应用的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
HChenX committed Dec 23, 2024
1 parent 8ac48e3 commit b071497
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 100 deletions.
Original file line number Diff line number Diff line change
@@ -1,130 +1,165 @@
/*
* This file is part of HyperCeiler.
* This file is part of HyperCeiler.
* HyperCeiler is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License.
* HyperCeiler is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
* Copyright (C) 2023-2024 HyperCeiler Contributions
*/
* Copyright (C) 2023-2024 HyperCeiler Contributions
*/
package com.sevtinge.hyperceiler.module.hook.home.gesture;

import static com.hchen.hooktool.log.XposedLog.logE;
import static com.hchen.hooktool.log.XposedLog.logI;

import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.Context;

import com.sevtinge.hyperceiler.module.base.BaseHook;
import com.hchen.hooktool.BaseHC;
import com.hchen.hooktool.hook.IHook;

import java.util.ArrayList;
import java.util.HashMap;

import de.robv.android.xposed.XposedHelpers;
/**
* 启用桌面快捷返回功能
*
* @noinspection DataFlowIssue
*/
public class QuickBack extends BaseHC {
private static final HashMap<String, Integer> mResMap = new HashMap<>();

public class QuickBack extends BaseHook {
@Override
public void init() {
findAndHookMethod("com.miui.home.recents.GestureStubView",
"isDisableQuickSwitch", new MethodHook() {
@Override
protected void before(MethodHookParam param) {
param.setResult(false);
}
}
protected void init() {
hookMethod("com.miui.home.recents.GestureStubView",
"isDisableQuickSwitch",
returnResult(false)
);

findAndHookMethod("com.miui.home.recents.GestureStubView",
"getNextTask", Context.class, boolean.class, int.class,
new MethodHook() {
@Override
protected void before(MethodHookParam param) {
Context context = (Context) param.args[0];
ActivityManager.RunningTaskInfo runningTask;
Object recentsModel = XposedHelpers.callStaticMethod(findClass("com.miui.home.recents.RecentsModel"), "getInstance", context);
Object taskLoader = XposedHelpers.callMethod(recentsModel, "getTaskLoader");
Object createLoadPlan = XposedHelpers.callMethod(taskLoader, "createLoadPlan", context);
XposedHelpers.callMethod(taskLoader, "preloadTasks", createLoadPlan, -1);
Object taskStack = XposedHelpers.callMethod(createLoadPlan, "getTaskStack");
ActivityOptions activityOptions = null;
if (taskStack == null || (int) XposedHelpers.callMethod(taskStack, "getTaskCount") == 0 || (runningTask = (ActivityManager.RunningTaskInfo) XposedHelpers.callMethod(recentsModel, "getRunningTask")) == null) {
param.setResult(null);
return;
}
ArrayList<?> stackTasks = (ArrayList<?>) XposedHelpers.callMethod(taskStack, "getStackTasks");
int size = stackTasks.size();
Object task = null;
int i2 = 0;
while (true) {
if (i2 >= size - 1) {
break;
} else if ((int) XposedHelpers.getObjectField(XposedHelpers.getObjectField(stackTasks.get(i2), "key"), "id") == runningTask.id) {
task = stackTasks.get(i2 + 1);
break;
} else {
i2++;
hookMethod("com.miui.home.recents.GestureStubView$3",
"onSwipeStop",
boolean.class, float.class, boolean.class,
new IHook() {

@Override
public void before() {
boolean isFinish = (boolean) getArgs(0);
if (isFinish) {
Object mGestureStubView = getThisField("this$0");
Object mGestureBackArrowView = getField(mGestureStubView, "mGestureBackArrowView");
Object getCurrentState = callMethod(mGestureBackArrowView, "getCurrentState");

int ordinal = (int) callMethod(getCurrentState, "ordinal");
int[] mState = (int[]) getStaticField("com.miui.home.recents.GestureStubView$4", "$SwitchMap$com$miui$home$recents$GestureBackArrowView$ReadyState");
ordinal = mState[ordinal];
if (ordinal == 2) {
callMethod(mGestureStubView, "onBackCancelled");
logI(TAG, "call onBackCancelled");
}
}
}
if (task == null && size >= 1 && "com.miui.home".equals(runningTask.baseActivity.getPackageName())) {
task = stackTasks.get(0);
}
if (task != null && XposedHelpers.getObjectField(task, "icon") == null) {
XposedHelpers.setObjectField(task, "icon", XposedHelpers.callMethod(taskLoader, "getAndUpdateActivityIcon",
XposedHelpers.getObjectField(task, "key"),
XposedHelpers.getObjectField(task, "taskDescription"),
context.getResources(), true
));
}
if (!(boolean) param.args[1] || task == null) {
param.setResult(task);
return;
}
int i = (int) param.args[2];
if (i == 0) {
activityOptions = ActivityOptions.makeCustomAnimation(context,
getAnimId(context, "recents_quick_switch_left_enter"),
getAnimId(context, "recents_quick_switch_left_exit"));
} else if (i == 1) {
activityOptions = ActivityOptions.makeCustomAnimation(context,
getAnimId(context, "recents_quick_switch_right_enter"),
getAnimId(context, "recents_quick_switch_right_exit"));
}
Object iActivityManager = XposedHelpers.callStaticMethod(findClass("android.app.ActivityManagerNative"), "getDefault");
if (iActivityManager != null) {
try {
if ((int) XposedHelpers.getObjectField(XposedHelpers.getObjectField(task, "key"), "windowingMode") == 3) {
if (activityOptions == null) {
activityOptions = ActivityOptions.makeBasic();
}
activityOptions.getClass().getMethod("setLaunchWindowingMode", Integer.class).invoke(activityOptions, 4);
}
XposedHelpers.callMethod(iActivityManager, "startActivityFromRecents",
XposedHelpers.getObjectField(
XposedHelpers.getObjectField(task, "key"),
"id"),
activityOptions == null ? null : activityOptions.toBundle());
param.setResult(task);
}
);

hookMethod("com.miui.home.recents.GestureStubView",
"getNextTask",
Context.class, boolean.class, int.class,
new IHook() {
@Override
public void before() {
Context context = (Context) getArgs(0);
ActivityManager.RunningTaskInfo runningTask;
Object recentsModel = callStaticMethod("com.miui.home.recents.RecentsModel", "getInstance", context);
Object taskLoader = callMethod(recentsModel, "getTaskLoader");
Object createLoadPlan = callMethod(taskLoader, "createLoadPlan", context);
callMethod(taskLoader, "preloadTasks", createLoadPlan, -1);
Object taskStack = callMethod(createLoadPlan, "getTaskStack");
ActivityOptions activityOptions = null;
if (taskStack == null || (int) callMethod(taskStack, "getTaskCount") == 0 ||
(runningTask = (ActivityManager.RunningTaskInfo) callMethod(recentsModel, "getRunningTask")) == null) {
setResult(null);
return;
} catch (Exception e) {
logE(TAG, "Error: " + e);
param.setResult(task);
}
ArrayList<?> stackTasks = (ArrayList<?>) callMethod(taskStack, "getStackTasks");
int size = stackTasks.size();
Object task = null;
int i2 = 0;
while (true) {
if (i2 >= size - 1) {
break;
} else if ((int) getField(getField(stackTasks.get(i2), "key"), "id") == runningTask.id) {
task = stackTasks.get(i2 + 1);
break;
} else {
i2++;
}
}
if (task == null && size >= 1 && "com.miui.home".equals(runningTask.baseActivity.getPackageName())) {
task = stackTasks.get(0);
}
if (task != null && getField(task, "icon") == null) {
setField(task, "icon", callMethod(taskLoader, "getAndUpdateActivityIcon",
getField(task, "key"),
getField(task, "taskDescription"),
context.getResources(), true
));
}
if (!(boolean) getArgs(1) || task == null) {
setResult(task);
return;
}
int i = (int) getArgs(2);
if (i == 0) {
activityOptions = ActivityOptions.makeCustomAnimation(context,
getAnimId(context, "recents_quick_switch_left_enter"),
getAnimId(context, "recents_quick_switch_left_exit"));
} else if (i == 1) {
activityOptions = ActivityOptions.makeCustomAnimation(context,
getAnimId(context, "recents_quick_switch_right_enter"),
getAnimId(context, "recents_quick_switch_right_exit"));
}
Object iActivityManager = callStaticMethod("android.app.ActivityManagerNative", "getDefault");
if (iActivityManager != null) {
try {
if ((int) getField(getField(task, "key"), "windowingMode") == 3) {
if (activityOptions == null) {
activityOptions = ActivityOptions.makeBasic();
}
activityOptions.getClass().getMethod("setLaunchWindowingMode", Integer.class).invoke(activityOptions, 4);
}
callMethod(iActivityManager, "startActivityFromRecents",
getField(getField(task, "key"), "id"),
activityOptions == null ? null : activityOptions.toBundle());
setResult(task);
return;
} catch (Exception e) {
logE(TAG, "Error: " + e);
setResult(task);
return;
}
}
setResult(task);
}
param.setResult(task);
}
}
);

}

public static int getAnimId(Context context, String str) {
return context.getResources().getIdentifier(str, "anim", context.getPackageName());
if (mResMap.get(str) == null) {
int id = context.getResources().getIdentifier(str, "anim", context.getPackageName());
mResMap.put(str, id);
return id;
} else
return mResMap.get(str);
}
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ dexkit = "2.0.2"
ezxhelper = "2.2.0"
hiddenapibypass = "4.3"
annotation-processor = "4.4.0"
hooktool = "v.1.1.0"
hooktool = "v.1.1.3"
lyricGetterApi = "6.0.0"
mmkv = "2.0.1"

Expand Down

0 comments on commit b071497

Please sign in to comment.