Floating Cat

深入Android辅助服务架构与设计

字数统计: 6.2k阅读时长: 29 min
2018/03/22 Share

首先我们需要明确在整个AccessibilityService体系中共包含三个部分,其结构基本如下:

image-20181225174719637

  • 被监控应用端: 即我们需要监控的应用,比如微信,系统某些界面等等;
  • 监控服务端: 用来实时接受来自被监控应用端的事件,并作出处理,即我们自行实现的AccessibilityService
  • AccessibilityManagerService: 由于被监控应用端和监控服务端涉涉及跨进程通信,同时它们之间又是多对多的关系,因此为了需要引入中间管理器来对两端进行管理.(为了方便起见,后续我们简称为AMS,注意不要和ActivityManagerService进行混淆)

需要注意的对于被监控客户端和AMS以及监控服务端和AMS而言,都可以单独的当成C-S架构来看:对于被监控客户端和AMS: 前者是客户端Client,后者是服务端Server;对于监控服务端和AMS: 前者是客户端Client,后者是Server.

在后续的正文中,将按照 监控服务端和AMS -> 被监控客户端和AMS的顺序来讲述,前者以AccessibilityService注册为主题,后者以AccessibilityEvnet分为为主旨.

AccessibilityService注册流程

在AccessibilityService注册中主要涉及AMS绑定我们自定义AccessibilityService的过程.在该阶段,当AMS检测到系统中AccessibilityService状态变化后会做出相应的处理,比如检测到某个AccessibilityService被安装到系统并被用户启用后,AMS会主动绑定AccessibilityService,这和绑定远程服务的流程一样.

AccessibilityService架构

在开发辅助服务时,需要我们继承AccessibilityService,那AccessibilityService到底是什么呢?首先来看一张基本结构图:

image-20181225180514185

AccessibilityService继承自Service,也就是说它就是一个标准的服务,该服务只能由AMS进行绑定.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public abstract class AccessibilityService extends Service {

@Override
public final IBinder onBind(Intent intent) {
// AMS主动绑定时,将返回IAccessibilityServiceClientWrapper实例
return new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {
@Override
public void onServiceConnected() {
AccessibilityService.this.dispatchServiceConnected();
}

@Override
public void onInterrupt() {
AccessibilityService.this.onInterrupt();
}

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
AccessibilityService.this.onAccessibilityEvent(event);
}

@Override
public void init(int connectionId, IBinder windowToken) {
mConnectionId = connectionId;
mWindowToken = windowToken;

// The client may have already obtained the window manager, so
// update the default token on whatever manager we gave them.
final WindowManagerImpl wm = (WindowManagerImpl) getSystemService(WINDOW_SERVICE);
wm.setDefaultToken(windowToken);
}

......

});
}

......

}

不难发现AccessibilityService的onBind()方法中返回类型为IAccessibilityServiceClientWrapper的对象,IAccessibilityServiceClientWrapper以内部类的形式存在于AccessibilityService中,其定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub
implements HandlerCaller.Callback {
private static final int DO_INIT = 1;
private static final int DO_ON_INTERRUPT = 2;
private static final int DO_ON_ACCESSIBILITY_EVENT = 3;
private static final int DO_ON_GESTURE = 4;
private static final int DO_CLEAR_ACCESSIBILITY_CACHE = 5;
private static final int DO_ON_KEY_EVENT = 6;
private static final int DO_ON_MAGNIFICATION_CHANGED = 7;
private static final int DO_ON_SOFT_KEYBOARD_SHOW_MODE_CHANGED = 8;
private static final int DO_GESTURE_COMPLETE = 9;
private static final int DO_ON_FINGERPRINT_ACTIVE_CHANGED = 10;
private static final int DO_ON_FINGERPRINT_GESTURE = 11;
private static final int DO_ACCESSIBILITY_BUTTON_CLICKED = 12;
private static final int DO_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 13;

private final HandlerCaller mCaller;

private final Callbacks mCallback;

private int mConnectionId = AccessibilityInteractionClient.NO_ID;

public IAccessibilityServiceClientWrapper(Context context, Looper looper,
Callbacks callback) {
mCallback = callback;
mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
}

public void init(IAccessibilityServiceConnection connection, int connectionId,
IBinder windowToken) {
Message message = mCaller.obtainMessageIOO(DO_INIT, connectionId,
connection, windowToken);
mCaller.sendMessage(message);
}

public void onInterrupt() {
Message message = mCaller.obtainMessage(DO_ON_INTERRUPT);
mCaller.sendMessage(message);
}

public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) {
Message message = mCaller.obtainMessageBO(
DO_ON_ACCESSIBILITY_EVENT, serviceWantsEvent, event);
mCaller.sendMessage(message);
}

.......

}

