Skip to content

Commit 60a3b2a

Browse files
committed
opt: 允许截屏同步上游改动
1 parent 2126b99 commit 60a3b2a

1 file changed

Lines changed: 56 additions & 107 deletions

File tree

  • library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/systemframework/others

library/libhook/src/main/java/com/sevtinge/hyperceiler/libhook/rules/systemframework/others/FlagSecure.java

Lines changed: 56 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import android.os.Build;
77

88
import com.sevtinge.hyperceiler.common.log.XposedLog;
9-
import com.sevtinge.hyperceiler.libhook.callback.IMethodHook;
109
import com.sevtinge.hyperceiler.libhook.utils.hookapi.tool.EzxHelpUtils;
1110

1211
import java.lang.reflect.Field;
@@ -16,7 +15,7 @@
1615
import java.util.function.BiConsumer;
1716
import java.util.function.BiPredicate;
1817

19-
import io.github.kyuubiran.ezxhelper.xposed.common.HookParam;
18+
import io.github.libxposed.api.XposedInterface;
2019
import io.github.libxposed.api.XposedModuleInterface;
2120

2221
public class FlagSecure {
@@ -25,6 +24,11 @@ public class FlagSecure {
2524

2625
private static Field captureSecureLayersField;
2726

27+
@FunctionalInterface
28+
private interface ChainHooker {
29+
Object intercept(XposedInterface.Chain chain) throws Throwable;
30+
}
31+
2832
public void onLoad(XposedModuleInterface.SystemServerStartingParam lpparam) {
2933
var classLoader = lpparam.getClassLoader();
3034

@@ -34,153 +38,111 @@ public void onLoad(XposedModuleInterface.SystemServerStartingParam lpparam) {
3438
XposedLog.e(TAG, "system", "deoptimize system server failed", t);
3539
}
3640

41+
// Screen record detection (V~Baklava)
3742
try {
3843
hookWindowManagerService(classLoader);
3944
} catch (Throwable t) {
4045
XposedLog.e(TAG, "system", "hook WindowManagerService failed", t);
4146
}
4247

48+
// Screenshot detection (U~Baklava)
4349
try {
4450
hookActivityTaskManagerService(classLoader);
4551
} catch (Throwable t) {
4652
XposedLog.e(TAG, "system", "hook ActivityTaskManagerService failed", t);
4753
}
4854

55+
// Xiaomi HyperOS (U~Baklava)
4956
try {
5057
hookHyperOS(classLoader);
5158
} catch (ClassNotFoundException ignored) {
5259
} catch (Throwable t) {
5360
XposedLog.e(TAG, "system", "hook HyperOS failed", t);
5461
}
5562

63+
// ScreenCapture in WindowManagerService (S~Baklava)
5664
try {
5765
hookScreenCapture(classLoader);
5866
} catch (Throwable t) {
5967
XposedLog.e(TAG, "system", "hook ScreenCapture failed", t);
6068
}
6169

70+
// WifiDisplay (S~Baklava) / OverlayDisplay (S~Baklava) / VirtualDisplay (U~Baklava)
6271
try {
6372
hookDisplayControl(classLoader);
6473
} catch (Throwable t) {
6574
XposedLog.e(TAG, "system", "hook DisplayControl failed", t);
6675
}
6776

77+
// VirtualDisplay with MediaProjection (S~Baklava)
6878
try {
6979
hookVirtualDisplayAdapter(classLoader);
7080
} catch (Throwable t) {
7181
XposedLog.e(TAG, "system", "hook VirtualDisplayAdapter failed", t);
7282
}
7383

84+
// secureLocked flag
7485
try {
7586
hookWindowState(classLoader);
7687
} catch (Throwable t) {
7788
XposedLog.e(TAG, "system", "hook WindowState failed", t);
7889
}
7990
}
8091

81-
private final IMethodHook createDisplayHooker = new IMethodHook() {
82-
@Override
83-
public void before(HookParam callback) {
84-
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
85-
var stackTrace = new Throwable().getStackTrace();
86-
for (int i = 4; i < stackTrace.length && i < 8; i++) {
87-
var name = stackTrace[i].getMethodName();
88-
if (name.equals("createVirtualDisplayLocked")) {
89-
return;
90-
}
91-
}
92-
}
93-
callback.getArgs()[1] = true;
94-
}
92+
private final ChainHooker createDisplayHooker = chain -> {
93+
Object[] args = chain.getArgs().toArray();
94+
args[1] = true;
95+
return chain.proceed(args);
9596
};
9697

97-
private final IMethodHook checkPermissionHooker = new IMethodHook() {
98-
@Override
99-
public void before(HookParam callback) {
100-
var permission = callback.getArgs()[0];
101-
if ("android.permission.CAPTURE_BLACKOUT_CONTENT".equals(permission)) {
102-
callback.getArgs()[0] = "android.permission.READ_FRAME_BUFFER";
98+
private final ChainHooker screenCaptureHooker = chain -> {
99+
var captureArgs = chain.getArg(0);
100+
try {
101+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA && isAtLeastBaklava1()) {
102+
captureSecureLayersField.set(captureArgs, 1);
103+
} else {
104+
captureSecureLayersField.set(captureArgs, true);
103105
}
106+
} catch (IllegalAccessException t) {
107+
XposedLog.e(TAG, "system", "ScreenCaptureHooker failed", t);
104108
}
109+
return chain.proceed();
105110
};
106111

107-
private final IMethodHook oplusScreenCaptureHooker = new IMethodHook() {
108-
@Override
109-
public void before(HookParam callback) {
110-
callback.getArgs()[0] = -1;
112+
private final ChainHooker createVirtualDisplayLockedHooker = chain -> {
113+
var caller = (int) chain.getArg(2);
114+
if (caller >= 10000 && chain.getArg(1) == null) {
115+
// not os and not media projection
116+
return chain.proceed();
111117
}
112-
};
113-
114-
private final IMethodHook screenCaptureHooker = new IMethodHook() {
115-
@Override
116-
public void before(HookParam callback) {
117-
var captureArgs = callback.getArgs()[0];
118-
try {
119-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA && isAtLeastBaklava1()) {
120-
captureSecureLayersField.set(captureArgs, 1);
121-
} else {
122-
captureSecureLayersField.set(captureArgs, true);
123-
}
124-
} catch (IllegalAccessException t) {
125-
XposedLog.e(TAG, "system", "ScreenCaptureHooker failed", t);
118+
for (int i = 3; i < chain.getArgs().size(); i++) {
119+
var arg = chain.getArg(i);
120+
if (arg instanceof Integer) {
121+
var flags = (int) arg;
122+
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
123+
Object[] args = chain.getArgs().toArray();
124+
args[i] = flags;
125+
return chain.proceed(args);
126126
}
127127
}
128+
XposedLog.e(TAG, "system", "flag not found in CreateVirtualDisplayLockedHooker");
129+
return chain.proceed();
128130
};
129131

130-
private final IMethodHook createVirtualDisplayLockedHooker = new IMethodHook() {
131-
@Override
132-
public void before(HookParam callback) {
133-
var caller = (int) callback.getArgs()[2];
134-
if (caller >= 10000 && callback.getArgs()[1] == null) {
135-
return;
136-
}
137-
for (int i = 3; i < callback.getArgs().length; i++) {
138-
var arg = callback.getArgs()[i];
139-
if (arg instanceof Integer) {
140-
var flags = (int) arg;
141-
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
142-
callback.getArgs()[i] = flags;
143-
return;
144-
}
145-
}
146-
XposedLog.e(TAG, "system", "flag not found in CreateVirtualDisplayLockedHooker");
147-
}
132+
private final ChainHooker secureLockedHooker = chain -> {
133+
var walker = StackWalker.getInstance();
134+
var match = walker.walk(frames -> frames
135+
.map(StackWalker.StackFrame::getMethodName)
136+
.limit(10)
137+
.skip(6)
138+
.anyMatch(s -> s.equals("setInitialSurfaceControlProperties") || s.equals("createSurfaceLocked")));
139+
if (match) return chain.proceed();
140+
return false;
148141
};
149142

150-
private final IMethodHook secureLockedHooker = new IMethodHook() {
151-
@Override
152-
public void before(HookParam callback) {
153-
var walker = StackWalker.getInstance();
154-
var match = walker.walk(frames -> frames
155-
.map(StackWalker.StackFrame::getMethodName)
156-
.limit(6)
157-
.skip(2)
158-
.anyMatch(s -> s.equals("setInitialSurfaceControlProperties") || s.equals("createSurfaceLocked")));
159-
if (match) return;
160-
callback.setResult(false);
161-
}
162-
};
163-
164-
private final IMethodHook returnTrueHooker = new IMethodHook() {
165-
@Override
166-
public void before(HookParam callback) {
167-
callback.setResult(true);
168-
}
169-
};
170-
171-
private final IMethodHook returnFalseHooker = new IMethodHook() {
172-
@Override
173-
public void before(HookParam callback) {
174-
callback.setResult(false);
175-
}
176-
};
143+
private final ChainHooker returnFalseHooker = chain -> false;
177144

178-
private final IMethodHook returnNullHooker = new IMethodHook() {
179-
@Override
180-
public void before(HookParam callback) {
181-
callback.setResult(null);
182-
}
183-
};
145+
private final ChainHooker returnNullHooker = chain -> null;
184146

185147
private void deoptimizeSystemServer(ClassLoader classLoader) throws ClassNotFoundException {
186148
deoptimizeMethods(
@@ -259,33 +221,20 @@ private void hookWindowManagerService(ClassLoader classLoader) throws ClassNotFo
259221
hook(method, returnFalseHooker);
260222
}
261223

262-
private void hookActivityManagerService(ClassLoader classLoader) throws ClassNotFoundException, NoSuchMethodException {
263-
var activityTaskManagerServiceClazz = classLoader.loadClass("com.android.server.am.ActivityManagerService");
264-
var method = activityTaskManagerServiceClazz.getDeclaredMethod("checkPermission", String.class, int.class, int.class);
265-
hook(method, checkPermissionHooker);
266-
}
267-
268224
private void hookHyperOS(ClassLoader classLoader) throws ClassNotFoundException {
269225
var windowManagerServiceImplClazz = classLoader.loadClass("com.android.server.wm.WindowManagerServiceImpl");
270226
hookMethods(windowManagerServiceImplClazz, returnFalseHooker, "notAllowCaptureDisplay");
271227
}
272228

273-
private void hookScreenshotHardwareBuffer(ClassLoader classLoader) throws ClassNotFoundException, NoSuchMethodException {
274-
var screenshotHardwareBufferClazz = classLoader.loadClass(
275-
"android.window.ScreenCapture$ScreenshotHardwareBuffer");
276-
var method = screenshotHardwareBufferClazz.getDeclaredMethod("containsSecureLayers");
277-
hook(method, returnFalseHooker);
278-
}
279-
280-
private void hookMethods(Class<?> clazz, IMethodHook hooker, String... names) {
229+
private void hookMethods(Class<?> clazz, ChainHooker hooker, String... names) {
281230
List<String> list = Arrays.asList(names);
282231
Arrays.stream(clazz.getDeclaredMethods())
283232
.filter(method -> list.contains(method.getName()))
284233
.forEach(method -> hook(method, hooker));
285234
}
286235

287-
private void hook(Method method, IMethodHook hooker) {
288-
EzxHelpUtils.hookMethod(method, hooker);
236+
private void hook(Method method, ChainHooker hooker) {
237+
EzxHelpUtils.chain(method, hooker::intercept);
289238
}
290239

291240
private static boolean isAtLeastBaklava1() {

0 commit comments

Comments
 (0)