1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.accessibilityservice; 18 19 import android.accessibilityservice.AccessibilityService; 20 import android.accessibilityservice.AccessibilityServiceInfo; 21 import android.app.Notification; 22 import android.util.Log; 23 import android.view.accessibility.AccessibilityEvent; 24 import android.view.accessibility.AccessibilityManager; 25 26 import java.util.Timer; 27 import java.util.TimerTask; 28 29 /** 30 * This class text the accessibility framework end to end. 31 * <p> 32 * Note: Since accessibility is provided by {@link AccessibilityService}s we create one, 33 * and it generates an event and an interruption dispatching them through the 34 * {@link AccessibilityManager}. We verify the received result. To trigger the test 35 * go to Settings->Accessibility and select the enable accessibility check and then 36 * select the check for this service (same name as the class). 37 */ 38 public class AccessibilityTestService extends AccessibilityService { 39 40 private static final String LOG_TAG = "AccessibilityTestService"; 41 42 private static final String CLASS_NAME = "foo.bar.baz.Test"; 43 private static final String PACKAGE_NAME = "foo.bar.baz"; 44 private static final String TEXT = "Some stuff"; 45 private static final String BEFORE_TEXT = "Some other stuff"; 46 47 private static final String CONTENT_DESCRIPTION = "Content description"; 48 49 private static final int ITEM_COUNT = 10; 50 private static final int CURRENT_ITEM_INDEX = 1; 51 private static final int INTERRUPT_INVOCATION_TYPE = 0x00000200; 52 53 private static final int FROM_INDEX = 1; 54 private static final int ADDED_COUNT = 2; 55 private static final int REMOVED_COUNT = 1; 56 57 private static final int NOTIFICATION_TIMEOUT_MILLIS = 80; 58 59 private int mReceivedResult; 60 61 private Timer mTimer = new Timer(); 62 63 @Override 64 public void onServiceConnected() { 65 AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 66 info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK; 67 info.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE; 68 info.notificationTimeout = NOTIFICATION_TIMEOUT_MILLIS; 69 info.flags &= AccessibilityServiceInfo.DEFAULT; 70 setServiceInfo(info); 71 72 // we need to wait until the system picks our configuration 73 // otherwise it will not notify us 74 mTimer.schedule(new TimerTask() { 75 @Override 76 public void run() { 77 try { 78 testAccessibilityEventDispatching(); 79 testInterrupt(); 80 } catch (Exception e) { 81 Log.e(LOG_TAG, "Error in testing Accessibility feature", e); 82 } 83 } 84 }, 1000); 85 } 86 87 /** 88 * Check here if the event we received is actually the one we sent. 89 */ 90 @Override 91 public void onAccessibilityEvent(AccessibilityEvent event) { 92 assert(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED == event.getEventType()); 93 assert(event != null); 94 assert(event.getEventTime() > 0); 95 assert(CLASS_NAME.equals(event.getClassName())); 96 assert(PACKAGE_NAME.equals(event.getPackageName())); 97 assert(1 == event.getText().size()); 98 assert(TEXT.equals(event.getText().get(0))); 99 assert(BEFORE_TEXT.equals(event.getBeforeText())); 100 assert(event.isChecked()); 101 assert(CONTENT_DESCRIPTION.equals(event.getContentDescription())); 102 assert(ITEM_COUNT == event.getItemCount()); 103 assert(CURRENT_ITEM_INDEX == event.getCurrentItemIndex()); 104 assert(event.isEnabled()); 105 assert(event.isPassword()); 106 assert(FROM_INDEX == event.getFromIndex()); 107 assert(ADDED_COUNT == event.getAddedCount()); 108 assert(REMOVED_COUNT == event.getRemovedCount()); 109 assert(event.getParcelableData() != null); 110 assert(1 == ((Notification) event.getParcelableData()).icon); 111 112 // set the type of the receved request 113 mReceivedResult = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED; 114 } 115 116 /** 117 * Set a flag that we received the interrupt request. 118 */ 119 @Override 120 public void onInterrupt() { 121 122 // set the type of the receved request 123 mReceivedResult = INTERRUPT_INVOCATION_TYPE; 124 } 125 126 /** 127 * If an {@link AccessibilityEvent} is sent and received correctly. 128 */ 129 public void testAccessibilityEventDispatching() throws Exception { 130 AccessibilityEvent event = 131 AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED); 132 133 assert(event != null); 134 event.setClassName(CLASS_NAME); 135 event.setPackageName(PACKAGE_NAME); 136 event.getText().add(TEXT); 137 event.setBeforeText(BEFORE_TEXT); 138 event.setChecked(true); 139 event.setContentDescription(CONTENT_DESCRIPTION); 140 event.setItemCount(ITEM_COUNT); 141 event.setCurrentItemIndex(CURRENT_ITEM_INDEX); 142 event.setEnabled(true); 143 event.setPassword(true); 144 event.setFromIndex(FROM_INDEX); 145 event.setAddedCount(ADDED_COUNT); 146 event.setRemovedCount(REMOVED_COUNT); 147 event.setParcelableData(new Notification(1, "Foo", 1234)); 148 149 AccessibilityManager.getInstance(this).sendAccessibilityEvent(event); 150 151 assert(mReceivedResult == event.getEventType()); 152 153 Log.i(LOG_TAG, "AccessibilityTestService#testAccessibilityEventDispatching: Success"); 154 } 155 156 /** 157 * If accessibility feedback interruption is triggered and received correctly. 158 */ 159 public void testInterrupt() throws Exception { 160 AccessibilityManager.getInstance(this).interrupt(); 161 162 assert(INTERRUPT_INVOCATION_TYPE == mReceivedResult); 163 164 Log.i(LOG_TAG, "AccessibilityTestService#testInterrupt: Success"); 165 } 166 } 167 168