IAccessibilityServiceClientWrapper继承自IAccessibilityServiceClient.Stub,而IAccessibilityServiceClient用来代表AccessibilityService组件.在IAccessibilityServiceClient接口中定义了暴露给AMS可操作的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public interface IAccessibilityServiceClient extends android.os.IInterface {

public static abstract class Stub extends android.os.Binder implements android.accessibilityservice.IAccessibilityServiceClient {
......

private static class Proxy implements android.accessibilityservice.IAccessibilityServiceClient {
}

......
}

public void init(android.accessibilityservice.IAccessibilityServiceConnection connection, int connectionId, android.os.IBinder windowToken) throws android.os.RemoteException;
public void onAccessibilityEvent(android.view.accessibility.AccessibilityEvent event, boolean serviceWantsEvent) throws android.os.RemoteException;
public void onInterrupt() throws android.os.RemoteException;
public void onGesture(int gesture) throws android.os.RemoteException;
public void clearAccessibilityCache() throws android.os.RemoteException;
public void onKeyEvent(android.view.KeyEvent event, int sequence) throws android.os.RemoteException;
public void onMagnificationChanged(android.graphics.Region region, float scale, float centerX, float centerY) throws android.os.RemoteException;
public void onSoftKeyboardShowModeChanged(int showMode) throws android.os.RemoteException;
public void onPerformGestureResult(int sequence, boolean completedSuccessfully) throws android.os.RemoteException;
public void onFingerprintCapturingGesturesChanged(boolean capturing) throws android.os.RemoteException;
public void onFingerprintGesture(int gesture) throws android.os.RemoteException;
public void onAccessibilityButtonClicked() throws android.os.RemoteException;
public void onAccessibilityButtonAvailabilityChanged(boolean available) throws android.os.RemoteException;

}

此外IAccessibilityServiceClientWrapper的构造函数中存在参数类型为Callbacks的回调接口.该回调接口最终会被AMS调用,其定义如下:

android.accessibilityservice.AccessibilityService.Callbacks

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Callbacks {
void onAccessibilityEvent(AccessibilityEvent event);
void onInterrupt();
void onServiceConnected();
void init(int connectionId, IBinder windowToken);
boolean onGesture(int gestureId);
boolean onKeyEvent(KeyEvent event);
void onMagnificationChanged(@NonNull Region region,
float scale, float centerX, float centerY);
void onSoftKeyboardShowModeChanged(int showMode);
void onPerformGestureResult(int sequence, boolean completedSuccessfully);
void onFingerprintCapturingGesturesChanged(boolean active);
void onFingerprintGesture(int gesture);
void onAccessibilityButtonClicked();
void onAccessibilityButtonAvailabilityChanged(boolean available);
}

在AccessibilityService启用时,AMS会主动绑定该服务,并通过onBind()返回IAccessibilityServiceClientWrapper对象,当AMS需要与AccessibilityService通信时,就会回远程回调此处的Callbacks接口,以分发AccessibilityEvent到对应的AccessibilityService为例,此时AMS会远程回调Callbacks中的onAccessibilityEvent():

1
2
3
4
5
6
7
8
9
10
new IAccessibilityServiceClientWrapper(this, getMainLooper(), new Callbacks() {

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// 事件分发
AccessibilityService.this.onAccessibilityEvent(event);
}

......
}

我们发现在Callbacks的匿名实现类中,最终又调用了AccessibilityService实例中的onAccessibilityEvent(event),此方法是抽象类AccessibilityService中的抽象方法,也是我们在自定义AccessibilityService时必须要重写的方法:

1
2
3
4
5
6
7
public abstract class AccessibilityService extends Service {
......

public abstract void onAccessibilityEvent(AccessibilityEvent event);

.......
}

AMS绑定AccessibilityService时机

和AMS启动时机一样,AccessibilityServiceManager也是由SystemServer启动,其构造函数如下:

com.android.server.accessibility.AccessibilityManagerService#AccessibilityManagerService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  public AccessibilityManagerService(Context context) {
mContext = context;
mPackageManager = mContext.getPackageManager();
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
mSecurityPolicy = new SecurityPolicy();
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mMainHandler = new MainHandler(mContext.getMainLooper());
mGlobalActionPerformer = new GlobalActionPerformer(mContext, mWindowManagerService);
// 动态注册广播接收器
registerBroadcastReceivers();
new AccessibilityContentObserver(mMainHandler).register(
context.getContentResolver());
}

