欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?AccessibilityService?事件分發(fā)原理分析總結(jié)

 更新時間:2022年06月16日 10:22:22   作者:??自動化BUG制造器????  
這篇文章主要介紹了Android?AccessibilityService?事件分發(fā)原理分析總結(jié),AccessibilityService有很多用來接收外部調(diào)用事件變化的方法,這些方法封裝在內(nèi)部接口Callbacks中,文章圍繞AccessibilityService相關(guān)資料展開詳情,需要的朋友可以參考一下

前言:

在了解了無障礙服務(wù)基礎(chǔ)使用之后,我們來探究一下 AccessibilityService 的事件接收方法回調(diào)的時機(jī)和它深層次的實(shí)現(xiàn)邏輯。

AccessibilityService 監(jiān)聽事件的調(diào)用邏輯

AccessibilityService 有很多用來接收外部調(diào)用事件變化的方法,這些方法封裝在內(nèi)部接口 Callbacks 中:

public interface Callbacks {
    void onAccessibilityEvent(AccessibilityEvent event);
    void onInterrupt();
    void onServiceConnected();
    void init(int connectionId, IBinder windowToken);
    boolean onGesture(AccessibilityGestureEvent gestureInfo);
    boolean onKeyEvent(KeyEvent event);
    void onMagnificationChanged(int displayId, @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(int displayId);
    void onAccessibilityButtonAvailabilityChanged(boolean available);
    void onSystemActionsChanged();
}

以最常用的 onAccessibilityEvent 為例,介紹一下調(diào)用流程。

onAccessibilityEvent 在 AccessibilityService 中,AccessibilityService 在 onBind 生命周期中,返回了一個IAccessibilityServiceClientWrapper 對象,它是一個 Binder ,所以外部實(shí)際上通過 Binder 機(jī)制跨進(jìn)程調(diào)用到無障礙服務(wù)的。

外部通過 Binder 調(diào)用到 Service 具體的實(shí)現(xiàn)方法的調(diào)用棧是:

- frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java#IAccessibilityServiceClientWrapper#onAccessibilityEvent
- frameworks/base/core/java/com/android/internal/os/HandlerCaller.java#sendMessage
- frameworks/base/core/java/com/android/internal/os/HandlerCaller.java#Callback#executeMessage
- frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java#IAccessibilityServiceClientWrapper#executeMessage
- frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java#Callbacks#onAccessibilityEvent
- frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java#onAccessibilityEvent

首先是外部調(diào)用到 IAccessibilityServiceClientWrapper 的 onAccessibilityEvent 方法:

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

在這個方法中通過 HandlerCaller 切換到主線程,然后發(fā)送了一個消息。

這里的 HandlerCaller 的源碼是:

public class HandlerCaller {
    final Looper mMainLooper;
    final Handler mH;
    final Callback mCallback;
    class MyHandler extends Handler {
        MyHandler(Looper looper, boolean async) {
            super(looper, null, async);
        }
        @Override
        public void handleMessage(Message msg) {
            mCallback.executeMessage(msg);
        }
    }
    public interface Callback {
        public void executeMessage(Message msg);
    }
    public HandlerCaller(Context context, Looper looper, Callback callback,
            boolean asyncHandler) {
        mMainLooper = looper != null ? looper : context.getMainLooper();
        mH = new MyHandler(mMainLooper, asyncHandler);
        mCallback = callback;
    }
    ...
}

從它的源碼中可以看出,這是一個向主線程發(fā)消息的 Handler 。 在主線程中執(zhí)行它的內(nèi)部類 Callback 的 executeMessage 方法。

IAccessibilityServiceClientWrapper 實(shí)現(xiàn)了 AccessibilityService.Callback接口,所以調(diào)用到了IAccessibilityServiceClientWrapper.executeMessage 方法中。IAccessibilityServiceClientWrapper 對象的創(chuàng)建是在 onBind 生命周期中。它接收一個 AccessibilityService.Callback 對象作為 IAccessibilityServiceClientWrapper 的構(gòu)造參數(shù):

@Override
public final IBinder onBind(Intent intent) {
    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);
        }
	...
});

