Merge "Expose if running a11y service has crashed" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c863d506cf
@@ -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();
|
||||
|
||||
@@ -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()}.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user