Merge "Expose if running a11y service has crashed" into pi-dev

am: c863d506cf

Change-Id: I032c524115ca3863d5fe08a843dbe9febce27c76
This commit is contained in:
Phil Weaver
2018-03-20 21:51:12 +00:00
committed by android-build-merger
7 changed files with 79 additions and 16 deletions

View File

@@ -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
@@ -409,6 +409,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.
*/
@@ -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();

View File

@@ -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()}.

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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";

View File

@@ -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)));
}
}