Android 9.0源码学习-AccessibilityManager

2024-06-06 22:38

本文主要是介绍Android 9.0源码学习-AccessibilityManager,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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 NameFile 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.addAct

这篇关于Android 9.0源码学习-AccessibilityManager的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1037437

相关文章

Android使用ImageView.ScaleType实现图片的缩放与裁剪功能

《Android使用ImageView.ScaleType实现图片的缩放与裁剪功能》ImageView是最常用的控件之一,它用于展示各种类型的图片,为了能够根据需求调整图片的显示效果,Android提... 目录什么是 ImageView.ScaleType?FIT_XYFIT_STARTFIT_CENTE

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Android实现在线预览office文档的示例详解

《Android实现在线预览office文档的示例详解》在移动端展示在线Office文档(如Word、Excel、PPT)是一项常见需求,这篇文章为大家重点介绍了两种方案的实现方法,希望对大家有一定的... 目录一、项目概述二、相关技术知识三、实现思路3.1 方案一:WebView + Office Onl

Android实现两台手机屏幕共享和远程控制功能

《Android实现两台手机屏幕共享和远程控制功能》在远程协助、在线教学、技术支持等多种场景下,实时获得另一部移动设备的屏幕画面,并对其进行操作,具有极高的应用价值,本项目旨在实现两台Android手... 目录一、项目概述二、相关知识2.1 MediaProjection API2.2 Socket 网络

Android实现悬浮按钮功能

《Android实现悬浮按钮功能》在很多场景中,我们希望在应用或系统任意界面上都能看到一个小的“悬浮按钮”(FloatingButton),用来快速启动工具、展示未读信息或快捷操作,所以本文给大家介绍... 目录一、项目概述二、相关技术知识三、实现思路四、整合代码4.1 Java 代码(MainActivi

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

Android Mainline基础简介

《AndroidMainline基础简介》AndroidMainline是通过模块化更新Android核心组件的框架,可能提高安全性,本文给大家介绍AndroidMainline基础简介,感兴趣的朋... 目录关键要点什么是 android Mainline?Android Mainline 的工作原理关键

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

Android实现打开本地pdf文件的两种方式

《Android实现打开本地pdf文件的两种方式》在现代应用中,PDF格式因其跨平台、稳定性好、展示内容一致等特点,在Android平台上,如何高效地打开本地PDF文件,不仅关系到用户体验,也直接影响... 目录一、项目概述二、相关知识2.1 PDF文件基本概述2.2 android 文件访问与存储权限2.

Android Studio 配置国内镜像源的实现步骤

《AndroidStudio配置国内镜像源的实现步骤》本文主要介绍了AndroidStudio配置国内镜像源的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录一、修改 hosts,解决 SDK 下载失败的问题二、修改 gradle 地址,解决 gradle