IAccessibilityServiceClientWrapper 中的 executeMessage中,根據(jù)不同的 Handler 消息調(diào)用了 AccessibilityService.Callback 的對應(yīng)方法:

public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub implements HandlerCaller.Callback {
    private final HandlerCaller mCaller;
    public IAccessibilityServiceClientWrapper(Context context, Looper looper,
        Callbacks callback) {
        // ...
        mCaller = new HandlerCaller(context, looper, this, true);
    }
    @Override
    public void executeMessage(Message message) {
        switch (message.what) {
            case DO_ON_ACCESSIBILITY_EVENT: {
                // ...
                mCallback.onAccessibilityEvent(event);
                return;
            }
            case DO_ON_INTERRUPT: {
                // ...
                mCallback.onInterrupt();
                return;
            }
            default :
                Log.w(LOG_TAG, "Unknown message type " + message.what);
        }   
    }
}

而剛才傳入的 AccessibilityService.Callback 方法的實(shí)現(xiàn)中,調(diào)用了AccessibilityService 的 onAccessibilityEvent 方法:

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

這樣整個調(diào)用鏈就清晰了:

  • 外部通過 Binder 機(jī)制調(diào)用到 AccessibilityService 的內(nèi)部 Binder 代理實(shí)現(xiàn)IAccessibilityServiceClientWrapper對象
  • IAccessibilityServiceClientWrapper對象內(nèi)部通過 Handler 機(jī)制切換到主線程執(zhí)行 AccessibilityService.Callback 中對應(yīng)的方法。
  • AccessibilityService.Callback 中的方法調(diào)用到了AccessibilityService 對應(yīng)的生命周期方法。

接下來關(guān)注一下一些重要的事件接收方法。

onAccessibilityEvent

Handler 中的 DO_ON_ACCESSIBILITY_EVENT 事件會調(diào)用到 onAccessibilityEvent 。 在 executeMessage(Message message) 方法中的邏輯是:

case DO_ON_ACCESSIBILITY_EVENT: {
    AccessibilityEvent event = (AccessibilityEvent) message.obj;
    boolean serviceWantsEvent = message.arg1 != 0;
    if (event != null) {
        // Send the event to AccessibilityCache via AccessibilityInteractionClient
        AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
                event);
        if (serviceWantsEvent
                && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
            // Send the event to AccessibilityService
            mCallback.onAccessibilityEvent(event);
        }
        // Make sure the event is recycled.
        try {
            event.recycle();
        } catch (IllegalStateException ise) {
            /* ignore - best effort */
        }
    }
    return;
}
  • 取出 message.obj 轉(zhuǎn)換為 AccessibilityEvent ,并根據(jù) message.arg1檢查 Service 是否想要處理這個事件。
  • 檢查 AccessibilityEvent對象是否為 null,為空直接 return
  • 將 AccessibilityEvent對象通過 AccessibilityInteractionClient 加入到 AccessibilityCache 緩存中,然后根據(jù) service 是否要處理事件和AccessibilityInteractionClient連接狀態(tài),決定是否要將事件發(fā)送給 AccessibilityService
  • 最后回收事件對象。

這里的AccessibilityInteractionClient連接狀態(tài)檢查時通過 mConnectionId 屬性來判斷的,在IAccessibilityServiceClientWrapper 的 init 時被賦值,init 也是通過 Handler 傳遞來的消息切換到主線程進(jìn)行的:

case DO_INIT: {
    mConnectionId = message.arg1;
    SomeArgs args = (SomeArgs) message.obj;
    IAccessibilityServiceConnection connection =
            (IAccessibilityServiceConnection) args.arg1;
    IBinder windowToken = (IBinder) args.arg2;
    args.recycle();
    if (connection != null) {
        AccessibilityInteractionClient.getInstance(mContext).addConnection(
                mConnectionId, connection);
        mCallback.init(mConnectionId, windowToken);
        mCallback.onServiceConnected();
    } else {
        AccessibilityInteractionClient.getInstance(mContext).removeConnection(
                mConnectionId);
        mConnectionId = AccessibilityInteractionClient.NO_ID;
        AccessibilityInteractionClient.getInstance(mContext).clearCache();
        mCallback.init(AccessibilityInteractionClient.NO_ID, null);
    }
    return;
}

