本文主要是介绍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 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了:
- AMS绑定AS
- AM与AMS联系
- AccessibilityEvent Dispatch
- 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!