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 = getResources().getDimensionPixelSize(
78                 R.dimen.button_touchable_width_increment_amount);
79         Button button = findViewById(R.id.button);
80         Function<View, Rect> withTouchableAtRight = (v) -> new Rect(
81                 v.getLeft(), 0, v.getRight() + touchableSize, v.getHeight());
82         button.getViewTreeObserver().addOnGlobalLayoutListener(setTouchDelegate(button,
83                 () -> withTouchableAtRight.apply(button))::run);
84 
85         Button delegated = findViewById(R.id.buttonDelegated);
86         Function<View, Rect> withTouchableAsParent = (v) -> new Rect(
87                 0, 0, v.getWidth(), v.getHeight());
88         delegated.getViewTreeObserver().addOnGlobalLayoutListener(setTouchDelegate(delegated,
89                 () -> withTouchableAsParent.apply((View) delegated.getParent()))::run);
90     }
91 
setTouchDelegate(View target, Supplier<Rect> rectSupplier)92     private static Runnable setTouchDelegate(View target, Supplier<Rect> rectSupplier) {
93         return () -> ((View) target.getParent()).setTouchDelegate(
94                 new TouchDelegate(rectSupplier.get(), target));
95     }
96 
setReportedPackageName(String packageName)97     public void setReportedPackageName(String packageName) {
98         if (packageName != null) {
99             mPackageNameInjector = new PackageNameInjector(packageName);
100         } else {
101             mPackageNameInjector = null;
102         }
103         setPackageNameInjector(getWindow().getDecorView(), mPackageNameInjector);
104     }
105 
setPackageNameInjector(View node, PackageNameInjector injector)106     private static void setPackageNameInjector(View node, PackageNameInjector injector) {
107         if (node == null) {
108             return;
109         }
110         node.setAccessibilityDelegate(injector);
111         if (node instanceof ViewGroup) {
112             final ViewGroup viewGroup = (ViewGroup) node;
113             final int childCount = viewGroup.getChildCount();
114             for (int i = 0; i < childCount; i++) {
115                 setPackageNameInjector(viewGroup.getChildAt(i), injector);
116             }
117         }
118     }
119 
120     private static class PackageNameInjector extends View.AccessibilityDelegate {
121         private final String mPackageName;
122 
PackageNameInjector(String packageName)123         PackageNameInjector(String packageName) {
124             mPackageName = packageName;
125         }
126 
127         @Override
onInitializeAccessibilityEvent(View host, AccessibilityEvent event)128         public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
129             super.onInitializeAccessibilityEvent(host, event);
130             event.setPackageName(mPackageName);
131         }
132 
133         @Override
onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info)134         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
135             super.onInitializeAccessibilityNodeInfo(host, info);
136             info.setPackageName(mPackageName);
137         }
138     }
139 }
140