onIntercept

onAccessibilityEvent 事件一樣都是通過 Handler 機(jī)制進(jìn)行處理的:

case DO_ON_INTERRUPT: {
    if (mConnectionId != AccessibilityInteractionClient.NO_ID) {
        mCallback.onInterrupt();
    }
    return;
}

只檢查了與AccessibilityInteractionClient 的連接狀態(tài)。

AccessibilityService 事件的外部來源

經(jīng)過上面的分析,我們知道外部通過 binder 機(jī)制觸發(fā)了 AccessibilityService 的事件監(jiān)聽方法,那么它們來自哪里呢? 接下來從 AccessibilityServiceInfo 開始,分析系統(tǒng)事件是如何傳遞到無障礙服務(wù)的。

AccessibilityServiceInfo

AccessibilityServiceInfo 用來描述 AccessibilityService 。系統(tǒng)根據(jù)這個類中的信息,將 AccessibilityEvents 通知給一個 AccessibilityService。

AccessibilityServiceInfo 中定義了一些屬性,用來控制無障礙服務(wù)的一些權(quán)限和能力。我們在 AndroidManifest.xml 中為無障礙服務(wù)指定的meta-data 標(biāo)簽中,指定的配置文件中的配置,和AccessibilityServiceInfo 中的屬性一一對應(yīng)。

AccessibilityServiceInfo 的引用:

查看 AccessibilityServiceInfo 的引用棧,發(fā)現(xiàn)有很多地方都用到了這個類,關(guān)于無障礙的重點(diǎn)看 AccessibilityManagerService 和 AccessibilityManager 這一套邏輯。 從名稱上看,無障礙功能提供了類似 AMS 一樣的系統(tǒng)服務(wù),并通過一個 Manager 類來進(jìn)行調(diào)用。

AccessibilityManager

AccessibilityManager 是一個系統(tǒng)服務(wù)管理器,用來分發(fā) AccessibilityEvent 事件。當(dāng)用戶界面中發(fā)生一些值得注意的事件時,例如焦點(diǎn)變化和 Activity 啟動等,會生成這些事件。

AccessibilityManager 內(nèi)部有一個看起來與發(fā)送消息有關(guān)的方法:

public void sendAccessibilityEvent(AccessibilityEvent event) {
        final IAccessibilityManager service;
        final int userId;
        final AccessibilityEvent dispatchedEvent;
        synchronized (mLock) {
            service = getServiceLocked();
            if (service == null) return;
            event.setEventTime(SystemClock.uptimeMillis());
            if (event.getAction() == 0) {
                event.setAction(mPerformingAction);
            }
            if (mAccessibilityPolicy != null) {
                dispatchedEvent = mAccessibilityPolicy.onAccessibilityEvent(event, mIsEnabled, mRelevantEventTypes);
                if (dispatchedEvent == null) return;
            } else {
                dispatchedEvent = event;
            }
            if (!isEnabled()) {
                Looper myLooper = Looper.myLooper();
                if (myLooper == Looper.getMainLooper()) {
                    throw new IllegalStateException("Accessibility off. Did you forget to check that?");
                } else {
                    // 當(dāng)不是在主線程(mainLooper)運(yùn)行時,調(diào)用檢查無障礙開啟狀態(tài)可能會異常。因此直接拋出異常
                    Log.e(LOG_TAG, "AccessibilityEvent sent with accessibility disabled");
                    return;
                }
            }
            userId = mUserId;
        }
        try {
            final long identityToken = Binder.clearCallingIdentity();
            try {
                service.sendAccessibilityEvent(dispatchedEvent, userId);
            } finally {
                Binder.restoreCallingIdentity(identityToken);
            }
            if (DEBUG) {
                Log.i(LOG_TAG, dispatchedEvent + " sent");
            }
        } catch (RemoteException re) {
            Log.e(LOG_TAG, "Error during sending " + dispatchedEvent + " ", re);
        } finally {
            if (event != dispatchedEvent) {
                event.recycle();
            }
            dispatchedEvent.recycle();
        }
    }