其中registerBroadcastReceivers()动态注册PackageMonitor类型的广播接收器.其中PackageMonitor用于监听app安装,删除,更新以及SD卡增加/移除的广播通知,然后根据这些广播通知,来决定什么时候要主动绑定某个AccessibilityService或者和某个AccessibilityService断开.比如当某个App从系统中被删除或者被强制停止时,会分别调用onPackageRemoved()onHandleForceStop()方法,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void registerBroadcastReceivers() {
PackageMonitor monitor = new PackageMonitor() {

@Override
public void onSomePackagesChanged() {
......
onUserStateChangedLocked();
......
}

@Override
public void onPackageRemoved(String packageName, int uid) {
......
onUserStateChangedLocked();
......
}

@Override
public boolean onHandleForceStop(Intent intent, String[] packages,int uid, boolean doit) {
......
onUserStateChangedLocked();
......
}

......
}

通过上述代码不难看出AccessibilityManagerService通过监听系统状态变化的广播,并决定是否调用onUserStateChangedLocked()来更新状态,更新的时机主要涉及以下场景:

  • 用户在系统设置界面,为某个APP开启辅助服务的时候
  • 用户在系统设置界面,关闭某个APP辅助功能
  • 接受到用户删除APP事件的时候
  • 接受到某个App被强制停止

接下来来看看onUserStateChangedLocked()中到底做了什么:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private void onUserStateChangedLocked(UserState userState) {
// TODO: Remove this hack
mInitialized = true;
updateLegacyCapabilitiesLocked(userState);
updateServicesLocked(userState);
updateAccessibilityShortcutLocked(userState);
updateWindowsForAccessibilityCallbackLocked(userState);
updateAccessibilityFocusBehaviorLocked(userState);
updateFilterKeyEventsLocked(userState);
updateTouchExplorationLocked(userState);
updatePerformGesturesLocked(userState);
updateDisplayDaltonizerLocked(userState);
updateDisplayInversionLocked(userState);
updateMagnificationLocked(userState);
updateSoftKeyboardShowModeLocked(userState);
scheduleUpdateFingerprintGestureHandling(userState);
scheduleUpdateInputFilter(userState);
scheduleUpdateClientsIfNeededLocked(userState);
updateRelevantEventsLocked(userState);
updateAccessibilityButtonTargetsLocked(userState);
}

上述代码中会调用很多状态更新的方法,但我们目前只关心AMS什么时候主动绑定AccessibilityService.因此先看方法updateServicesLocked():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
   private void updateServicesLocked(UserState userState) {
Map<ComponentName, AccessibilityServiceConnection> componentNameToServiceMap =
userState.mComponentNameToServiceMap;
boolean isUnlockingOrUnlocked = LocalServices.getService(UserManagerInternal.class)
.isUserUnlockingOrUnlocked(userState.mUserId);
// mInstalledServices表示手机中所有已经安装的AccessibilityService,
// 每个AccessibilityService用AccessibilityServiceInfo表示
for (int i = 0, count = userState.mInstalledServices.size(); i < count; i++) {
AccessibilityServiceInfo installedService = userState.mInstalledServices.get(i);
ComponentName componentName = ComponentName.unflattenFromString(
installedService.getId());

AccessibilityServiceConnection service = componentNameToServiceMap.get(componentName);

// Ignore non-encryption-aware services until user is unlocked
if (!isUnlockingOrUnlocked && !installedService.isDirectBootAware()) {
Slog.d(LOG_TAG, "Ignoring non-encryption-aware service " + componentName);
continue;
}

// Wait for the binding if it is in process.
if (userState.mBindingServices.contains(componentName)) {
continue;
}
if (userState.mEnabledServices.contains(componentName)
&& !mUiAutomationManager.suppressingAccessibilityServicesLocked()) {
// 当前AccessibilityService被启用后,为其创建连接对象
// AccessibilityServiceConnection
if (service == null) {
service = new AccessibilityServiceConnection(userState, mContext, componentName,
installedService, sIdCounter++, mMainHandler, mLock, mSecurityPolicy,
this, mWindowManagerService, mGlobalActionPerformer);
} else if (userState.mBoundServices.contains(service)) {
continue;
}
// 调用AccessibilityServiceConnection的bindLocked()方法主动连接
// AccessibilityService
service.bindLocked();
} else {
if (service != null) {
service.unbindLocked();
}
}
}

final int count = userState.mBoundServices.size();
mTempIntArray.clear();
for (int i = 0; i < count; i++) {
final ResolveInfo resolveInfo =
userState.mBoundServices.get(i).mAccessibilityServiceInfo.getResolveInfo();
if (resolveInfo != null) {
mTempIntArray.add(resolveInfo.serviceInfo.applicationInfo.uid);
}
}
// Calling out with lock held, but to a lower-level service
final AudioManagerInternal audioManager =
LocalServices.getService(AudioManagerInternal.class);
if (audioManager != null) {
audioManager.setAccessibilityServiceUids(mTempIntArray);
}
updateAccessibilityEnabledSetting(userState);
}

这里面主要做了三件事情:

  1. 遍历手机中所有已安装的辅助服务,这些服务信息被保存在UserState.mInstalledServices中;
  2. 根据componentName,在mEnabledServices(mEnableServices保存了所有启动的辅助服务,即AMS绑定过的AccessibilityService)里面查找enabled状态的AccessibilityService组件,如果不存在就构造一个service.这里service类型是AccessibilityServiceConnection,在AMS中,用AccessibilityServiceConnection表示AMS和某个AccessibilityService的连接.
  3. 调用service的bindLocked方法来进行真正的绑定操作

其实componentName里面保存的就是AccessibilityService的packageName和className.重点来看service的bindLocked()操作:

com.android.server.accessibility.AccessibilityServiceConnection#bindLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void bindLocked() {
UserState userState = mUserStateWeakReference.get();
if (userState == null) return;
final long identity = Binder.clearCallingIdentity();
try {
int flags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE;
if (userState.mBindInstantServiceAllowed) {
flags |= Context.BIND_ALLOW_INSTANT;
}
// 调用bindServiceAsUser()来绑定服务,其中第二个参数this类型是ServiceConnection
if (mService == null && mContext.bindServiceAsUser(
mIntent, this, flags, new UserHandle(userState.mUserId))) {
userState.getBindingServicesLocked().add(mComponentName);
}
} finally {
Binder.restoreCallingIdentity(identity);
}


}

