android辅助功能手势,Android辅助功能——全局手势放大实现原理

本文深入探讨了Android系统中辅助功能的手势放大功能实现原理。通过分析`AccessibilityManagerService`中的`MagnificationController`,揭示了如何通过注册监听、与WindowManagerService交互来实现手势拦截及全局放大。主要涉及` MagnificationController`的注册、`WindowStateObserver`与WMS的沟通、`AccessibilityInputFilter`的插入以及放大动画的处理。这一过程涉及两个编舞者协同工作,分别在System Server主线程和android.display线程中处理放大参数更新和Surface更新。
摘要由CSDN通过智能技术生成

在Android的辅助功能中,存在一个点击三次屏幕触发屏幕放大功能。

0178f054a031

辅助功能中打开

0178f054a031

放大后效果

这个功能的使用频率实在是低...但是为什么会想记录一下这个功能的实现原理。第一,在处理性能问题的时候遇到了相关代码;其次其实现的原理还是具有部分启发性质的。主要还是研究启发部分:

1、如何实现手势拦截

2、全局放大的原理(主要在system_server中存在双编舞者协作实现),如下图所示在启动手势放大过程中systrace抓取到下面的现象:

0178f054a031

两个编舞者协同工作

一、手势拦截

在设置中打开放大手势的开关,会设置Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED这个属性值,AccessiblityContentObserver中的onChange会处理这个值的变化:

@Override

4456 public void onChange(boolean selfChange, Uri uri) {

4457 synchronized (mLock) {

4458 // Profiles share the accessibility state of the parent. Therefore,

4459 // we are checking for changes only the parent settings.

4460 UserState userState = getCurrentUserStateLocked();

4461

4462 // If the automation service is suppressing, we will update when it dies.

4463 if (userState.isUiAutomationSuppressingOtherServices()) {

4464 return;

4465 }

4466

4467 if (mTouchExplorationEnabledUri.equals(uri)) {

4468 if (readTouchExplorationEnabledSettingLocked(userState)) {

4469 onUserStateChangedLocked(userState);

4470 }

4471 } else if (mDisplayMagnificationEnabledUri.equals(uri)) {

4472 if (readDisplayMagnificationEnabledSettingLocked(userState)) {

4479 onUserStateChangedLocked(userState);

4480 }

4481 }

在onUserStateChangedLocked中会调用updateMagnificationLocked以及scheduleUpdateInputFilter去更新当前系统状态:

updateMagnificationLocked是用于建立wms和辅助功能服务的联系

scheduleUpdateInputFilter是用于在输入层面建立手势拦截,往Input流程中加入inputfilter

1820 private void updateMagnificationLocked(UserState userState) {

1821 if (userState.mUserId != mCurrentUserId) {

1822 return;

1823 }

1824

1825 if (userState.mIsDisplayMagnificationEnabled ||

1826 userHasListeningMagnificationServicesLocked(userState)) {

1827 // Initialize the magnification controller if necessary

1828 getMagnificationController();

//核心在于放大控制器的注册

1829 mMagnificationController.register();

1830 } else if (mMagnificationController != null) {

//当关闭此功能的时候会调用反注册

1831 mMagnificationController.unregister();

1832 }

1833 }

实际上就是通过MagnificationController去注册。

55/**

56 * This class is used to control and query the state of display magnification

57 * from the accessibility manager and related classes. It is responsible for

58 * holding the current state of magnification and animation, and it handles

59 * communication between the accessibility manager and window manager.

60 */

61class MagnificationController

从对这个类的描述可以看出,它是为了控制和查询当前屏幕的放大状态;其次用于辅助服务和WMS之间的通信工作。这些具体的含义还是放到代码中去一一解释。

首先看看他的register函数:

public void register() {

130 synchronized (mLock) {

131 if (!mRegistered) {

//step1、注册广播监听亮灭屏事件

132 mScreenStateObserver.register();

//step2、注册WMS中的回调(与WMS之间通信)

133 mWindowStateObserver.register();

//step3、使能跟动画相关的函数(虽然这个类名字有点奇怪,但还是能猜到是跟动画相关的)

134 mSpecAnimationBridge.setEnabled(true);

135 // Obtain initial state.

136 mWindowStateObserver.getMagnificationRegion(mMagnificationRegion);

137 mMagnificationRegion.getBounds(mMagnificationBounds);

138 mRegistered = true;

139 }

140 }

141 }

step1就略过从step2开始看它是如何跟wms进行交互的。

/**

957 * This class handles the screen magnification when accessibility is enabled.

958 */

959 private static class WindowStateObserver

960 implements WindowManagerInternal.MagnificationCallbacks {

......

975

976 public WindowStateObserver(Context context, MagnificationController controller) {

977 mController = controller;

978 mWindowManager = LocalServices.getService(WindowManagerInternal.class);

979 mHandler = new CallbackHandler(context);

980 }

981

982 public void register() {

987 mWindowManager.setMagnificationCallbacks(this);

990 }

991

WindowStateObserver实现了接口MagnificationCallbacks,这个接口是wms用于通知放大控制器当前wms端有了哪些变化的:

/**

51 * Callbacks for contextual changes that affect the screen magnification

52 * feature.

53 */

54 public interface MagnificationCallbacks {

55

56 /**

57 * Called when the region where magnification operates changes. Note that this isn't the

58 * entire screen. For example, IMEs are not magnified.

*这种情况在放大的情况下点开了输入法,输入法界面是不能够被放大的,但是由于其占用了一定的屏幕空间,就会导致放大的区域变小,wms就会回调注册的该方法

59 *

60 * @param magnificationRegion the current magnification region

61 */

62 public void onMagnificationRegionChanged(Region magnificationRegion);

63

64 /**

65 * Called when an application requests a rectangle on the screen to allow

66 * the client to apply the appropriate pan and scale.

67 *

68 * @param left The rectangle left.

69 * @param top The rectangle top.

70 * @param right The rectangle right.

71 * @param bottom The rectangle bottom.

72 */

73 public void onRectangleOnScreenRequested(int left, int top, int right, int bottom);

74

75 /**

76 * Notifies that the rotation changed.

77 *

78 * @param rotation The current rotation.

79 */

80 public void onRotationChanged(int rotation);

81

82 /**

83 * Notifies that the context of the user changed. For example, an application

84 * was started.

*context发生变化(个人理解为当前Activity发生了切换)

85 */

86 public void onUserContextChanged();

87 }

通过注册WindowStateObserver到WMS,就建立wms和AccessibilityMS的沟通了。

回到前面的step3,使能SpecAnimationBridge,从下面这个类的注释可以看出它有两个功能

/**

727 * Class responsible for animating spec on the main thread and sending spec

728 * updates to the window manager.

729 */

730 private static class SpecAnimationBridge {

1:将放大相关的参数发送给wms

<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值