• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 mAccessibilityViewId;
55     private final int mRequestTypes;
56 
57     /**
58      * @param view The view whose requests need preparation. It must be attached to a
59      * window. This object will retain a weak reference to this view, and will unregister itself
60      * from AccessibilityManager if the view is detached from a window. It will not re-register
61      * itself.
62      * @param requestTypes The types of requests that require preparation. Different types may
63      * be ORed together.
64      *
65      * @throws IllegalStateException if the view is not attached to a window.
66      */
AccessibilityRequestPreparer(View view, @RequestTypes int requestTypes)67     public AccessibilityRequestPreparer(View view, @RequestTypes int requestTypes) {
68         if (!view.isAttachedToWindow()) {
69             throw new IllegalStateException("View must be attached to a window");
70         }
71         mViewRef = new WeakReference<>(view);
72         mAccessibilityViewId = view.getAccessibilityViewId();
73         mRequestTypes = requestTypes;
74         view.addOnAttachStateChangeListener(new ViewAttachStateListener());
75     }
76 
77     /**
78      * Callback to allow preparation for filling extra data. Only called back if
79      * REQUEST_TYPE_EXTRA_DATA is requested.
80      *
81      * @param virtualViewId The ID of a virtual child node, if the {@link View} for this preparer
82      * supports virtual descendents, or {@link AccessibilityNodeProvider#HOST_VIEW_ID}
83      * if the request is for the view itself.
84      * @param extraDataKey The extra data key for the request
85      * @param args The arguments for the request
86      * @param preparationFinishedMessage A message that must be sent to its target when preparations
87      * are complete.
88      *
89      * @see View#addExtraDataToAccessibilityNodeInfo(AccessibilityNodeInfo, String, Bundle)
90      * @see View.AccessibilityDelegate#addExtraDataToAccessibilityNodeInfo(
91      * View, AccessibilityNodeInfo, String, Bundle)
92      * @see AccessibilityNodeProvider#addExtraDataToAccessibilityNodeInfo(
93      * int, AccessibilityNodeInfo, String, Bundle)
94      */
onPrepareExtraData(int virtualViewId, String extraDataKey, Bundle args, Message preparationFinishedMessage)95     public abstract void onPrepareExtraData(int virtualViewId, String extraDataKey,
96             Bundle args, Message preparationFinishedMessage);
97 
98     /**
99      * Get the view this object was created with.
100      *
101      * @return The view this object was created with, or {@code null} if the weak reference held
102      * to the view is no longer valid.
103      */
getView()104     public @Nullable View getView() {
105         return mViewRef.get();
106     }
107 
108     private class ViewAttachStateListener implements View.OnAttachStateChangeListener {
109         @Override
onViewAttachedToWindow(View v)110         public void onViewAttachedToWindow(View v) {
111         }
112 
113         @Override
onViewDetachedFromWindow(View v)114         public void onViewDetachedFromWindow(View v) {
115             Context context = v.getContext();
116             if (context != null) {
117                 context.getSystemService(AccessibilityManager.class)
118                         .removeAccessibilityRequestPreparer(AccessibilityRequestPreparer.this);
119             }
120             v.removeOnAttachStateChangeListener(this);
121         }
122     }
123 
getAccessibilityViewId()124     int getAccessibilityViewId() {
125         return mAccessibilityViewId;
126     }
127 }
128