上述代码中最终调用bindServiceAsUser()来绑定AccessibilityService.绑定成功后回调ServiceConnection中的onServiceConnected(),即AccessibilityServiceConnection中的onServiceConnected():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void onServiceConnected(ComponentName componentName, IBinder service) {
synchronized (mLock) {
// 此处service即AccessibilityService中onBind()方法返回的
// IAccessibilityServiceClientWrapper对象
if (mService != service) {
if (mService != null) {
mService.unlinkToDeath(this, 0);
}
mService = service;
try {
mService.linkToDeath(this, 0);
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Failed registering death link");
binderDied();
return;
}
}
// mServiceInterface是AccessibilityServiceConnection类型
mServiceInterface = IAccessibilityServiceClient.Stub.asInterface(service);
UserState userState = mUserStateWeakReference.get();
if (userState == null) return;
// 调用AMS的addServiceLocked()方法将该Connection实例保存在mBoundServices
// 成员变量中
userState.addServiceLocked(this);
mSystemSupport.onClientChange(false);
// Initialize the service on the main handler after we're done setting up for
// the new configuration (for example, initializing the input filter).
// 主线程继续调用initializeService()方法来继续完成初始化操作
mMainHandler.sendMessage(obtainMessage(
AccessibilityServiceConnection::initializeService, this));
}
}

不难看出其实每个AccessibilityServiceConnection都关联了对应AccessibilityService中返回的IAccessibilityServiceClientWrapper对象,即上述代码中的mService.然后将该AccessibilityServiceConnection保存在AMS中对应UserState的mBoundServices中:

com.android.server.accessibility.AccessibilityManagerService.UserState#addServiceLocked

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserState {
public final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();

public void addServiceLocked(AccessibilityServiceConnection serviceConnection) {
if (!mBoundServices.contains(serviceConnection)) {
serviceConnection.onAdded();
mBoundServices.add(serviceConnection);
mComponentNameToServiceMap.put(serviceConnection.mComponentName, serviceConnection);
scheduleNotifyClientsOfServicesStateChange(this);
}
}

......
}

接下来继续调用initializeService()来完成初始化操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void initializeService() {
IAccessibilityServiceClient serviceInterface = null;
synchronized (mLock) {
UserState userState = mUserStateWeakReference.get();
if (userState == null) return;
Set<ComponentName> bindingServices = userState.getBindingServicesLocked();
if (bindingServices.contains(mComponentName) || mWasConnectedAndDied) {
bindingServices.remove(mComponentName);
mWasConnectedAndDied = false;
serviceInterface = mServiceInterface;
}
}
if (serviceInterface == null) {
binderDied();
return;
}
try {
// 远程调用IAccessibilityServiceClient的init()方法以便AccessibilityService所在
// 进程能够持有当前AccessibilityServiceConnection的代理对象
serviceInterface.init(this, mId, mOverlayWindowToken);
} catch (RemoteException re) {
Slog.w(LOG_TAG, "Error while setting connection for service: "
+ serviceInterface, re);
binderDied();
}
}

最终初始化完成后,在AMS进程一端,AMS持有远程AccessibilityService中IAccessibilityServiceClientWrapper的本地代理对象,在AMS需要和AccessibilityService通信时,就会远程回调IAccessibilityServiceClientWrapper中Callbacks接口;此外AccessibilityService也持有了AMS端中对应AccessibilityServiceConnection的本地代理对象,在AccessibilityService需要和AMS通信时便会借助该代理对象.

image-20181225231722678

小结

当AMS监听到一些系统状态变化时,最终会调用onUserStateChangedLocked()进行用户状态更新操作.在此期间会根据componentName,在mEnabledServices里面查找enabled状态的AccessibilityService组件,并为其生成对应AccessibilityServiceConnection对象,然后调用该对象的bindLocked()方法,在bindLocked()中会调用context的bindServiceAsUser(mIntent...)来绑定AccessibilityService.

image-20181226215836704

AccessibilityEvent分发

AccessibilityEvent代表将可能系统中产生的事件,该事件对象产生后会通过跨进程的方式传送给AMS,然后AMS继续通过跨进程的方式传递给对应AccessibilityService进程.

AccessibilityEvent生成及初始化

当一个View想要对外发送AccessibilityEvent时,需要用到以下接口:

1
2
3
4
5
6
public interface AccessibilityEventSource {

public void sendAccessibilityEvent(int eventType);

public void sendAccessibilityEventUnchecked(AccessibilityEvent event);
}

该接口中定义了两个方法用来发送AccessibilityEvent.Android官方希望任何一个View在开始设计时都能对残疾人友好,因此选择在View来实现该接口,这样我们在View及其子类就可以方便的支持无障碍服务了.首先来看View中关于点击操作所发出的事件的流程,即performClick():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {

AccessibilityDelegate mAccessibilityDelegate;

public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
// 1.设置ClickListener的情况,先回调onClick()
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this);
result = true;
} else {
result = false;
}

// 2.向辅助服务发送CLICKED事件
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
notifyEnterOrExitForAutoFillIfNeeded(true);
return result;
}

public void sendAccessibilityEvent(int eventType) {
if (mAccessibilityDelegate != null) {
// 如果已经设置了委托,则调用委托者的sendAccessibilityEvent()
mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
} else {
// 没有设置委托的情况下,调用sendAccessibilityEventInternal()
sendAccessibilityEventInternal(eventType);
}
}