這個方法是用來發(fā)送一個 AccessibilityEvent 事件的,簡化里面的邏輯:

- 加鎖
- getServiceLocked() 獲取 service 對象,service 獲取不到直接 return
- event 設(shè)置一個時間,然后設(shè)置 action
- 檢查 AccessibilityPolicy 對象是否為 null
  - 不為空,dispatchedEvent 根據(jù) AccessibilityPolicy 的 onAccessibilityEvent(event) 賦值,賦值后仍為空直接 return
  - 為空, dispatchedEvent = event
- 檢查系統(tǒng)是否開啟無障礙功能
- 解鎖
- try
  - try
    - service.sendAccessibilityEvent(dispatchedEvent, userId); 通過 AccessibilityManagerService 的 sendAccessibilityEvent 發(fā)送事件
  - finally
    - Binder.restoreCallingIdentity(identityToken); 
- finally
  - 回收 event 和 dispatchedEvent 對象

這里 getServiceLocked() 內(nèi)部調(diào)用了 tryConnectToServiceLocked 方法:

    private void tryConnectToServiceLocked(IAccessibilityManager service) {
        if (service == null) {
            IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
            if (iBinder == null) {
                return;
            }
            service = IAccessibilityManager.Stub.asInterface(iBinder);
        }
		  // ...
    }

而 AccessibilityManagerService 實(shí)現(xiàn)了 IAccessibilityManager.Stub ,所以這里的 service 時 AccessibilityManagerService。 這里調(diào)用了 service.sendAccessibilityEvent(dispatchedEvent, userId);

通過 Binder 機(jī)制,調(diào)用到的是 AccessibilityManagerService 里的 sendAccessibilityEvent 方法。

AccessibilityManager.sendAccessibilityEvent 的調(diào)用位置有很多,其中比較顯眼的是在 ViewRootImpl 中的,因?yàn)?ViewRootImpl 是 View 添加到 Window 的重要實(shí)現(xiàn)類。sendAccessibilityEvent 在 ViewRootImpl 的內(nèi)部類中存在調(diào)用:

    @Override
    public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
        // ...
        final int eventType = event.getEventType();
        final View source = getSourceForAccessibilityEvent(event);
        switch (eventType) {
            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
                if (source != null) {
                    AccessibilityNodeProvider provider = source.getAccessibilityNodeProvider();
                    if (provider != null) {
                        final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(event.getSourceNodeId());
                        final AccessibilityNodeInfo node;
                        node = provider.createAccessibilityNodeInfo(virtualNodeId);
                        setAccessibilityFocus(source, node);
                    }
                }
            } break;
            case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
                if (source != null && source.getAccessibilityNodeProvider() != null) {
                    setAccessibilityFocus(null, null);
                }
            } break;
            case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
                handleWindowContentChangedEvent(event);
            } break;
        }
        mAccessibilityManager.sendAccessibilityEvent(event);
        return true;
    }

這是一個 override 方法,它的定義在接口 ViewParent 中。 這個方法的調(diào)用棧很多:

可以跟到 View 中存在的同名方法 :

public void sendAccessibilityEvent(int eventType) {
    if (mAccessibilityDelegate != null) {
        mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
    } else {
        sendAccessibilityEventInternal(eventType);
    }
}

它在 View 中的調(diào)用:

可以看出,常見的 View 的事件,包括:點(diǎn)擊、長按、焦點(diǎn)變化等,都會調(diào)用sendAccessibilityEvent方法。

在 ViewRootImpl中,AccessibilityManager也存在很多處調(diào)用邏輯:

