From 74f9e1b867acbf248dd1640ef4c3f514b0ec9743 Mon Sep 17 00:00:00 2001 From: Phil Weaver Date: Wed, 2 Nov 2016 15:40:42 -0700 Subject: [PATCH] Add null check to a11y interrupt. Also adding same robustness to interrupt that we have for sending a11y events. Bug: 32507871 Test: Ran a11y CTS. Verified manually with sample app that sends interrupt and accessibility service that crashes when started. That case used to crash the app, and doesn't anymore. Change-Id: I5cf05dcbb54ea23ae876cb3258dd206c55dce775 (cherry picked from commit 867ad35d9c676b5ba2047b0fc9a4006737e5c4aa) --- .../accessibility/AccessibilityManager.java | 13 ++++++++++- .../AccessibilityManagerService.java | 23 +++++++++++++------ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 2dfa8cdd3db9e..286f5f7c1bf9b 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -353,7 +353,18 @@ public final class AccessibilityManager { return; } if (!mIsEnabled) { - throw new IllegalStateException("Accessibility off. Did you forget to check that?"); + Looper myLooper = Looper.myLooper(); + if (myLooper == Looper.getMainLooper()) { + throw new IllegalStateException( + "Accessibility off. Did you forget to check that?"); + } else { + // If we're not running on the thread with the main looper, it's possible for + // the state of accessibility to change between checking isEnabled and + // calling this method. So just log the error rather than throwing the + // exception. + Log.e(LOG_TAG, "Interrupt called with accessibility disabled"); + return; + } } userId = mUserId; } diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 58bb5f3793127..34ccb7b82c87c 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -538,7 +538,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public void interrupt(int userId) { - CopyOnWriteArrayList services; + List interfacesToInterrupt; synchronized (mLock) { // We treat calls from a profile as if made by its parent as profiles // share the accessibility state of the parent. The call below @@ -549,15 +549,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (resolvedUserId != mCurrentUserId) { return; } - services = getUserStateLocked(resolvedUserId).mBoundServices; + List services = getUserStateLocked(resolvedUserId).mBoundServices; + int numServices = services.size(); + interfacesToInterrupt = new ArrayList<>(numServices); + for (int i = 0; i < numServices; i++) { + Service service = services.get(i); + IBinder a11yServiceBinder = service.mService; + IAccessibilityServiceClient a11yServiceInterface = service.mServiceInterface; + if ((a11yServiceBinder != null) && (a11yServiceInterface != null)) { + interfacesToInterrupt.add(a11yServiceInterface); + } + } } - for (int i = 0, count = services.size(); i < count; i++) { - Service service = services.get(i); + for (int i = 0, count = interfacesToInterrupt.size(); i < count; i++) { try { - service.mServiceInterface.onInterrupt(); + interfacesToInterrupt.get(i).onInterrupt(); } catch (RemoteException re) { - Slog.e(LOG_TAG, "Error during sending interrupt request to " - + service.mService, re); + Slog.e(LOG_TAG, "Error sending interrupt request to " + + interfacesToInterrupt.get(i), re); } } }