diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 35276ccd51725..5e6ace785dc30 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -41,6 +41,7 @@ import android.util.Log; import android.view.IWindow; import android.view.View; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IntPair; import java.util.ArrayList; @@ -126,6 +127,8 @@ public final class AccessibilityManager { final Handler mHandler; + final Handler.Callback mCallback; + boolean mIsEnabled; int mRelevantEventTypes = AccessibilityEvent.TYPES_ALL_MASK; @@ -217,12 +220,12 @@ public final class AccessibilityManager { // is now off an exception will be thrown. We want to have the exception // enforcement to guard against apps that fire unnecessary accessibility // events when accessibility is off. - mHandler.obtainMessage(MyHandler.MSG_SET_STATE, state, 0).sendToTarget(); + mHandler.obtainMessage(MyCallback.MSG_SET_STATE, state, 0).sendToTarget(); } @Override public void notifyServicesStateChanged() { - mHandler.obtainMessage(MyHandler.MSG_NOTIFY_SERVICES_STATE_CHANGED).sendToTarget(); + mHandler.obtainMessage(MyCallback.MSG_NOTIFY_SERVICES_STATE_CHANGED).sendToTarget(); } @Override @@ -271,7 +274,8 @@ public final class AccessibilityManager { public AccessibilityManager(Context context, IAccessibilityManager service, int userId) { // Constructor can't be chained because we can't create an instance of an inner class // before calling another constructor. - mHandler = new MyHandler(context.getMainLooper()); + mCallback = new MyCallback(); + mHandler = new Handler(context.getMainLooper(), mCallback); mUserId = userId; synchronized (mLock) { tryConnectToServiceLocked(service); @@ -288,6 +292,7 @@ public final class AccessibilityManager { * @hide */ public AccessibilityManager(Handler handler, IAccessibilityManager service, int userId) { + mCallback = new MyCallback(); mHandler = handler; mUserId = userId; synchronized (mLock) { @@ -302,6 +307,14 @@ public final class AccessibilityManager { return mClient; } + /** + * @hide + */ + @VisibleForTesting + public Handler.Callback getCallback() { + return mCallback; + } + /** * Returns if the accessibility in the system is enabled. * @@ -711,15 +724,15 @@ public final class AccessibilityManager { mIsHighTextContrastEnabled = highTextContrastEnabled; if (wasEnabled != enabled) { - mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED); + mHandler.sendEmptyMessage(MyCallback.MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED); } if (wasTouchExplorationEnabled != touchExplorationEnabled) { - mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_EXPLORATION_STATE_CHANGED); + mHandler.sendEmptyMessage(MyCallback.MSG_NOTIFY_EXPLORATION_STATE_CHANGED); } if (wasHighTextContrastEnabled != highTextContrastEnabled) { - mHandler.sendEmptyMessage(MyHandler.MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED); + mHandler.sendEmptyMessage(MyCallback.MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED); } } @@ -960,19 +973,15 @@ public final class AccessibilityManager { } } - private final class MyHandler extends Handler { + private final class MyCallback implements Handler.Callback { public static final int MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED = 1; public static final int MSG_NOTIFY_EXPLORATION_STATE_CHANGED = 2; public static final int MSG_NOTIFY_HIGH_TEXT_CONTRAST_STATE_CHANGED = 3; public static final int MSG_SET_STATE = 4; public static final int MSG_NOTIFY_SERVICES_STATE_CHANGED = 5; - public MyHandler(Looper looper) { - super(looper, null, false); - } - @Override - public void handleMessage(Message message) { + public boolean handleMessage(Message message) { switch (message.what) { case MSG_NOTIFY_ACCESSIBILITY_STATE_CHANGED: { handleNotifyAccessibilityStateChanged(); @@ -998,6 +1007,7 @@ public final class AccessibilityManager { } } break; } + return true; } } } diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index 6c7f146ed6804..205c8dea18b08 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -52,20 +52,6 @@ - - - - - - - - - - - - diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java deleted file mode 100644 index 340c62405814a..0000000000000 --- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerServiceTest.java +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.accessibilityservice.AccessibilityService; -import android.accessibilityservice.AccessibilityServiceInfo; -import android.content.ComponentName; -import android.content.Context; -import android.content.pm.ServiceInfo; -import android.os.IBinder; -import android.os.Message; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.UserHandle; -import android.provider.Settings; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.IAccessibilityManager; -import android.view.accessibility.IAccessibilityManagerClient; - -import com.android.internal.util.IntPair; - -/** - * This test exercises the - * {@link com.android.server.accessibility.AccessibilityManagerService} by mocking the - * {@link android.view.accessibility.AccessibilityManager} which talks to to the - * service. The service itself is interacting with the platform. Note: Testing - * the service in full isolation would require significant amount of work for - * mocking all system interactions. It would also require a lot of mocking code. - */ -public class AccessibilityManagerServiceTest extends AndroidTestCase { - - /** - * Timeout required for pending Binder calls or event processing to - * complete. - */ - private static final long TIMEOUT_BINDER_CALL = 100; - - /** - * Timeout in which we are waiting for the system to start the mock - * accessibility services. - */ - private static final long TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES = 1000; - - /** - * Timeout used for testing that a service is notified only upon a - * notification timeout. - */ - private static final long TIMEOUT_TEST_NOTIFICATION_TIMEOUT = 300; - - /** - * The interface used to talk to the tested service. - */ - private IAccessibilityManager mManagerService; - - @Override - protected void setUp() throws Exception { - // Reset the state. - ensureOnlyMockServicesEnabled(getContext(), false, false); - } - - @Override - public void setContext(Context context) { - super.setContext(context); - if (MyFirstMockAccessibilityService.sComponentName == null) { - MyFirstMockAccessibilityService.sComponentName = new ComponentName( - context.getPackageName(), MyFirstMockAccessibilityService.class.getName()) - .flattenToShortString(); - } - if (MySecondMockAccessibilityService.sComponentName == null) { - MySecondMockAccessibilityService.sComponentName = new ComponentName( - context.getPackageName(), MySecondMockAccessibilityService.class.getName()) - .flattenToShortString(); - } - } - - /** - * Creates a new instance. - */ - public AccessibilityManagerServiceTest() { - IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE); - mManagerService = IAccessibilityManager.Stub.asInterface(iBinder); - } - - @LargeTest - public void testAddClient_AccessibilityDisabledThenEnabled() throws Exception { - // at least some service must be enabled, otherwise accessibility will always be disabled. - ensureOnlyMockServicesEnabled(mContext, true, false); - - // make sure accessibility is disabled - ensureAccessibilityEnabled(mContext, false); - - // create a client mock instance - MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient(); - - // invoke the method under test - final int stateFlagsDisabled = - IntPair.first(mManagerService.addClient(mockClient, UserHandle.USER_CURRENT)); - boolean enabledAccessibilityDisabled = - (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; - - // check expected result - assertFalse("The client must be disabled since accessibility is disabled.", - enabledAccessibilityDisabled); - - // enable accessibility - ensureAccessibilityEnabled(mContext, true); - - // invoke the method under test - final int stateFlagsEnabled = - IntPair.first(mManagerService.addClient(mockClient, UserHandle.USER_CURRENT)); - boolean enabledAccessibilityEnabled = - (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; - - // check expected result - assertTrue("The client must be enabled since accessibility is enabled.", - enabledAccessibilityEnabled); - } - - @LargeTest - public void testAddClient_AccessibilityEnabledThenDisabled() throws Exception { - // at least some service must be enabled, otherwise accessibility will always be disabled. - ensureOnlyMockServicesEnabled(mContext, true, false); - - // enable accessibility before registering the client - ensureAccessibilityEnabled(mContext, true); - - // create a client mock instance - MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient(); - - // invoke the method under test - final int stateFlagsEnabled = - IntPair.first(mManagerService.addClient(mockClient, UserHandle.USER_CURRENT)); - boolean enabledAccessibilityEnabled = - (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; - - // check expected result - assertTrue("The client must be enabled since accessibility is enabled.", - enabledAccessibilityEnabled); - - // disable accessibility - ensureAccessibilityEnabled(mContext, false); - - // invoke the method under test - final int stateFlagsDisabled = - IntPair.first(mManagerService.addClient(mockClient, UserHandle.USER_CURRENT)); - boolean enabledAccessibilityDisabled = - (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0; - - // check expected result - assertFalse("The client must be disabled since accessibility is disabled.", - enabledAccessibilityDisabled); - } - - @LargeTest - public void testGetAccessibilityServicesList() throws Exception { - boolean firstMockServiceInstalled = false; - boolean secondMockServiceInstalled = false; - - String packageName = getContext().getPackageName(); - String firstMockServiceClassName = MyFirstMockAccessibilityService.class.getName(); - String secondMockServiceClassName = MySecondMockAccessibilityService.class.getName(); - - // look for the two mock services - for (AccessibilityServiceInfo info : mManagerService.getInstalledAccessibilityServiceList( - UserHandle.USER_CURRENT)) { - ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo; - if (packageName.equals(serviceInfo.packageName)) { - if (firstMockServiceClassName.equals(serviceInfo.name)) { - firstMockServiceInstalled = true; - } else if (secondMockServiceClassName.equals(serviceInfo.name)) { - secondMockServiceInstalled = true; - } - } - } - - // check expected result - assertTrue("First mock service must be installed", firstMockServiceInstalled); - assertTrue("Second mock service must be installed", secondMockServiceInstalled); - } - - @LargeTest - public void testSendAccessibilityEvent_OneService_MatchingPackageAndEventType() - throws Exception { - // enable the mock accessibility service - ensureOnlyMockServicesEnabled(mContext, true, false); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the mock service - MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; - service.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // wait for the binder call to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - - // set expectations - service.expectEvent(sentEvent); - service.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(service); - } - - @LargeTest - public void testSendAccessibilityEvent_OneService_NotMatchingPackage() throws Exception { - // enable the mock accessibility service - ensureOnlyMockServicesEnabled(mContext, true, false); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the mock service - MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; - service.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // wait for the binder call to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - sentEvent.setPackageName("no.service.registered.for.this.package"); - - // set expectations - service.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(service); - } - - @LargeTest - public void testSendAccessibilityEvent_OneService_NotMatchingEventType() throws Exception { - // enable the mock accessibility service - ensureOnlyMockServicesEnabled(mContext, true, false); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the mock service - MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; - service.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // wait for the binder call to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - sentEvent.setEventType(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); - - // set expectations - service.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(service); - } - - @LargeTest - public void testSendAccessibilityEvent_OneService_NotificationAfterTimeout() throws Exception { - // enable the mock accessibility service - ensureOnlyMockServicesEnabled(mContext, true, false); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the mock service - MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance; - AccessibilityServiceInfo info = MockAccessibilityService.createDefaultInfo(); - info.notificationTimeout = TIMEOUT_TEST_NOTIFICATION_TIMEOUT; - service.setServiceInfo(info); - - // wait for the binder call to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate the first event to be sent - AccessibilityEvent firstEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(firstEvent); - - // create and populate the second event to be sent - AccessibilityEvent secondEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(secondEvent); - - // set expectations - service.expectEvent(secondEvent); - service.replay(); - - // send the events - mManagerService.sendAccessibilityEvent(firstEvent, UserHandle.USER_CURRENT); - mManagerService.sendAccessibilityEvent(secondEvent, UserHandle.USER_CURRENT); - - // wait for #sendAccessibilityEvent to reach the backing service - Thread.sleep(TIMEOUT_BINDER_CALL); - - try { - service.verify(); - fail("No events must be dispatched before the expiration of the notification timeout."); - } catch (IllegalStateException ise) { - /* expected */ - } - - // wait for the configured notification timeout to expire - Thread.sleep(TIMEOUT_TEST_NOTIFICATION_TIMEOUT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(service); - } - - @LargeTest - public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_DiffFeedback() - throws Exception { - // enable the mock accessibility services - ensureOnlyMockServicesEnabled(mContext, true, true); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the first mock service - MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; - AccessibilityServiceInfo firstInfo = MockAccessibilityService.createDefaultInfo(); - firstInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE; - firstService.setServiceInfo(firstInfo); - - // configure the second mock service - MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; - AccessibilityServiceInfo secondInfo = MockAccessibilityService.createDefaultInfo(); - secondInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_HAPTIC; - secondService.setServiceInfo(secondInfo); - - // wait for the binder calls to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - - // set expectations for the first mock service - firstService.expectEvent(sentEvent); - firstService.replay(); - - // set expectations for the second mock service - secondService.expectEvent(sentEvent); - secondService.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(firstService); - assertMockServiceVerifiedWithinTimeout(secondService); - } - - @LargeTest - public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType() - throws Exception { - // enable the mock accessibility services - ensureOnlyMockServicesEnabled(mContext, true, true); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the first mock service - MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; - firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // configure the second mock service - MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; - secondService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // wait for the binder calls to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - - // set expectations for the first mock service - firstService.expectEvent(sentEvent); - firstService.replay(); - - // set expectations for the second mock service - secondService.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(firstService); - assertMockServiceVerifiedWithinTimeout(secondService); - } - - @LargeTest - public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_OneDefault() - throws Exception { - // enable the mock accessibility services - ensureOnlyMockServicesEnabled(mContext, true, true); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the first mock service - MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; - AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo(); - firstInfo.flags = AccessibilityServiceInfo.DEFAULT; - firstService.setServiceInfo(firstInfo); - - // configure the second mock service - MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; - secondService.setServiceInfo(MySecondMockAccessibilityService.createDefaultInfo()); - - // wait for the binder calls to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - - // set expectations for the first mock service - firstService.replay(); - - // set expectations for the second mock service - secondService.expectEvent(sentEvent); - secondService.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(firstService); - assertMockServiceVerifiedWithinTimeout(secondService); - } - - @LargeTest - public void testSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_TwoDefault() - throws Exception { - // enable the mock accessibility services - ensureOnlyMockServicesEnabled(mContext, true, true); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the first mock service - MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; - AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo(); - firstInfo.flags = AccessibilityServiceInfo.DEFAULT; - firstService.setServiceInfo(firstInfo); - - // configure the second mock service - MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; - AccessibilityServiceInfo secondInfo = MyFirstMockAccessibilityService.createDefaultInfo(); - secondInfo.flags = AccessibilityServiceInfo.DEFAULT; - secondService.setServiceInfo(firstInfo); - - // wait for the binder calls to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // create and populate an event to be sent - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - fullyPopulateDefaultAccessibilityEvent(sentEvent); - - // set expectations for the first mock service - firstService.expectEvent(sentEvent); - firstService.replay(); - - // set expectations for the second mock service - secondService.replay(); - - // send the event - mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(firstService); - assertMockServiceVerifiedWithinTimeout(secondService); - } - - @LargeTest - public void testInterrupt() throws Exception { - // enable the mock accessibility services - ensureOnlyMockServicesEnabled(mContext, true, true); - - // set the accessibility setting value - ensureAccessibilityEnabled(mContext, true); - - // configure the first mock service - MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance; - firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // configure the second mock service - MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance; - secondService.setServiceInfo(MockAccessibilityService.createDefaultInfo()); - - // wait for the binder calls to #setService to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // set expectations for the first mock service - firstService.expectInterrupt(); - firstService.replay(); - - // set expectations for the second mock service - secondService.expectInterrupt(); - secondService.replay(); - - // call the method under test - mManagerService.interrupt(UserHandle.USER_CURRENT); - - // verify if all expected methods have been called - assertMockServiceVerifiedWithinTimeout(firstService); - assertMockServiceVerifiedWithinTimeout(secondService); - } - - /** - * Fully populates the {@link AccessibilityEvent} to marshal. - * - * @param sentEvent The event to populate. - */ - private void fullyPopulateDefaultAccessibilityEvent(AccessibilityEvent sentEvent) { - sentEvent.setAddedCount(1); - sentEvent.setBeforeText("BeforeText"); - sentEvent.setChecked(true); - sentEvent.setClassName("foo.bar.baz.Class"); - sentEvent.setContentDescription("ContentDescription"); - sentEvent.setCurrentItemIndex(1); - sentEvent.setEnabled(true); - sentEvent.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT); - sentEvent.setEventTime(1000); - sentEvent.setFromIndex(1); - sentEvent.setFullScreen(true); - sentEvent.setItemCount(1); - sentEvent.setPackageName("foo.bar.baz"); - sentEvent.setParcelableData(Message.obtain(null, 1, null)); - sentEvent.setPassword(true); - sentEvent.setRemovedCount(1); - } - - /** - * This class is a mock {@link IAccessibilityManagerClient}. - */ - public class MyMockAccessibilityManagerClient extends IAccessibilityManagerClient.Stub { - int mState; - - public void setState(int state) { - mState = state; - } - - public void notifyServicesStateChanged() {} - - public void setRelevantEventTypes(int eventTypes) {} - - public void setTouchExplorationEnabled(boolean enabled) {} - } - - /** - * Ensures accessibility is in a given state by writing the state to the - * settings and waiting until the accessibility manager service pick it up. - * - * @param context A context handle to access the settings. - * @param enabled The accessibility state to write to the settings. - * @throws Exception If any error occurs. - */ - private void ensureAccessibilityEnabled(Context context, boolean enabled) throws Exception { - boolean isEnabled = Settings.Secure.getInt(context.getContentResolver(), - Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1; - - if (isEnabled == enabled) { - return; - } - - Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED, - enabled ? 1 : 0); - - // wait the accessibility manager service to pick the change up - Thread.sleep(TIMEOUT_BINDER_CALL); - } - - /** - * Ensures the only {@link MockAccessibilityService}s with given component - * names are enabled by writing to the system settings and waiting until the - * accessibility manager service picks that up or the - * {@link #TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES} is exceeded. - * - * @param context A context handle to access the settings. - * @param firstMockServiceEnabled If the first mock accessibility service is enabled. - * @param secondMockServiceEnabled If the second mock accessibility service is enabled. - * @throws IllegalStateException If some of the requested for enabling mock services - * is not properly started. - * @throws Exception Exception If any error occurs. - */ - private void ensureOnlyMockServicesEnabled(Context context, boolean firstMockServiceEnabled, - boolean secondMockServiceEnabled) throws Exception { - String enabledServices = Settings.Secure.getString(context.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES); - - StringBuilder servicesToEnable = new StringBuilder(); - if (firstMockServiceEnabled) { - servicesToEnable.append(MyFirstMockAccessibilityService.sComponentName).append(":"); - } - if (secondMockServiceEnabled) { - servicesToEnable.append(MySecondMockAccessibilityService.sComponentName).append(":"); - } - - Settings.Secure.putString(context.getContentResolver(), - Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, servicesToEnable.toString()); - - // Optimization. If things will not change, we don't have to do anything. - if (servicesToEnable.equals(enabledServices)) { - return; - } - - // we have enabled the services of interest and need to wait until they - // are instantiated and started (if needed) and the system binds to them - boolean firstMockServiceOK = false; - boolean secondMockServiceOK = false; - long start = SystemClock.uptimeMillis(); - long pollingInterval = TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES / 6; - - while (SystemClock.uptimeMillis() - start < TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES) { - firstMockServiceOK = !firstMockServiceEnabled - || (MyFirstMockAccessibilityService.sInstance != null - && MyFirstMockAccessibilityService.sInstance.isSystemBoundAsClient()); - - secondMockServiceOK = !secondMockServiceEnabled - || (MySecondMockAccessibilityService.sInstance != null - && MySecondMockAccessibilityService.sInstance.isSystemBoundAsClient()); - - if (firstMockServiceOK && secondMockServiceOK) { - return; - } - - Thread.sleep(pollingInterval); - } - - StringBuilder message = new StringBuilder(); - message.append("Mock accessibility services not started or system not bound as a client: "); - if (!firstMockServiceOK) { - message.append(MyFirstMockAccessibilityService.sComponentName); - message.append(" "); - } - if (!secondMockServiceOK) { - message.append(MySecondMockAccessibilityService.sComponentName); - } - throw new IllegalStateException(message.toString()); - } - - /** - * Asserts the the mock accessibility service has been successfully verified - * (which is it has received the expected method calls with expected - * arguments) within the {@link #TIMEOUT_BINDER_CALL}. The verified state is - * checked by polling upon small intervals. - * - * @param service The service to verify. - * @throws Exception If the verification has failed with exception after the - * {@link #TIMEOUT_BINDER_CALL}. - */ - private void assertMockServiceVerifiedWithinTimeout(MockAccessibilityService service) - throws Exception { - Exception lastVerifyException = null; - long beginTime = SystemClock.uptimeMillis(); - long pollTimeout = TIMEOUT_BINDER_CALL / 5; - - // poll until the timeout has elapsed - while (SystemClock.uptimeMillis() - beginTime < TIMEOUT_BINDER_CALL) { - // sleep first since immediate call will always fail - try { - Thread.sleep(pollTimeout); - } catch (InterruptedException ie) { - /* ignore */ - } - // poll for verification and if this fails save the exception and - // keep polling - try { - service.verify(); - // reset so it does not accept more events - service.reset(); - return; - } catch (Exception e) { - lastVerifyException = e; - } - } - - // reset, we have already failed - service.reset(); - - // always not null - throw lastVerifyException; - } - - /** - * This class is the first mock {@link AccessibilityService}. - */ - public static class MyFirstMockAccessibilityService extends MockAccessibilityService { - - /** - * The service {@link ComponentName} flattened as a string. - */ - static String sComponentName; - - /** - * Handle to the service instance. - */ - static MyFirstMockAccessibilityService sInstance; - - /** - * Creates a new instance. - */ - public MyFirstMockAccessibilityService() { - sInstance = this; - } - } - - /** - * This class is the first mock {@link AccessibilityService}. - */ - public static class MySecondMockAccessibilityService extends MockAccessibilityService { - - /** - * The service {@link ComponentName} flattened as a string. - */ - static String sComponentName; - - /** - * Handle to the service instance. - */ - static MySecondMockAccessibilityService sInstance; - - /** - * Creates a new instance. - */ - public MySecondMockAccessibilityService() { - sInstance = this; - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java b/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java deleted file mode 100644 index e1c5cee752e15..0000000000000 --- a/services/tests/servicestests/src/com/android/server/MockAccessibilityService.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server; - -import android.accessibilityservice.AccessibilityService; -import android.accessibilityservice.AccessibilityServiceInfo; -import android.content.Intent; -import android.os.Message; -import android.view.accessibility.AccessibilityEvent; - -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Queue; - -import junit.framework.TestCase; - -/** - * This is the base class for mock {@link AccessibilityService}s. - */ -public abstract class MockAccessibilityService extends AccessibilityService { - - /** - * The event this service expects to receive. - */ - private final Queue mExpectedEvents = new LinkedList(); - - /** - * Interruption call this service expects to receive. - */ - private boolean mExpectedInterrupt; - - /** - * Flag if the mock is currently replaying. - */ - private boolean mReplaying; - - /** - * Flag if the system is bound as a client to this service. - */ - private boolean mIsSystemBoundAsClient; - - /** - * Creates an {@link AccessibilityServiceInfo} populated with default - * values. - * - * @return The default info. - */ - public static AccessibilityServiceInfo createDefaultInfo() { - AccessibilityServiceInfo defaultInfo = new AccessibilityServiceInfo(); - defaultInfo.eventTypes = AccessibilityEvent.TYPE_ANNOUNCEMENT; - defaultInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE; - defaultInfo.flags = 0; - defaultInfo.notificationTimeout = 0; - defaultInfo.packageNames = new String[] { - "foo.bar.baz" - }; - - return defaultInfo; - } - - /** - * Starts replaying the mock. - */ - public void replay() { - mReplaying = true; - } - - /** - * Verifies if all expected service methods have been called. - */ - public void verify() { - if (!mReplaying) { - throw new IllegalStateException("Did you forget to call replay()"); - } - - if (mExpectedInterrupt) { - throw new IllegalStateException("Expected call to #interrupt() not received"); - } - if (!mExpectedEvents.isEmpty()) { - throw new IllegalStateException("Expected a call to onAccessibilityEvent() for " - + "events \"" + mExpectedEvents + "\" not received"); - } - } - - /** - * Resets this instance so it can be reused. - */ - public void reset() { - mExpectedEvents.clear(); - mExpectedInterrupt = false; - mReplaying = false; - } - - /** - * Sets an expected call to - * {@link #onAccessibilityEvent(AccessibilityEvent)} with given event as - * argument. - * - * @param expectedEvent The expected event argument. - */ - public void expectEvent(AccessibilityEvent expectedEvent) { - mExpectedEvents.add(expectedEvent); - } - - /** - * Sets an expected call of {@link #onInterrupt()}. - */ - public void expectInterrupt() { - mExpectedInterrupt = true; - } - - @Override - public void onAccessibilityEvent(AccessibilityEvent receivedEvent) { - if (!mReplaying) { - return; - } - - if (mExpectedEvents.isEmpty()) { - throw new IllegalStateException("Unexpected event: " + receivedEvent); - } - - AccessibilityEvent expectedEvent = mExpectedEvents.poll(); - assertEqualsAccessiblityEvent(expectedEvent, receivedEvent); - } - - @Override - public void onInterrupt() { - if (!mReplaying) { - return; - } - - if (!mExpectedInterrupt) { - throw new IllegalStateException("Unexpected call to onInterrupt()"); - } - - mExpectedInterrupt = false; - } - - @Override - protected void onServiceConnected() { - mIsSystemBoundAsClient = true; - } - - @Override - public boolean onUnbind(Intent intent) { - mIsSystemBoundAsClient = false; - return false; - } - - /** - * Returns if the system is bound as client to this service. - * - * @return True if the system is bound, false otherwise. - */ - public boolean isSystemBoundAsClient() { - return mIsSystemBoundAsClient; - } - - /** - * Compares all properties of the expectedEvent and the - * receviedEvent to verify that the received event is the one - * that is expected. - */ - private void assertEqualsAccessiblityEvent(AccessibilityEvent expectedEvent, - AccessibilityEvent receivedEvent) { - TestCase.assertEquals("addedCount has incorrect value", expectedEvent.getAddedCount(), - receivedEvent.getAddedCount()); - TestCase.assertEquals("beforeText has incorrect value", expectedEvent.getBeforeText(), - receivedEvent.getBeforeText()); - TestCase.assertEquals("checked has incorrect value", expectedEvent.isChecked(), - receivedEvent.isChecked()); - TestCase.assertEquals("className has incorrect value", expectedEvent.getClassName(), - receivedEvent.getClassName()); - TestCase.assertEquals("contentDescription has incorrect value", expectedEvent - .getContentDescription(), receivedEvent.getContentDescription()); - TestCase.assertEquals("currentItemIndex has incorrect value", expectedEvent - .getCurrentItemIndex(), receivedEvent.getCurrentItemIndex()); - TestCase.assertEquals("enabled has incorrect value", expectedEvent.isEnabled(), - receivedEvent.isEnabled()); - TestCase.assertEquals("eventType has incorrect value", expectedEvent.getEventType(), - receivedEvent.getEventType()); - TestCase.assertEquals("fromIndex has incorrect value", expectedEvent.getFromIndex(), - receivedEvent.getFromIndex()); - TestCase.assertEquals("fullScreen has incorrect value", expectedEvent.isFullScreen(), - receivedEvent.isFullScreen()); - TestCase.assertEquals("itemCount has incorrect value", expectedEvent.getItemCount(), - receivedEvent.getItemCount()); - assertEqualsNotificationAsParcelableData(expectedEvent, receivedEvent); - TestCase.assertEquals("password has incorrect value", expectedEvent.isPassword(), - receivedEvent.isPassword()); - TestCase.assertEquals("removedCount has incorrect value", expectedEvent.getRemovedCount(), - receivedEvent.getRemovedCount()); - assertEqualsText(expectedEvent, receivedEvent); - } - - /** - * Compares the {@link android.os.Parcelable} data of the - * expectedEvent and receivedEvent to verify that - * the received event is the one that is expected. - */ - private void assertEqualsNotificationAsParcelableData(AccessibilityEvent expectedEvent, - AccessibilityEvent receivedEvent) { - String message = "parcelableData has incorrect value"; - Message expectedMessage = (Message) expectedEvent.getParcelableData(); - Message receivedMessage = (Message) receivedEvent.getParcelableData(); - - if (expectedMessage == null) { - if (receivedMessage == null) { - return; - } - } - - TestCase.assertNotNull(message, receivedMessage); - - // we do a very simple sanity check since we do not test Message - TestCase.assertEquals(message, expectedMessage.what, receivedMessage.what); - } - - /** - * Compares the text of the expectedEvent and - * receivedEvent by comparing the string representation of the - * corresponding {@link CharSequence}s. - */ - private void assertEqualsText(AccessibilityEvent expectedEvent, - AccessibilityEvent receivedEvent) { - String message = "text has incorrect value"; - List expectedText = expectedEvent.getText(); - List receivedText = receivedEvent.getText(); - - TestCase.assertEquals(message, expectedText.size(), receivedText.size()); - - Iterator expectedTextIterator = expectedText.iterator(); - Iterator receivedTextIterator = receivedText.iterator(); - - for (int i = 0; i < expectedText.size(); i++) { - // compare the string representation - TestCase.assertEquals(message, expectedTextIterator.next().toString(), - receivedTextIterator.next().toString()); - } - } -} diff --git a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java similarity index 57% rename from services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java rename to services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java index 92617716e28d8..5d09e31a3dc72 100644 --- a/services/tests/servicestests/src/com/android/server/AccessibilityManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerTest.java @@ -14,18 +14,24 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.accessibility; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertSame; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.accessibilityservice.AccessibilityServiceInfo; +import android.app.Instrumentation; +import android.os.Looper; import android.os.UserHandle; -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.MediumTest; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManager; @@ -33,6 +39,10 @@ import android.view.accessibility.IAccessibilityManagerClient; import com.android.internal.util.IntPair; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -40,44 +50,48 @@ import java.util.ArrayList; import java.util.List; /** - * Tests for the AccessibilityManager which mocking the backing service. + * Tests for the AccessibilityManager by mocking the backing service. */ -public class AccessibilityManagerTest extends AndroidTestCase { +@RunWith(AndroidJUnit4.class) +public class AccessibilityManagerTest { + private static final boolean WITH_A11Y_ENABLED = true; + private static final boolean WITH_A11Y_DISABLED = false; - /** - * Timeout required for pending Binder calls or event processing to - * complete. - */ - public static final long TIMEOUT_BINDER_CALL = 50; + @Mock private IAccessibilityManager mMockService; + private MessageCapturingHandler mHandler; + private Instrumentation mInstrumentation; - @Mock - private IAccessibilityManager mMockService; + @BeforeClass + public static void oneTimeInitialization() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + } - @Override + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mHandler = new MessageCapturingHandler(null); + mInstrumentation = InstrumentationRegistry.getInstrumentation(); } private AccessibilityManager createManager(boolean enabled) throws Exception { - if (enabled) { - when(mMockService.addClient(any(IAccessibilityManagerClient.class), anyInt())) - .thenReturn( - IntPair.of(AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED, - AccessibilityEvent.TYPES_ALL_MASK)); - } else { - when(mMockService.addClient(any(IAccessibilityManagerClient.class), anyInt())) - .thenReturn(IntPair.of(0, AccessibilityEvent.TYPES_ALL_MASK)); - } + long serviceReturnValue = IntPair.of( + (enabled) ? AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED : 0, + AccessibilityEvent.TYPES_ALL_MASK); + when(mMockService.addClient(any(IAccessibilityManagerClient.class), anyInt())) + .thenReturn(serviceReturnValue); AccessibilityManager manager = - new AccessibilityManager(mContext, mMockService, UserHandle.USER_CURRENT); + new AccessibilityManager(mHandler, mMockService, UserHandle.USER_CURRENT); verify(mMockService).addClient(any(IAccessibilityManagerClient.class), anyInt()); - + mHandler.setCallback(manager.getCallback()); + mHandler.sendAllMessages(); return manager; } - @MediumTest + @Test public void testGetAccessibilityServiceList() throws Exception { // create a list of installed accessibility services the mock service returns List expectedServices = new ArrayList<>(); @@ -99,59 +113,50 @@ public class AccessibilityManagerTest extends AndroidTestCase { assertEquals("All expected services must be returned", expectedServices, receivedServices); } - @MediumTest + @Test public void testInterrupt() throws Exception { - AccessibilityManager manager = createManager(true); + AccessibilityManager manager = createManager(WITH_A11Y_ENABLED); manager.interrupt(); verify(mMockService).interrupt(UserHandle.USER_CURRENT); } - @LargeTest + @Test public void testIsEnabled() throws Exception { - // invoke the method under test - AccessibilityManager manager = createManager(true); - boolean isEnabledServiceEnabled = manager.isEnabled(); + // Create manager with a11y enabled + AccessibilityManager manager = createManager(WITH_A11Y_ENABLED); + assertTrue("Must be enabled since the mock service is enabled", manager.isEnabled()); - // check expected result - assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled); - - // disable accessibility + // Disable accessibility manager.getClient().setState(0); - - // wait for the asynchronous IBinder call to complete - Thread.sleep(TIMEOUT_BINDER_CALL); - - // invoke the method under test - boolean isEnabledServcieDisabled = manager.isEnabled(); - - // check expected result - assertFalse("Must be disabled since the mock service is disabled", - isEnabledServcieDisabled); + mHandler.sendAllMessages(); + assertFalse("Must be disabled since the mock service is disabled", manager.isEnabled()); } - @MediumTest + @Test public void testSendAccessibilityEvent_AccessibilityEnabled() throws Exception { - AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); + AccessibilityEvent sentEvent = AccessibilityEvent.obtain( + AccessibilityEvent.TYPE_ANNOUNCEMENT); - AccessibilityManager manager = createManager(true); + AccessibilityManager manager = createManager(WITH_A11Y_ENABLED); manager.sendAccessibilityEvent(sentEvent); assertSame("The event should be recycled.", sentEvent, AccessibilityEvent.obtain()); } - @MediumTest + @Test public void testSendAccessibilityEvent_AccessibilityDisabled() throws Exception { AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); - AccessibilityManager manager = createManager(false /* disabled */); - - try { - manager.sendAccessibilityEvent(sentEvent); - fail("No accessibility events are sent if accessibility is disabled"); - } catch (IllegalStateException ise) { - // check expected result - assertEquals("Accessibility off. Did you forget to check that?", ise.getMessage()); - } + AccessibilityManager manager = createManager(WITH_A11Y_DISABLED); + mInstrumentation.runOnMainSync(() -> { + try { + manager.sendAccessibilityEvent(sentEvent); + fail("No accessibility events are sent if accessibility is disabled"); + } catch (IllegalStateException ise) { + // check expected result + assertEquals("Accessibility off. Did you forget to check that?", ise.getMessage()); + } + }); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java index d44c1ca0c0ef9..5887215257e30 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationControllerTest.java @@ -20,11 +20,12 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertFalse; -import static org.mockito.Matchers.anyInt; +import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -48,6 +49,7 @@ import android.view.WindowManagerInternal; import android.view.WindowManagerInternal.MagnificationCallbacks; import com.android.internal.R; + import org.hamcrest.CoreMatchers; import org.hamcrest.Description; import org.hamcrest.TypeSafeMatcher; @@ -471,9 +473,10 @@ public class MagnificationControllerTest { public void testResetIfNeeded_doesWhatItSays() { mMagnificationController.register(); zoomIn2xToMiddle(); + reset(mMockAms); assertTrue(mMagnificationController.resetIfNeeded(false)); verify(mMockAms).notifyMagnificationChanged( - eq(INITIAL_MAGNIFICATION_REGION), eq(1.0f), anyInt(), anyInt()); + eq(INITIAL_MAGNIFICATION_REGION), eq(1.0f), anyFloat(), anyFloat()); assertFalse(mMagnificationController.isMagnifying()); assertFalse(mMagnificationController.resetIfNeeded(false)); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java b/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java index 003f7abf6b002..0dba35f2a164e 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MessageCapturingHandler.java @@ -42,6 +42,10 @@ public class MessageCapturingHandler extends Handler { return super.sendMessageAtTime(message, uptimeMillis); } + public void setCallback(Handler.Callback callback) { + mCallback = callback; + } + public void sendOneMessage() { Message message = timedMessages.remove(0).first; removeMessages(message.what, message.obj);