Android 9.0源码学习-AccessibilityManager

本文详细介绍了Android AccessibilityManager在Android 9.0中的工作原理,包括核心类AccessibilityManager、AccessibilityServiceManager和AccessibilityService的交互,以及AMS如何绑定AS、处理AccessibilityEvent的流程。此外,还探讨了AccessibilityEvent的触发、分发和响应过程。

Android Accessibility是为了帮助残障人士更好使用手机开发出来一个模块,比如屏幕阅读器,手势等等,当然现在已经被玩坏了,各种外挂,比如微信抢红包的外挂,也是基于Accessibility写出来的。

Android developer有关于Accessibility的介绍(需要科学上网),我自己也基于这个有一篇笔记Android-Accessibility(Android 8.0以上)

Accessibility Architecture

先拿一个具体的例子来看,这是一个抢红包的外挂,把WeChat称作Target APP,就是被监控的APP,当跳出来一个红包,触发了一个AccessibilityEvent,system_server中的AccessibilityManagerService将AccessibilityEvent分发给有AccessibilityService的APP,称为Accessibility APP,这个AccessibilityService受到这个AccessibilityEvent后,会找到这个页面的Open Button,模拟点击。(Target APP和Accessibility APP是我看别的博客这么取的)
在这里插入图片描述

Core Class

