1 /*
2  * Copyright (C) 2010 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.cts.activities;
18 
19 import android.accessibilityservice.cts.R;
20 import android.graphics.Rect;
21 import android.os.Bundle;
22 import android.view.TouchDelegate;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.view.accessibility.AccessibilityEvent;
26 import android.view.accessibility.AccessibilityNodeInfo;
27 import android.widget.BaseAdapter;
28 import android.widget.Button;
29 import android.widget.ListAdapter;
30 import android.widget.ListView;
31 import android.widget.TextView;
32 
33 import java.util.function.Function;
34 import java.util.function.Supplier;
35 
36 /**
37  * This class is an {@link android.app.Activity} used to perform end-to-end
38  * testing of the accessibility feature by interaction with the
39  * UI widgets.
40  */
41 public class AccessibilityEndToEndActivity extends AccessibilityTestActivity {
42     private PackageNameInjector mPackageNameInjector;
43 
44     @Override
onCreate(Bundle savedInstanceState)45     protected void onCreate(Bundle savedInstanceState) {
46         super.onCreate(savedInstanceState);
47         setContentView(R.layout.end_to_end_test);
48 
49         ListAdapter listAdapter = new BaseAdapter() {
50             public View getView(int position, View convertView, ViewGroup parent) {
51                 TextView textView = (TextView) View
52                         .inflate(AccessibilityEndToEndActivity.this, R.layout.list_view_row, null);
53                 textView.setText((String) getItem(position));
54                 return textView;
55             }
56 
57             public long getItemId(int position) {
58                 return position;
59             }
60 
61             public Object getItem(int position) {
62                 if (position == 0) {
63                     return AccessibilityEndToEndActivity.this.getString(R.string.first_list_item);
64                 } else {
65                     return AccessibilityEndToEndActivity.this.getString(R.string.second_list_item);
66                 }
67             }
68 
69             public int getCount() {
70                 return 2;
71             }
72         };
73 
74         ListView listView = (ListView) findViewById(R.id.listview);
75         listView.setAdapter(listAdapter);
76 
77         final int touchableSize = 48;
78         Button button = findViewById(R.id.button);
79         Function<View, Rect> withTouchableAtRight = (v) -> new Rect(
80                 v.getLeft(), 0, v.getRight() + touchableSize, v.getHeight());
81         button.getViewTreeObserver().addOnGlobalLayoutListener(setTouchDelegate(button,
82                 () -> withTouchableAtRight.apply(button))::run);
83 
84         Button delegated = findViewById(R.id.buttonDelegated);
85         Function<View, Rect> withTouchableAsParent = (v) -> new Rect(
86                 0, 0, v.getWidth(), v.getHeight());
87         delegated.getViewTreeObserver().addOnGlobalLayoutListener(setTouchDelegate(delegated,
88                 () -> withTouchableAsParent.apply((View) delegated.getParent()))::run);
89     }
90 
setTouchDelegate(View target, Supplier<Rect> rectSupplier)91     private static Runnable setTouchDelegate(View target, Supplier<Rect> rectSupplier) {
92         return () -> ((View) target.getParent()).setTouchDelegate(
93                 new TouchDelegate(rectSupplier.get(), target));
94     }
95 
setReportedPackageName(String packageName)96     public void setReportedPackageName(String packageName) {
97         if (packageName != null) {
98             mPackageNameInjector = new PackageNameInjector(packageName);
99         } else {
100             mPackageNameInjector = null;
101         }
102         setPackageNameInjector(getWindow().getDecorView(), mPackageNameInjector);
103     }
104 
setPackageNameInjector(View node, PackageNameInjector injector)105     private static void setPackageNameInjector(View node, PackageNameInjector injector) {
106         if (node == null) {
107             return;
108         }
109         node.setAccessibilityDelegate(injector);
110         if (node instanceof ViewGroup) {
111             final ViewGroup viewGroup = (ViewGroup) node;
112             final int childCount = viewGroup.getChildCount();
113             for (int i = 0; i < childCount; i++) {
114                 setPackageNameInjector(viewGroup.getChildAt(i), injector);
115             }
116         }
117     }
118 
119     private static class PackageNameInjector extends View.AccessibilityDelegate {
120         private final String mPackageName;
121 
PackageNameInjector(String packageName)122         PackageNameInjector(String packageName) {
123             mPackageName = packageName;
124         }
125 
126         @Override
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)127         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
128             super.onInitializeAccessibilityEvent(host, event);
129             event.setPackageName(mPackageName);
130         }
131 
132         @Override
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)133         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
134             super.onInitializeAccessibilityNodeInfo(host, info);
135             info.setPackageName(mPackageName);
136         }
137     }
138 }
139