android 12 MTK 平台全屏手势的禁用和启用
前言:最近有个项目客户需求开启全屏手势功能,开启后有些界面很容易误触到全屏手势,公司测试提BUG在这些界面把全屏手势禁用,其他界面打开
实现逻辑:进入app onResume–>禁用手势 退出app onPause–>启用手势,我这都是进行写值操作的,你们可以根据自己的相关逻辑处理
onResume–>SystemProperties.set(“persist.sys.disable-gesture”, “true”); 禁用全屏手势
onPause–>SystemProperties.set(“persist.sys.disable-gesture”, “false”); 启用全屏手势
1.底部全屏手势(在Launcher3中处理)
vendor/mediatek/proprietary/packages/apps/Launcher3/quickstep/src/com/android/quickstep/TouchInteractionService.java
标识://M: xxx @{
//@}
以上代码省略
...............................
private void onInputEvent(InputEvent ev) {
if (!(ev instanceof MotionEvent)) {
Log.e(TAG, "Unknown event " + ev);
return;
}
MotionEvent event = (MotionEvent) ev;
if (ENABLE_PER_WINDOW_INPUT_ROTATION) {
final Display display = mDisplayManager.getDisplay(mDeviceState.getDisplayId());
int rotation = display.getRotation();
Point sz = new Point();
display.getRealSize(sz);
if (rotation != Surface.ROTATION_0) {
event.transform(InputChannelCompat.createRotationMatrix(rotation, sz.x, sz.y));
}
}
TestLogging.recordMotionEvent(
TestProtocol.SEQUENCE_TIS, "TouchInteractionService.onInputEvent", event);
if (!mDeviceState.isUserUnlocked()) {
return;
}
Object traceToken = TraceHelper.INSTANCE.beginFlagsOverride(
TraceHelper.FLAG_ALLOW_BINDER_TRACKING);
final int action = event.getAction();
if (action == ACTION_DOWN) {
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
//M:需要屏蔽的Setting值或者定义的Prop值进行控制全屏手势 @{
if(disableGesture()){
mUncheckedConsumer = InputConsumer.NO_OP;
}else
//@}
if (!mDeviceState.isOneHandedModeActive()
&& mRotationTouchHelper.isInSwipeUpTouchRegion(event)) {
// Clone the previous gesture state since onConsumerAboutToBeSwitched might trigger
// onConsumerInactive and wipe the previous gesture state
GestureState prevGestureState = new GestureState(mGestureState);
GestureState newGestureState = createGestureState(mGestureState);
newGestureState.setSwipeUpStartTimeMs(SystemClock.uptimeMillis());
mConsumer.onConsumerAboutToBeSwitched();
mGestureState = newGestureState;
mConsumer = newConsumer(prevGestureState, mGestureState, event);
ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName());
mUncheckedConsumer = mConsumer;
} else if (mDeviceState.isUserUnlocked() && mDeviceState.isFullyGesturalNavMode()) {
mGestureState = createGestureState(mGestureState);
ActivityManager.RunningTaskInfo runningTask = mGestureState.getRunningTask();
if (mDeviceState.canTriggerAssistantAction(event, runningTask)) {
// Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we
// should not interrupt it. QuickSwitch assumes that interruption can only
// happen if the next gesture is also quick switch.
mUncheckedConsumer = new AssistantInputConsumer(
this,
mGestureState,
InputConsumer.NO_OP, mInputMonitorCompat,
mDeviceState,
event);
} else if (mDeviceState.canTriggerOneHandedAction(event)) {
// Consume gesture event for triggering one handed feature.
mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
InputConsumer.NO_OP, mInputMonitorCompat);
} else {
mUncheckedConsumer = InputConsumer.NO_OP;
}
} else if (mDeviceState.canTriggerOneHandedAction(event)) {
// Consume gesture event for triggering one handed feature.
mUncheckedConsumer = new OneHandedModeInputConsumer(this, mDeviceState,
InputConsumer.NO_OP, mInputMonitorCompat);
} else {
mUncheckedConsumer = InputConsumer.NO_OP;
}
} else {
// Other events
//M:需要屏蔽的Setting值或者定义的Prop值进行控制全屏手势 @{
if (mUncheckedConsumer != InputConsumer.NO_OP || disableGesture()) {
//@}
// Only transform the event if we are handling it in a proper consumer
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
}
}
if (mUncheckedConsumer != InputConsumer.NO_OP) {
switch (event.getActionMasked()) {
case ACTION_DOWN:
case ACTION_UP:
ActiveGestureLog.INSTANCE.addLog("onMotionEvent("
+ (int) event.getRawX() + ", " + (int) event.getRawY() + ")",
event.getActionMasked());
break;
default:
ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
break;
}
}
.....................
}
..................................
//M: 需要屏蔽的Setting值或者定义的Prop值进行控制全屏手势 @{
private boolean disableGesture(){
return SystemProperties.getBoolean("persist.sys.disable-gesture", false);
}
//@}
2.左右back返回功能
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java(在SystemUI中处理)
private void onMotionEvent(MotionEvent ev) {
int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
if (DEBUG_MISSING_GESTURE) {
Log.d(DEBUG_MISSING_GESTURE_TAG, "Start gesture: " + ev);
}
// Verify if this is in within the touch region and we aren't in immersive mode, and
// either the bouncer is showing or the notification panel is hidden
mInputEventReceiver.setBatchingEnabled(false);
mIsOnLeftEdge = ev.getX() <= mEdgeWidthLeft + mLeftInset;
mMLResults = 0;
mLogGesture = false;
mInRejectedExclusion = false;
boolean isWithinInsets = isWithinInsets((int) ev.getX(), (int) ev.getY());
mAllowGesture = !mDisabledForQuickstep && mIsBackGestureAllowed && isWithinInsets
&& !mGestureBlockingActivityRunning
&& !QuickStepContract.isBackGestureDisabled(mSysUiFlags)
&& isWithinTouchRegion((int) ev.getX(), (int) ev.getY())
//M:需要屏蔽的Setting值或者定义的Prop值进行控制全屏手势 @{
&& !disableGesture();
//@}
if (mAllowGesture) {
mEdgeBackPlugin.setIsLeftPanel(mIsOnLeftEdge);
mEdgeBackPlugin.onMotionEvent(ev);
}
if (mLogGesture) {
mDownPoint.set(ev.getX(), ev.getY());
mEndPoint.set(-1, -1);
mThresholdCrossed = false;
}
// For debugging purposes, only log edge points
(isWithinInsets ? mGestureLogInsideInsets : mGestureLogOutsideInsets).log(String.format(
"Gesture [%d,alw=%B,%B,%B,%B,disp=%s,wl=%d,il=%d,wr=%d,ir=%d,excl=%s]",
System.currentTimeMillis(), mAllowGesture, mIsOnLeftEdge,
mIsBackGestureAllowed,
QuickStepContract.isBackGestureDisabled(mSysUiFlags), mDisplaySize,
mEdgeWidthLeft, mLeftInset, mEdgeWidthRight, mRightInset, mExcludeRegion));
} else if (mAllowGesture || mLogGesture) {
......................
if (mAllowGesture) {
// forward touch
mEdgeBackPlugin.onMotionEvent(ev);
}
}
mProtoTracer.scheduleFrameUpdate();
}
//M:需要屏蔽的Setting值或者定义的Prop值进行控制全屏手势 @{
private boolean disableGesture(){
return SystemProperties.getBoolean("persist.sys.disable-gesture", false);
}
//@}
a.如果是静态控制(Setting值开关或者Prop值写死)可以不用看下面的补救措施
b.如果是动态控制(进入app禁用全屏手势,退出app启用全屏手势),请查看下面的补救措施
规避措施:为防止控制全屏手势的app或者程序意外退出或者报错退出,需在其他地方加入补救措施,防止全屏手势功能失效
1.开机时默认可以恢复全屏手势的状态,默认可以使用
修改位置:framework/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
@Override
public void init(Context context, IWindowManager windowManager,
WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mWindowManager = windowManager;
........................
initKeyCombinationRules();
initSingleKeyGestureRules();
mSideFpsEventHandler = new SideFpsEventHandler(mContext, mHandler, mPowerManager);
//M:add 防止全屏手势功能失效 @{
SystemProperties.set("persist.sys.disable-gesture", "false");
//@}
}
2.app报错时恢复全屏手势的状态,默认可以使用
framework/base/services/core/java/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")
final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
boolean fromBinderDied, String reason) {
//M:规避app报错,全屏手势失效 @{
Slog.i(TAG, "[appDiedLocked] app.info.packageName=" + app.info.packageName);
if (TextUtils.equals(app.info.packageName, "com.raisesail.diagnosis")){
SystemProperties.set("persist.sys.disable-gesture", "false");
}
//@}
// First check if this ProcessRecord is actually active for the pid.
final ProcessRecord curProc;
synchronized (mPidsSelfLocked) {
curProc = mPidsSelfLocked.get(pid);
}
...................................
// On the device which doesn't have Cgroup, log LmkStateChanged which is used as a signal
// for pulling memory stats of other running processes when this process died.
if (!hasMemcg()) {
FrameworkStatsLog.write(FrameworkStatsLog.APP_DIED, SystemClock.elapsedRealtime());
}
}