public void sendAccessibilityEventInternal(int eventType){
// isEnabled()用来检查系统辅助功能是否开启
if(AccessibilityManager.getInstance(mContext).isEnabled()){
// 继续调用sendAccessibilityEventUnchecked()实现事件发送
sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType))
}
}

public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
// 如果已经设置了委托,则调用委托者的sendAccessibilityEventUnchecked()
if (mAccessibilityDelegate != null) {
mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
} else {
// 继续调用sendAccessibilityEventUncheckedInternal()实现事件发送
sendAccessibilityEventUncheckedInternal(event);
}
}


public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
// 1.isShown()用递归检查当前view以及其父view是否可见.如果不可见了就没必要继续处理了
if (!isShown()) {
return;
}
// 2.使用有关View的事件源的信息初始化AccessibilityEvent对象
onInitializeAccessibilityEvent(event);
// Only a subset of accessibility events populates text content.
if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
dispatchPopulateAccessibilityEvent(event);
}
// ViewRootImpl是ViewParent的实现类
ViewParent parent = getParent();
if (parent != null) {
// 3. 请求父View发送AccessibilityEvent,这里最终调用了ViewRootImpl的
// requestSendAccessibilityEvent()方法
getParent().requestSendAccessibilityEvent(this, event);
}
}

public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
mAccessibilityDelegate = delegate;
}
}

在上述代码中主要做了两件事:

  • 事件生成: 指定要发送的AccessibilityEvent类型,并生成对应的AccessibilityEvent事件
  • 事件发送: 在没有设置委托的情况下,最终调用ViewRootImpl#requestSendAccessibilityEvent()请求发送事件

事件生成

由于系统中会产生大量的事件,如果为每个事件都创建对应AccessibilityEvent对象可能会造成GC频繁发生,进而影响整体性能,因此Google采用享元模式来实现对AccessibilityEvent对象的复用.

AccessibilityEvent.obtain()根据事件类型返回一个缓存的AccessibilityEvent实例,享元模式.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class AccessibilityEvent{

private static final int MAX_POOL_SIZE = 10;
//sPool是对象池
private static final SynchronizedPool<AccessibilityEvent> sPool =
new SynchronizedPool<AccessibilityEvent>(MAX_POOL_SIZE);


public static AccessibilityEvent obtain(int eventType) {
AccessibilityEvent event = AccessibilityEvent.obtain();
event.setEventType(eventType);
return event;
}

public static AccessibilityEvent obtain() {
AccessibilityEvent event = sPool.acquire();
return (event != null) ? event : new AccessibilityEvent();
}

}

事件初始化

在获取AccessibilityEvent对象之后接下来会用当前事件源的信息对AccessiblityEvent对象进行初始化操作.在没有设置mAccessibilityDelegate的情况下默认通过View.onInitializeAccessibilityEventInternal()进行初始化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
// 1.设置当前View为事件源
event.setSource(this);
// 2.将产生该事件所在类的类名设置为AccessibilityEvent的mClassName.View的子类中通过
// 复写getAccessibilityClassName()来返回事件类的类名
event.setClassName(getAccessibilityClassName());
// 3.该事件是由那个应用产生的
event.setPackageName(getContext().getPackageName());
// 4.产生该事件的View是否在可用状态
event.setEnabled(isEnabled());
// 5.该View对应的内容概要信息,可以通过android:contentDescription来设置
event.setContentDescription(mContentDescription);

switch (event.getEventType()) {
case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
ArrayList<View> focusablesTempList = (mAttachInfo != null)
? mAttachInfo.mTempArrayList : new ArrayList<View>();
getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
event.setItemCount(focusablesTempList.size());
event.setCurrentItemIndex(focusablesTempList.indexOf(this));
if (mAttachInfo != null) {
focusablesTempList.clear();
}
} break;
case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
CharSequence text = getIterableTextForAccessibility();
if (text != null && text.length() > 0) {
//设置选中字符的开始位置
event.setFromIndex(getAccessibilitySelectionStart());
//设置选中字符的结束位置
event.setToIndex(getAccessibilitySelectionEnd());
//设置选中字符的长度,为什么不把选中的文字设置过来呢?
event.setItemCount(text.length());
}
} break;
}
}

上面的代码在View中对AccessibilityEvent对象的一些公共属性进行初始化,在View的子类可以重写此方法以便根据不同View组件来添加更多的信息.比如在TextView重写了此方法,进一步添加了事件的信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class TextView extends View implements ViewTreeObserver.onPreDrawListener{

@Override
public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
super.onInitializeAccessibilityEventInternal(event);

final boolean isPassword = hasPasswordTransformationMethod();
event.setPassword(isPassword);

if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
event.setFromIndex(Selection.getSelectionStart(mText));
event.setToIndex(Selection.getSelectionEnd(mText));
event.setItemCount(mText.length());
}
}


}

AccessibilityEvent发送到AMS

将AccessibilityEvent发送给AMS的具体操作最终由ViewRootImpl#requestSendAccessibilityEvent完成,具体流程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@Override
public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
if (mView == null || mStopped || mPausedForTransition) {
return false;
}

