Home | History | Annotate | Download | only in accessibility
      1 /*
      2  * Copyright (C) 2017 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.view.accessibility;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.Nullable;
     21 import android.content.Context;
     22 import android.os.Bundle;
     23 import android.os.Message;
     24 import android.view.View;
     25 
     26 import java.lang.annotation.Retention;
     27 import java.lang.annotation.RetentionPolicy;
     28 import java.lang.ref.WeakReference;
     29 
     30 /**
     31  * Object responsible to ensuring that a {@link View} is prepared to meet a synchronous request for
     32  * accessibility data.
     33  * <p>
     34  * Because accessibility requests arrive to {@link View}s synchronously on the UI thread, a View
     35  * that requires information from other processes can struggle to meet those requests. Registering
     36  * an instance of this class with {@link AccessibilityManager} allows a View to be notified when
     37  * a request is about to be made, and to asynchronously inform the accessibility system when it is
     38  * ready to meet the request.
     39  * <p>
     40  * <strong>Note:</strong> This class should only be needed in exceptional situations where a
     41  * {@link View} cannot otherwise synchronously meet the request for accessibility data.
     42  */
     43 public abstract class AccessibilityRequestPreparer {
     44     public static final int REQUEST_TYPE_EXTRA_DATA = 0x00000001;
     45 
     46     /** @hide */
     47     @IntDef(flag = true, prefix = { "REQUEST_TYPE_" }, value = {
     48             REQUEST_TYPE_EXTRA_DATA
     49     })
     50     @Retention(RetentionPolicy.SOURCE)
     51     public @interface RequestTypes {}
     52 
     53     private final WeakReference<View> mViewRef;
     54     private final int mRequestTypes;
     55 
     56     /**
     57      * @param view The view whose requests need preparation. It must be attached to a
     58      * window. This object will retain a weak reference to this view, and will unregister itself
     59      * from AccessibilityManager if the view is detached from a window. It will not re-register
     60      * itself.
     61      * @param requestTypes The types of requests that require preparation. Different types may
     62      * be ORed together.
     63      *
     64      * @throws IllegalStateException if the view is not attached to a window.
     65      */
     66     public AccessibilityRequestPreparer(View view, @RequestTypes int requestTypes) {
     67         if (!view.isAttachedToWindow()) {
     68             throw new IllegalStateException("View must be attached to a window");
     69         }
     70         mViewRef = new WeakReference<>(view);
     71         mRequestTypes = requestTypes;
     72         view.addOnAttachStateChangeListener(new ViewAttachStateListener());
     73     }
     74 
     75     /**
     76      * Callback to allow preparation for filling extra data. Only called back if
     77      * REQUEST_TYPE_EXTRA_DATA is requested.
     78      *
     79      * @param virtualViewId The ID of a virtual child node, if the {@link View} for this preparer
     80      * supports virtual descendents, or {@link AccessibilityNodeProvider#HOST_VIEW_ID}
     81      * if the request is for the view itself.
     82      * @param extraDataKey The extra data key for the request
     83      * @param args The arguments for the request
     84      * @param preparationFinishedMessage A message that must be sent to its target when preparations
     85      * are complete.
     86      *
     87      * @see View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
     88      * @see AccessibilityDelegate#addExtraDataToAccessibilityNodeInfo(View, AccessibilityNodeInfo,
     89      * String, Bundle)
     90      * @see AccessibilityNodeProvider#addExtraDataToAccessibilityNodeInfo(
     91      * int, AccessibilityNodeInfo, String, Bundle)
     92      */
     93     public abstract void onPrepareExtraData(int virtualViewId, String extraDataKey,
     94             Bundle args, Message preparationFinishedMessage);
     95 
     96     /**
     97      * Get the view this object was created with.
     98      *
     99      * @return The view this object was created with, or {@code null} if the weak reference held
    100      * to the view is no longer valid.
    101      */
    102     public @Nullable View getView() {
    103         return mViewRef.get();
    104     }
    105 
    106     private class ViewAttachStateListener implements View.OnAttachStateChangeListener {
    107         @Override
    108         public void onViewAttachedToWindow(View v) {
    109         }
    110 
    111         @Override
    112         public void onViewDetachedFromWindow(View v) {
    113             Context context = v.getContext();
    114             if (context != null) {
    115                 context.getSystemService(AccessibilityManager.class)
    116                         .removeAccessibilityRequestPreparer(AccessibilityRequestPreparer.this);
    117             }
    118             v.removeOnAttachStateChangeListener(this);
    119         }
    120     }
    121 }
    122