Home | History | Annotate | Download | only in accessibilityservice
      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