summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/accessibilityservice/AccessibilityServiceInfo.java15
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java14
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java6
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java16
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java9
-rw-r--r--services/accessibility/java/com/android/server/accessibility/MagnificationController.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java33
7 files changed, 79 insertions, 16 deletions
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index 0b10a35b5d5e..452225cd7da0 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -16,6 +16,8 @@
package android.accessibilityservice;
+import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
+
import android.annotation.IntDef;
import android.content.ComponentName;
import android.content.Context;
@@ -50,8 +52,6 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
-
/**
* This class describes an {@link AccessibilityService}. The system notifies an
* {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
@@ -410,6 +410,15 @@ public class AccessibilityServiceInfo implements Parcelable {
public int flags;
/**
+ * Whether or not the service has crashed and is awaiting restart. Only valid from {@link
+ * android.view.accessibility.AccessibilityManager#getEnabledAccessibilityServiceList(int)},
+ * because that is populated from the internal list of running services.
+ *
+ * @hide
+ */
+ public boolean crashed;
+
+ /**
* The component name the accessibility service.
*/
private ComponentName mComponentName;
@@ -757,6 +766,7 @@ public class AccessibilityServiceInfo implements Parcelable {
parcel.writeInt(feedbackType);
parcel.writeLong(notificationTimeout);
parcel.writeInt(flags);
+ parcel.writeInt(crashed ? 1 : 0);
parcel.writeParcelable(mComponentName, flagz);
parcel.writeParcelable(mResolveInfo, 0);
parcel.writeString(mSettingsActivityName);
@@ -773,6 +783,7 @@ public class AccessibilityServiceInfo implements Parcelable {
feedbackType = parcel.readInt();
notificationTimeout = parcel.readLong();
flags = parcel.readInt();
+ crashed = parcel.readInt() != 0;
mComponentName = parcel.readParcelable(this.getClass().getClassLoader());
mResolveInfo = parcel.readParcelable(null);
mSettingsActivityName = parcel.readString();
diff --git a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
index 350b64882ed5..8473c06c1ac7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/accessibility/AccessibilityUtils.java
@@ -20,6 +20,7 @@ import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.UserHandle;
@@ -50,6 +51,19 @@ public class AccessibilityUtils {
return getEnabledServicesFromSettings(context, UserHandle.myUserId());
}
+ public static boolean hasServiceCrashed(String packageName, String serviceName,
+ List<AccessibilityServiceInfo> enabledServiceInfos) {
+ for (int i = 0; i < enabledServiceInfos.size(); i++) {
+ AccessibilityServiceInfo accessibilityServiceInfo = enabledServiceInfos.get(i);
+ final ServiceInfo serviceInfo = enabledServiceInfos.get(i).getResolveInfo().serviceInfo;
+ if (TextUtils.equals(serviceInfo.packageName, packageName)
+ && TextUtils.equals(serviceInfo.name, serviceName)) {
+ return accessibilityServiceInfo.crashed;
+ }
+ }
+ return false;
+ }
+
/**
* @return the set of enabled accessibility services for {@param userId}. If there are no
* services, it returns the unmodifiable {@link Collections#emptySet()}.
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index ed068b931bad..5c5978ad1adc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -88,7 +88,7 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
final int mId;
- final AccessibilityServiceInfo mAccessibilityServiceInfo;
+ protected final AccessibilityServiceInfo mAccessibilityServiceInfo;
// Lock must match the one used by AccessibilityManagerService
protected final Object mLock;
@@ -340,6 +340,10 @@ abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServ
}
}
+ public int getCapabilities() {
+ return mAccessibilityServiceInfo.getCapabilities();
+ }
+
int getRelevantEventTypes() {
return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK : 0)
| mEventTypes;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index ecd47e8dd39e..8941b4926584 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -621,7 +621,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
for (int i = 0; i < serviceCount; ++i) {
final AccessibilityServiceConnection service = services.get(i);
if ((service.mFeedbackType & feedbackType) != 0) {
- result.add(service.mAccessibilityServiceInfo);
+ result.add(service.getServiceInfo());
}
}
return result;
@@ -1874,7 +1874,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final int serviceCount = userState.mBoundServices.size();
for (int i = 0; i < serviceCount; i++) {
AccessibilityServiceConnection service = userState.mBoundServices.get(i);
- if ((service.mAccessibilityServiceInfo.getCapabilities()
+ if ((service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0) {
userState.mIsPerformGesturesEnabled = true;
return;
@@ -1888,7 +1888,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
for (int i = 0; i < serviceCount; i++) {
AccessibilityServiceConnection service = userState.mBoundServices.get(i);
if (service.mRequestFilterKeyEvents
- && (service.mAccessibilityServiceInfo.getCapabilities()
+ && (service.getCapabilities()
& AccessibilityServiceInfo
.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) != 0) {
userState.mIsFilterKeyEventsEnabled = true;
@@ -2124,7 +2124,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
// Starting in JB-MR2 we request an accessibility service to declare
// certain capabilities in its meta-data to allow it to enable the
// corresponding features.
- if ((service.mAccessibilityServiceInfo.getCapabilities()
+ if ((service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION) != 0) {
return true;
}
@@ -3446,22 +3446,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
}
public boolean canRetrieveWindowContentLocked(AbstractAccessibilityServiceConnection service) {
- return (service.mAccessibilityServiceInfo.getCapabilities()
+ return (service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT) != 0;
}
public boolean canControlMagnification(AbstractAccessibilityServiceConnection service) {
- return (service.mAccessibilityServiceInfo.getCapabilities()
+ return (service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION) != 0;
}
public boolean canPerformGestures(AccessibilityServiceConnection service) {
- return (service.mAccessibilityServiceInfo.getCapabilities()
+ return (service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES) != 0;
}
public boolean canCaptureFingerprintGestures(AccessibilityServiceConnection service) {
- return (service.mAccessibilityServiceInfo.getCapabilities()
+ return (service.getCapabilities()
& AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES) != 0;
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index 89bf82d6f065..eb18f06baae0 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -165,7 +165,14 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect
}
}
- public void initializeService() {
+ @Override
+ public AccessibilityServiceInfo getServiceInfo() {
+ // Update crashed data
+ mAccessibilityServiceInfo.crashed = mWasConnectedAndDied;
+ return mAccessibilityServiceInfo;
+ }
+
+ private void initializeService() {
IAccessibilityServiceClient serviceInterface = null;
synchronized (mLock) {
UserState userState = mUserStateWeakReference.get();
diff --git a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
index 5b5d18f4aaf7..9f441978f3aa 100644
--- a/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/MagnificationController.java
@@ -55,7 +55,7 @@ import java.util.Locale;
* magnification region. If a value is out of bounds, it will be adjusted to guarantee these
* constraints.
*/
-class MagnificationController implements Handler.Callback {
+public class MagnificationController implements Handler.Callback {
private static final boolean DEBUG = false;
private static final String LOG_TAG = "MagnificationController";
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
index 0462b1430496..e5c6c6e51430 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java
@@ -16,6 +16,9 @@
package com.android.server.accessibility;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -57,6 +60,7 @@ public class AccessibilityServiceConnectionTest {
static final int SERVICE_ID = 42;
AccessibilityServiceConnection mConnection;
+
@Mock AccessibilityManagerService.UserState mMockUserState;
@Mock Context mMockContext;
@Mock AccessibilityServiceInfo mMockServiceInfo;
@@ -66,7 +70,9 @@ public class AccessibilityServiceConnectionTest {
@Mock WindowManagerInternal mMockWindowManagerInternal;
@Mock GlobalActionPerformer mMockGlobalActionPerformer;
@Mock KeyEventDispatcher mMockKeyEventDispatcher;
+ @Mock MagnificationController mMockMagnificationController;
+ MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
@BeforeClass
public static void oneTimeInitialization() {
@@ -79,12 +85,15 @@ public class AccessibilityServiceConnectionTest {
public void setup() {
MockitoAnnotations.initMocks(this);
when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher);
+ when(mMockSystemSupport.getMagnificationController())
+ .thenReturn(mMockMagnificationController);
+
when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
mMockResolveInfo.serviceInfo = mock(ServiceInfo.class);
mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
- COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, new Handler(), new Object(),
+ COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(),
mMockSecurityPolicy, mMockSystemSupport, mMockWindowManagerInternal,
mMockGlobalActionPerformer);
}
@@ -106,12 +115,30 @@ public class AccessibilityServiceConnectionTest {
@Test
public void bindConnectUnbind_linksAndUnlinksToServiceDeath() throws RemoteException {
IBinder mockBinder = mock(IBinder.class);
- when(mMockUserState.getBindingServicesLocked())
- .thenReturn(new HashSet<>(Arrays.asList(COMPONENT_NAME)));
+ setServiceBinding(COMPONENT_NAME);
mConnection.bindLocked();
mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
verify(mockBinder).linkToDeath(eq(mConnection), anyInt());
mConnection.unbindLocked();
verify(mockBinder).unlinkToDeath(eq(mConnection), anyInt());
}
+
+ @Test
+ public void connectedServiceCrashedAndRestarted_crashReportedInServiceInfo() {
+ IBinder mockBinder = mock(IBinder.class);
+ setServiceBinding(COMPONENT_NAME);
+ mConnection.bindLocked();
+ mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
+ assertFalse(mConnection.getServiceInfo().crashed);
+ mConnection.binderDied();
+ assertTrue(mConnection.getServiceInfo().crashed);
+ mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
+ mHandler.sendAllMessages();
+ assertFalse(mConnection.getServiceInfo().crashed);
+ }
+
+ private void setServiceBinding(ComponentName componentName) {
+ when(mMockUserState.getBindingServicesLocked())
+ .thenReturn(new HashSet<>(Arrays.asList(componentName)));
+ }
}