刚才举得例子是表象,那么程序内部,这个过程其实就是三个类之间的交互,当然实际不止这么简单啦,这个后面再讲,现在只要记住这三个是核心的类就好了。(以下都会用缩写代替

  • AccessibilityManager(AM):Send AccessibilityEvent
  • AccessibilityServiceManager(AMS):Dispatch
  • AccessibilityService(AS):Response

在这里插入图片描述

File List

File Name File Path
View.java /frameworks/base/core/java/android/view/View.java
ViewRootImpl.java /frameworks/base/core/java/android/view/ViewRootImpl.java
AccessibilityManager.java /frameworks/base/core/java/android/view/accessibility/AccessibilityManager.java
AccessibilityManagerService.java /frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
AbstractAccessibilityServiceConnection.java /frameworks/base/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
AccessibilityServiceConnection.java /frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
AccessibilityManagerService.java /frameworks/base/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
AccessibilityService.java /frameworks/base/core/java/android/accessibilityservice/AccessibilityService.java

Accessibility Flow

Accessibility Flow主要有下面几个Flow了:

  1. AMS绑定AS
  2. AM与AMS联系
  3. AccessibilityEvent Dispatch
  4. Response to AccessibilityEvent
    在这里插入图片描述

AMS绑定AS

在这里插入图片描述

上图是AMS与AS联系的flow,下面一步一步的来说。

Step1:什么时候AMS会绑定AS?

  • Settings->Accessibility->enable(enableAccessibilityServiceLocked()
  • Settings->Accessibility->disable(disableAccessibilityServiceLocked()
  • Some RegisterBroadcastReceivers (registerBroadcastReceivers()
    • onSomePackagesChanged()
    • onPackageUpdateFinished()
    • onHandleForceStop()
    • onPackageRemoved()
  • Others State Change

当用户在设置->无障碍里面选择了开启或关闭一个辅助功能,会导致一些系统状态会变化;Accessibility APP的安装状态会以BroadcastReceivers的方式会通知状态改变;还有其他的一些状态改变。这些变化最终会调用到AMS的onUserStateChangedLocked()方法。

在这里插入图片描述

AccessibilityManagerService.java – enableAccessibilityServiceLocked()

		  /**
2333       * Enables accessibility service specified by {@param componentName} for the {@param userId}.
2334       */
2335      private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
   
   
2336          final SettingStringHelper setting =
2337                  new SettingStringHelper(
2338                          mContext.getContentResolver(),
2339                          Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2340                          userId);
2341          setting.write(ComponentNameSet.add(setting.read(), componentName));
2342  
2343          UserState userState = getUserStateLocked(userId);
2344          if (userState.mEnabledServices.add(componentName)) {
   
   
2345              onUserStateChangedLocked(userState);
2346          }
2347      }

AccessibilityManagerService.java – disableAccessibilityServiceLocked()

    	 /**
2350       * Disables accessibility service specified by {@param componentName} for the {@param userId}.
2351       */
2352      private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
   
   
2353          final SettingsStringUtil.SettingStringHelper setting =
2354                  new SettingStringHelper(
2355                          mContext.getContentResolver(),
2356                          Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
2357                          userId);
2358          setting.write(ComponentNameSet.remove(setting.read(), componentName));
2359  
2360          UserState userState = getUserStateLocked(userId);
2361          if (userState.mEnabledServices.remove(componentName)) {
   
   
2362              onUserStateChangedLocked(userState);
2363          }
2364      }

AccessibilityManagerService.java – registerBroadcastReceivers()

    private void registerBroadcastReceivers() {
   
   
324          PackageMonitor monitor = new PackageMonitor() {
   
   
325              @Override
326              public void onSomePackagesChanged() {
   
   
327                  synchronized (mLock) {
   
   
328                      // Only the profile parent can install accessibility services.
329                      // Therefore we ignore packages from linked profiles.
330                      if (getChangingUserId() != mCurrentUserId) {
   
   
331                          return;
332                      }
333                      // We will update when the automation service dies.
334                      UserState userState = getCurrentUserStateLocked();
335                      // We have to reload the installed services since some services may
336                      // have different attributes, resolve info (does not support equals),
337                      // etc. Remove them then to force reload.
338                      userState.mInstalledServices.clear();
339                      if (readConfigurationForUserStateLocked(userState)) {
   
   
340                          onUserStateChangedLocked(userState);
341                      }
342                  }
343              }
344  
345              @Override
346              public void onPackageUpdateFinished(String packageName, int uid) {
   
   
347                  // Unbind all services from this package, and then update the user state to
348                  // re-bind new versions of them.
349                  synchronized (mLock) {
   
   
350                      final int userId = getChangingUserId();
351                      if (userId != mCurrentUserId) {
   
   
352                          return;
353                      }
354                      UserState userState = getUserStateLocked(userId);
355                      boolean unboundAService = false;
356                      for (int i = userState.mBoundServices.size() - 1; i >= 0; i--) {
   
   
357                          AccessibilityServiceConnection boundService =
358                                  userState.mBoundServices.get(i);
359                          String servicePkg = boundService.mComponentName.getPackageName();
360                          if (servicePkg.equals(packageName)) {
   
   
361                              boundService.unbindLocked();
362                              unboundAService = true;
363                          }
364                      }
365                      if (unboundAService) {
   
   
366                          onUserStateChangedLocked(userState);
367                      }
368                  }
369              }
370  
371              @Override
372              public void onPackageRemoved(String packageName, int uid) {
   
   
373                  synchronized (mLock) {
   
   
374                      final int userId = getChangingUserId();
375                      // Only the profile parent can install accessibility services.
376                      // Therefore we ignore packages from linked profiles.
377                      if (userId != mCurrentUserId) {
   
   
378                          return;
379                      }
380                      UserState userState = getUserStateLocked(userId);
381                      Iterator<ComponentName> it = userState.mEnabledServices.iterator();
382                      while (it.hasNext()) {
   
   
383                          ComponentName comp = it.next();
384                          String compPkg = comp.getPackageName();
385                          if (compPkg.equals(packageName)) {
   
   
386                              it.remove();
387                              // Update the enabled services setting.
388                              persistComponentNamesToSettingLocked(
389                                      Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
390                                      userState.mEnabledServices, userId);
391                              // Update the touch exploration granted services setting.
392                              userState.mTouchExplorationGrantedServices.remove(comp);
393                              persistComponentNamesToSettingLocked(
394                                      Settings.Secure.
395                                      TOUCH_EXPLORATION_GRANTED_ACCESSIBILITY_SERVICES,
396                                      userState.mTouchExplorationGrantedServices, userId);
397                              onUserStateChangedLocked(userState);
398                              return;
399                          }
400                      }
401                  }
402              }
403  
404              @Override
405              public boolean onHandleForceStop(Intent intent, String[] packages,
406                      int uid, boolean doit) {
   
   
407                  synchronized (mLock) {
   
   
408                      final int userId = getChangingUserId();
409                      // Only the profile parent can install accessibility services.
410                      // Therefore we ignore packages from linked profiles.
411                      if (userId != mCurrentUserId) {
   
   
412                          return false;
413                      }
414                      UserState userState = getUserStateLocked(userId);
415                      Iterator<ComponentName> it = userState.mEnabledServices.iterator();
416                      while (it.hasNext()) {
   
   
417                          ComponentName comp = it.next();
418                          String compPkg = comp.getPackageName();
419                          for (String pkg : packages) {
   
   
420                              if (compPkg.equals(pkg)) {
   
   
421                                  if (!doit) {
   
   
422                                      return true;
423                                  }
424                                  it.remove();
425                                  persistComponentNamesToSettingLocked(
426                                          Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
427                                          userState.mEnabledServices, userId);
428                                  onUserStateChangedLocked(userState);
429                              }
430                          }
431                      }
432                      return false;
433                  }
434              }
435          };
436  
437          // package changes
438          monitor.register(mContext, null,  UserHandle.ALL, true);
439  
440          // user change and unlock
441          IntentFilter intentFilter = new IntentFilter();
442          intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
443          intentFilter.addAction(Intent.ACTION_USER_UNLOCKED)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值