可以看出在 Android 在 View 體系中,提供了很多對無障礙能力的支持。所有的 View 的事件都會被系統(tǒng)的無障礙服務(wù)捕獲到。

回到調(diào)用邏輯,AccessibilityManager內(nèi)部調(diào)用到的是AccessibilityManagerService里的sendAccessibilityEvent方法。下面介紹 AccessibilityManagerService里面的流程。

AccessibilityManagerService

sendAccessibilityEvent偽代碼邏輯:

synchronized {
	1. 解析配置文件中的屬性,并對其進(jìn)行配置
	2. 設(shè)置配置的包名范圍
}
if (dispatchEvent) {
	3. 確保接收此事件的 client 能夠獲取 window 當(dāng)前的狀態(tài),因?yàn)?Window Manager 可能會出于性能原因延遲計(jì)算,通過配置 shouldComputeWindows = true/false
	if (shouldComputeWindows) {
		4. 獲取 WindowManagerInternal wm 
		5. wm.computeWindowsForAccessibility(displayId);
	}
	synchoronized {
		notifyAccessibilityServicesDelayedLocked(event, false)
		notifyAccessibilityServicesDelayedLocked(event, true)
		mUiAutomationManager.sendAccessibilityEventLocked(event);
	}
}
...

最后的關(guān)鍵三行代碼中,調(diào)用了兩個方法:

notifyAccessibilityServicesDelayedLocked :

    private void notifyAccessibilityServicesDelayedLocked(AccessibilityEvent event, boolean isDefault) {
        try {
            AccessibilityUserState state = getCurrentUserStateLocked();
            for (int i = 0, count = state.mBoundServices.size(); i < count; i++) {
                AccessibilityServiceConnection service = state.mBoundServices.get(i);
                if (service.mIsDefault == isDefault) {
                    service.notifyAccessibilityEvent(event);
                }
            }
        } catch (IndexOutOfBoundsException oobe) {}
    }

AccessibilityManagerService從這個方法中,調(diào)用 AccessibilityServiceConnection的同名方法notifyAccessibilityEvent 。

這個意思是,先通知service.mIsDefault = false的無障礙服務(wù)連接發(fā)送事件,然后再通知 等于 true 的無障礙服務(wù)連接發(fā)送事件。

mUiAutomationManager.sendAccessibilityEventLocked(event)

mUiAutomationManager的類型是UiAutomationManager,它的sendAccessibilityEventLocked方法實(shí)現(xiàn)是:

void sendAccessibilityEventLocked(AccessibilityEvent event) {
    if (mUiAutomationService != null) {
        mUiAutomationService.notifyAccessibilityEvent(event);
    }
}

mUiAutomationService的類型是 UiAutomationService,它是UiAutomationManager的內(nèi)部類,繼承自AbstractAccessibilityServiceConnection,內(nèi)部操作都是切換到主線程進(jìn)行的,notifyAccessibilityEvent方法的實(shí)現(xiàn)在父類中,后續(xù)會和上面的AccessibilityServiceConnection一起說明。

AccessibilityServiceConnection

此類用來表示一個無障礙服務(wù)。 它存儲著服務(wù)管理所需的所有每個服務(wù)數(shù)據(jù),提供用于啟動/停止服務(wù)的 API,并負(fù)責(zé)在服務(wù)管理的數(shù)據(jù)結(jié)構(gòu)中添加/刪除服務(wù)。 該類還公開了配置接口,該接口在綁定后立即傳遞給它所代表的服務(wù)。 它還用作服務(wù)的連接。

AccessibilityServiceConnectionUiAutomationService 一樣,繼承自AbstractAccessibilityServiceConnection