// Immediately flush pending content changed event (if any) to preserve event order
if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED
&& mSendWindowContentChangedAccessibilityEvent != null
&& mSendWindowContentChangedAccessibilityEvent.mSource != null) {
mSendWindowContentChangedAccessibilityEvent.removeCallbacksAndRun();
}

// Intercept accessibility focus events fired by virtual nodes to keep
// track of accessibility focus position in such nodes.
final int eventType = event.getEventType();
switch (eventType) {
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
final long sourceNodeId = event.getSourceNodeId();
final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
sourceNodeId);
View source = mView.findViewByAccessibilityId(accessibilityViewId);
if (source != null) {
AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
if (provider != null) {
final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
sourceNodeId);
final AccessibilityNodeInfo node;
node = provider.createAccessibilityNodeInfo(virtualNodeId);
setAccessibilityFocus(source, node);
}
}
} break;
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
final long sourceNodeId = event.getSourceNodeId();
final int accessibilityViewId = AccessibilityNodeInfo.getAccessibilityViewId(
sourceNodeId);
View source = mView.findViewByAccessibilityId(accessibilityViewId);
if (source != null) {
AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
if (provider != null) {
setAccessibilityFocus(null, null);
}
}
} break;


case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
handleWindowContentChangedEvent(event);
} break;
}
// mAccessibilityManager是AccessibilityManager类型实例,最终调用
// AccessibilityManager实例的sendAccessibilityEvent()来发送事件
mAccessibilityManager.sendAccessibilityEvent(event);
return true;
}

在上述方法中首先对一些特殊类型的事件做了处理,最后调用AccessibilityManager实例的sendAccessibilityEvent()来向AccessibilityManagerService发送事件.

AccessibilityManager创建

AccessibilityManager以单例的形式存在,在其构造函数中会尝试连接AMS服务,即AccessibilityManagerService.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public final class AccessibilityManager {
final Handler.Callback mCallback;
final Handler mHandler;

...

public static AccessibilityManager getInstance(Context context) {
synchronized (sInstanceSync) {
if (sInstance == null) {
final int userId;
......
sInstance = new AccessibilityManager(context, null, userId);
}
}
return sInstance;
}

public AccessibilityManager(Context context, IAccessibilityManager service, int userId) {
mCallback = new MyCallback();
mHandler = new Handler(context.getMainLooper(), mCallback);
mUserId = userId;
synchronized (mLock) {
// 尝试连接到AMS服务
tryConnectToServiceLocked(service);
}
}

}

在AccessibilityManager的构造函数中,最终的的是通过tryConnectToServiceLocked()方法来连接AMS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void tryConnectToServiceLocked(IAccessibilityManager service) {
if (service == null) {
IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
if (iBinder == null) {
return;
}
service = IAccessibilityManager.Stub.asInterface(iBinder);
}

try {
final long userStateAndRelevantEvents = service.addClient(mClient, mUserId);
setStateLocked(IntPair.first(userStateAndRelevantEvents));
mRelevantEventTypes = IntPair.second(userStateAndRelevantEvents);
mService = service;
} catch (RemoteException re) {
Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
}
}

上述代码中首先通过ServiceManager来获取AccessibilityManagerService在本地代理对象,即IAccessibilityManager实例,在IAccessibilityManager接口中暴露了AccessibilityManagerService对外提供的方法,这是典型Binder通信过程,在系统代码中涉及多进程通信的过程基本类似.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface IAccessibilityManager extends android.os.IInterface {

public static abstract class Stub extends android.os.Binder implements android.view.accessibility.IAccessibilityManager {
.......
}

private static class Proxy implements android.view.accessibility.IAccessibilityManager {
.......

@Override
public void sendAccessibilityEvent(android.view.accessibility.AccessibilityEvent uiEvent, int userId) throws android.os.RemoteException {
.......
}

@Override
public long addClient(android.view.accessibility.IAccessibilityManagerClient client, int userId) throws android.os.RemoteException {
......
}

.....

}
}

AccessibilityManager在获取AMS的本地代理对象IAccessibilityManager后,会继续调用IAccessibilityManager的addClient()方法来将mClient通过跨进程的方式传递到AccessibilityManagerService中.那mClient到底是什么呢?其定义如下:

1
2
3
4
5
6
public final class AccessibilityManager {
private final IAccessibilityManagerClient.Stub mClient =
new IAccessibilityManagerClient.Stub() {
.......
}
}

不难发现这里mClient同样是Binder对象.当AccessibilityManagerService需要通知客户端一些变化时会利用到它.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface IAccessibilityManagerClient extends android.os.IInterface {

public static abstract class Stub extends android.os.Binder implements android.view.accessibility.IAccessibilityManagerClient {
static final int TRANSACTION_setState = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_notifyServicesStateChanged = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
static final int TRANSACTION_setRelevantEventTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

......

private static class Proxy implements android.view.accessibility.IAccessibilityManagerClient {
.......
}
}

public void setState(int stateFlags) throws android.os.RemoteException;
public void notifyServicesStateChanged() throws android.os.RemoteException;
public void setRelevantEventTypes(int eventTypes) throws android.os.RemoteException;
}

AccessibilityManagerService#addClient

现在回过头来看AMS中的addClient()中具体做了什么事?