它們的notifyAccessibilityEvent方法,在AbstractAccessibilityServiceConnection中:

    public void notifyAccessibilityEvent(AccessibilityEvent event) {
        synchronized (mLock) {
            ...
            // copy 一個副本,因?yàn)樵谡{(diào)度期間,如果接收的服務(wù)沒有訪問窗口內(nèi)容的權(quán)限,則可能會修改并刪除事件。
            AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
            Message message;
            if ((mNotificationTimeout > 0)
                    && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
                // 最多允許一個待處理事件
                final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
                mPendingEvents.put(eventType, newEvent);
                if (oldEvent != null) {
                    mEventDispatchHandler.removeMessages(eventType);
                    oldEvent.recycle();
                }
                message = mEventDispatchHandler.obtainMessage(eventType);
            } else {
                // 發(fā)送所有消息,繞過 mPendingEvents
                message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
            }
            message.arg1 = serviceWantsEvent ? 1 : 0;

            mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
        }
    }

這個方法中,通過一個 Handler 來處理和發(fā)送消息。

        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;
                notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent);
            }
        };

內(nèi)部調(diào)用notifyAccessibilityEventInternal

private void notifyAccessibilityEventInternal(int eventType, AccessibilityEvent event, boolean serviceWantsEvent) {
    IAccessibilityServiceClient listener;
    synchronized (mLock) {
        listener = mServiceInterface;
        // 如果在消息分發(fā)無障礙事件時 service die 或 關(guān)閉,listener 可能為空
        if (listener == null) return;
        // 我們有兩種通知事件的方式,節(jié)流和非節(jié)流。 如果我們不進(jìn)行節(jié)流,那么消息會隨事件一起出現(xiàn),我們會毫不費(fèi)力地處理這些事件。
        if (event == null) {
            // 我們正在限制事件,所以只要它為空,我們就會在 mPendingEvents 中發(fā)送這種類型的事件。 由于競爭條件,它只能為空:
            //   1) 一個 binder 線程調(diào)用 notifyAccessibilityServiceDelayedLocked,它發(fā)布一條用于調(diào)度事件的消息并將該事件存儲在 mPendingEvents 中。
            //   2) 消息由服務(wù)線程上的處理程序從隊(duì)列中拉出,此方法即將獲取鎖。
            //   3) 另一個 binder 線程在 notifyAccessibilityEvent 中獲取鎖
            //   4) notifyAccessibilityEvent 回收該方法即將處理的事件,替換為新的,并發(fā)布第二條消息
            //   5) 此方法抓取新事件,對其進(jìn)行處理,然后將其從 mPendingEvents 中刪除
            //   6) (4) 中發(fā)送的第二條消息到達(dá),但事件已在 (5) 中刪除。
            event = mPendingEvents.get(eventType);
            if (event == null) {
                return;
            }
            mPendingEvents.remove(eventType);
        }
        if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
            event.setConnectionId(mId);
        } else {
            event.setSource((View) null);
        }
        event.setSealed(true);
    }

    try {
        listener.onAccessibilityEvent(event, serviceWantsEvent);

    } catch (RemoteException re) {} finally {
        event.recycle();
    }
}

備注中說明了消息處理和分發(fā)邏輯,但我們這里只需要關(guān)注最后的:

listener.onAccessibilityEvent(event, serviceWantsEvent);

這里的 listener 是一個IAccessibilityServiceClient,是個 AIDL 文件。這個 AIDL 在我們的 AccessibilityService 中有實(shí)現(xiàn)類!

調(diào)用到這個IAccessibilityServiceClient , 就能調(diào)用到AccessibilityService中的代碼了。

至此無障礙服務(wù)的調(diào)用,從系統(tǒng)的 View 和其他事件位置,經(jīng)過AccessibilityManager.notifyAccessibilityEvent用 Binder 機(jī)制調(diào)用AccessibilityManagerService.notifyAccessibilityEvent ;然后AccessibilityManagerService內(nèi)部通過調(diào)用AccessibilityServiceConnection.notifyAccessibilityEvent來調(diào)用我們可以實(shí)現(xiàn)的AccessibilityService中接收事件。

到此這篇關(guān)于Android AccessibilityService 事件分發(fā)原理分析總結(jié)的文章就介紹到這了,更多相關(guān)Android AccessibilityService 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論