com.android.server.accessibility.AccessibilityManagerService#addClient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 @Override
public long addClient(IAccessibilityManagerClient callback, int userId) {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
UserState userState = getUserStateLocked(resolvedUserId);
// 对每个请求与AccessibilityManagerService通信的客户端创建Client对象
Client client = new Client(callback, Binder.getCallingUid(), userState);
if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) {
mGlobalClients.register(callback, client);
return IntPair.of(
userState.getClientState(),
client.mLastSentRelevantEventTypes);
} else {
userState.mUserClients.register(callback, client);
return IntPair.of(
(resolvedUserId == mCurrentUserId) ? userState.getClientState() : 0,
client.mLastSentRelevantEventTypes);
}
}
}

对于每个客户端而言,即从AccessibilityManager传来的mClient对象,也就是该方法的callback参数,AccessibilityManagerService会将其封装为Client.

image-20190113184139607

AccessibilityManager#sendAccessibilityEvent

AccessibilityManager发送事件到远程服务AccessibilityManagerService,

android.view.accessibility.AccessibilityManager#sendAccessibilityEvent

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public void sendAccessibilityEvent(AccessibilityEvent event) {
final IAccessibilityManager service;
final int userId;
synchronized (mLock) {
// 1.首先获取到AccessibilityManagerService的本地代理对象
service = getServiceLocked();
if (service == null) {
return;
}
// 2.检查Accessibility是否启用
if (!mIsEnabled) {
Looper myLooper = Looper.myLooper();
if (myLooper == Looper.getMainLooper()) {
throw new IllegalStateException(
"Accessibility off. Did you forget to check that?");
} else {
return;
}
}
if ((event.getEventType() & mRelevantEventTypes) == 0) {
return;
}
userId = mUserId;
}
try {
// 3.更新当前事件的时间
event.setEventTime(SystemClock.uptimeMillis());
long identityToken = Binder.clearCallingIdentity();
// 4.最终调用了AccessibilityManagerService服务的
// sendAccessibilityEvent()方法将事件发送到AMS
service.sendAccessibilityEvent(event, userId);
Binder.restoreCallingIdentity(identityToken);
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error during sending " + event + " ", re);
} finally {
//释放event对象,使其重新加入对象池以便重复利用
event.recycle();
}
}

在上述代码中,首先通过getServiceLocked()获取AccessibilityManagerService在本地的代理对象,即IAccessibilityManager的实例,其实现如下:

1
2
3
4
5
6
private IAccessibilityManager getServiceLocked() {
if (mService == null) {
tryConnectToServiceLocked(null);
}
return mService;
}

在该方法中最终还是借助tryConnectToServiceLocked()来连接AccessibilityManagerService.该方法返回的mService即之前IAccessibilityManager类型实例,也就是AMS在本地的代理对象,其真正的操作在AccessibilityManagerService.sendAccessibilityEvent()中,直接来看其实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class AccessibilityManagerService extends IAccessibilityManager.Stub {

...

@Override
public void sendAccessibilityEvent(AccessibilityEvent event, int userId) {
boolean dispatchEvent = false;

synchronized (mLock) {
if (event.getWindowId() ==
AccessibilityWindowInfo.PICTURE_IN_PICTURE_ACTION_REPLACER_WINDOW_ID) {
// The replacer window isn't shown to services. Move its events into the pip.
AccessibilityWindowInfo pip = mSecurityPolicy.getPictureInPictureWindow();
if (pip != null) {
int pipId = pip.getId();
event.setWindowId(pipId);
}
}

final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
// This method does nothing for a background user.
if (resolvedUserId == mCurrentUserId) {
if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(
event.getWindowId(), event.getSourceNodeId(),
event.getEventType(), event.getAction());
mSecurityPolicy.updateEventSourceLocked(event);
dispatchEvent = true;
}
if (mHasInputFilter && mInputFilter != null) {
mMainHandler.obtainMessage(
MainHandler.MSG_SEND_ACCESSIBILITY_EVENT_TO_INPUT_FILTER,
AccessibilityEvent.obtain(event)).sendToTarget();
}
}
}
// 1.需要分发事件
if (dispatchEvent) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
&& mWindowsForAccessibilityCallback != null) {
WindowManagerInternal wm = LocalServices.getService(WindowManagerInternal.class);
wm.computeWindowsForAccessibility();
}
synchronized (mLock) {
// 2.通知对应的AccessibilityServices
notifyAccessibilityServicesDelayedLocked(event, false);
notifyAccessibilityServicesDelayedLocked(event, true);
}
}

if (OWN_PROCESS_ID != Binder.getCallingPid()) {
event.recycle();
}
}

...
}

dispatchEvent为true表示需要向AccessibilityService分发事件,当需要进行事件分发时,最终会调用notifyAccessibilityServicesDelayedLocked():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event,
boolean isDefault) {
try {
UserState state = getCurrentUserStateLocked();
// mBoundServices保存了所有AccessibilityService与AMS的连接
for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
Service service = state.mBoundServices.get(i);

if (service.mIsDefault == isDefault) {
if (doesServiceWantEventLocked(service, event)) {
service.notifyAccessibilityEvent(event, true);
} else if (service.mUsesAccessibilityCache
&& (AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK
& event.getEventType()) != 0) {
service.notifyAccessibilityEvent(event, false);
}
}
}
} catch (IndexOutOfBoundsException oobe) {

}
}

上述方法中的mBoundServices是AMS中的成员变量,定义如下:

1
public final ArrayList<AccessibilityServiceConnection> mBoundServices = new ArrayList<>();

其中AccessibilityServiceConnection代表已经注册到AMS的AccessibilityService,也就是说mBoundServices保存了所有AccessibilityService与AMS的连接.比如我们自定义了一个辅助服务WXAccessibilityService,当该服务被启用时,AMS就会与该服务进行绑定,并生成对应的AccessibilityServiceConnection保存在mBoundServices中.(AccessibilityServiceConnection继承自AbstractAccessibilityServiceConnection)

notifyAccessibilityServicesDelayedLocked()方法中会遍历所有的AccessibilityServiceConnection对象,并调用其notifyAccessibilityEvent()来通知事件发生变化:

com.android.server.accessibility.AbstractAccessibilityServiceConnection#notifyAccessibilityEvent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 public void notifyAccessibilityEvent(AccessibilityEvent event) {
synchronized (mLock) {
final int eventType = event.getEventType();

final boolean serviceWantsEvent = wantsEventLocked(event);
final boolean requiredForCacheConsistency = mUsesAccessibilityCache
&& ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK & eventType) != 0);
if (!serviceWantsEvent && !requiredForCacheConsistency) {
return;
}

AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
// 1.根据event创建Message对象,后续将通过Handler进行处理
Message message;
if ((mNotificationTimeout > 0)
&& (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
// Allow at most one pending event
final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
mPendingEvents.put(eventType, newEvent);
if (oldEvent != null) {
mEventDispatchHandler.removeMessages(eventType);
oldEvent.recycle();
}
message = mEventDispatchHandler.obtainMessage(eventType);
} else {
// Send all messages, bypassing mPendingEvents
message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
}
message.arg1 = serviceWantsEvent ? 1 : 0;
// 2.发送Message,最终将其切换到主线程中进行处理
mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
}
}

由于此处分发过程发生在Binder线程池,需要借助Handler将其切换到主线程中,即mEventDispatchHandler,简单来看该Handler的创建以及对Message的处理过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub
implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter,
FingerprintGestureDispatcher.FingerprintGestureClient {

......

public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport,
WindowManagerInternal windowManagerInternal,
GlobalActionPerformer globalActionPerfomer) {
......
// 1.创建Handler,用于切换到主线程
mEventDispatchHandler = new Handler(mainHandler.getLooper()) {
@Override
public void handleMessage(Message message) {
final int eventType = message.what;
AccessibilityEvent event = (AccessibilityEvent) message.obj;
boolean serviceWantsEvent = message.arg1 != 0;
// 2.事件处理
notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent);
}
};
.......
}

......
}

在handleMessage()中继续调用notifyAccessibilityEventInternal()来将事件分发给具体的AccessibilityService.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private void notifyAccessibilityEventInternal(
int eventType,
AccessibilityEvent event,
boolean serviceWantsEvent) {
IAccessibilityServiceClient listener;

synchronized (mLock) {
listener = mServiceInterface;

if (listener == null) {
return;
}
// 1.根据eventType取出事件
if (event == null) {
event = mPendingEvents.get(eventType);
if (event == null) {
return;
}
mPendingEvents.remove(eventType);
}
// 2.进行权限检查,检查服务是否允许检索窗口内容
if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
event.setConnectionId(mId);
} else {
event.setSource((View) null);
}
event.setSealed(true);
}

try {
// 3.回调服务服务中的onAccessibityEvent()方法
listener.onAccessibilityEvent(event, serviceWantsEvent);
...
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
} finally {
event.recycle();
}
}

小结

当应用界面产生AccessibilityEvent需要被发送给辅助服务时,最终会调用ViewRootImpl中的requestSendAccessibilityEvent(),在该方法中最终通过AccessibilityManager跨进程调用AMS的sendAccessibilityEvent()方法将AccessibilityEvent传递到AMS中,AMS接受到该事件后遍历所有已经注册到系统的AccessibilityService,然后再次以跨进程的方式将AccessibilityEvent发送至自定义AccessibilityService所在进程.

总结

相比于ActivityManagerService或者PackageManagerService而言,AccessibilityServiceManager总体设计和架构都比较简单,更能加深对Binder使用的理解,同时通过简单的源码梳理,能帮助大家更有效的学习和使用辅助服务.此文拟稿与18年初,终结于19年初,一方面是向老东家360致敬,另一方面也作为新起点的标记.

CATALOG
  1. 1. AccessibilityService注册流程
    1. 1.1. AccessibilityService架构
    2. 1.2. AMS绑定AccessibilityService时机
    3. 1.3. 小结
  2. 2. AccessibilityEvent分发
    1. 2.1. AccessibilityEvent生成及初始化
      1. 2.1.1. 事件生成
      2. 2.1.2. 事件初始化
    2. 2.2. AccessibilityEvent发送到AMS
      1. 2.2.1. AccessibilityManager创建
      2. 2.2.2. AccessibilityManagerService#addClient
      3. 2.2.3. AccessibilityManager#sendAccessibilityEvent
    3. 2.3. 小结
  3. 3. 总结