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 package com.example.android.autofill.app;
17 
18 import android.app.assist.AssistStructure;
19 import android.app.assist.AssistStructure.ViewNode;
20 import android.app.assist.AssistStructure.WindowNode;
21 import android.os.Bundle;
22 import android.util.Log;
23 import android.view.View;
24 import android.view.ViewStructure.HtmlInfo;
25 import android.view.autofill.AutofillValue;
26 
27 import java.util.Arrays;
28 import java.util.Set;
29 
30 public final class Util {
31 
32     public static final String TAG = "AutofillSample";
33     public static final boolean DEBUG = true;
34     public static final boolean VERBOSE = false;
35     public static final String EXTRA_DATASET_NAME = "dataset_name";
36     public static final String EXTRA_FOR_RESPONSE = "for_response";
37 
bundleToString(StringBuilder builder, Bundle data)38     private static void bundleToString(StringBuilder builder, Bundle data) {
39         final Set<String> keySet = data.keySet();
40         builder.append("[Bundle with ").append(keySet.size()).append(" keys:");
41         for (String key : keySet) {
42             builder.append(' ').append(key).append('=');
43             Object value = data.get(key);
44             if ((value instanceof Bundle)) {
45                 bundleToString(builder, (Bundle) value);
46             } else {
47                 builder.append((value instanceof Object[])
48                         ? Arrays.toString((Object[]) value) : value);
49             }
50         }
51         builder.append(']');
52     }
53 
bundleToString(Bundle data)54     public static String bundleToString(Bundle data) {
55         if (data == null) {
56             return "N/A";
57         }
58         final StringBuilder builder = new StringBuilder();
59         bundleToString(builder, data);
60         return builder.toString();
61     }
62 
getAutofillTypeAsString(int type)63     public static String getAutofillTypeAsString(int type) {
64         switch (type) {
65             case View.AUTOFILL_TYPE_TEXT:
66                 return "TYPE_TEXT";
67             case View.AUTOFILL_TYPE_LIST:
68                 return "TYPE_LIST";
69             case View.AUTOFILL_TYPE_NONE:
70                 return "TYPE_NONE";
71             case View.AUTOFILL_TYPE_TOGGLE:
72                 return "TYPE_TOGGLE";
73             case View.AUTOFILL_TYPE_DATE:
74                 return "TYPE_DATE";
75         }
76         return "UNKNOWN_TYPE";
77     }
78 
getAutofillValueAndTypeAsString(AutofillValue value)79     private static String getAutofillValueAndTypeAsString(AutofillValue value) {
80         if (value == null) return "null";
81 
82         StringBuilder builder = new StringBuilder(value.toString()).append('(');
83         if (value.isText()) {
84             builder.append("isText");
85         } else if (value.isDate()) {
86             builder.append("isDate");
87         } else if (value.isToggle()) {
88             builder.append("isToggle");
89         } else if (value.isList()) {
90             builder.append("isList");
91         }
92         return builder.append(')').toString();
93     }
94 
dumpStructure(AssistStructure structure)95     public static void dumpStructure(AssistStructure structure) {
96         int nodeCount = structure.getWindowNodeCount();
97         Log.v(TAG, "dumpStructure(): component=" + structure.getActivityComponent()
98                 + " numberNodes=" + nodeCount);
99         for (int i = 0; i < nodeCount; i++) {
100             Log.v(TAG, "node #" + i);
101             WindowNode node = structure.getWindowNodeAt(i);
102             dumpNode("  ", node.getRootViewNode());
103         }
104     }
105 
dumpNode(String prefix, ViewNode node)106     private static void dumpNode(String prefix, ViewNode node) {
107         StringBuilder builder = new StringBuilder();
108         builder.append(prefix)
109                 .append("autoFillId: ").append(node.getAutofillId())
110                 .append("\tidEntry: ").append(node.getIdEntry())
111                 .append("\tid: ").append(node.getId())
112                 .append("\tclassName: ").append(node.getClassName())
113                 .append('\n');
114 
115         builder.append(prefix)
116                 .append("focused: ").append(node.isFocused())
117                 .append("\tvisibility").append(node.getVisibility())
118                 .append("\tchecked: ").append(node.isChecked())
119                 .append("\twebDomain: ").append(node.getWebDomain())
120                 .append("\thint: ").append(node.getHint())
121                 .append('\n');
122 
123         HtmlInfo htmlInfo = node.getHtmlInfo();
124 
125         if (htmlInfo != null) {
126             builder.append(prefix)
127                     .append("HTML TAG: ").append(htmlInfo.getTag())
128                     .append(" attrs: ").append(htmlInfo.getAttributes())
129                     .append('\n');
130         }
131 
132         String[] afHints = node.getAutofillHints();
133         CharSequence[] options = node.getAutofillOptions();
134         builder.append(prefix).append("afType: ").append(getAutofillTypeAsString(node.getAutofillType()))
135                 .append("\tafValue:")
136                 .append(getAutofillValueAndTypeAsString(node.getAutofillValue()))
137                 .append("\tafOptions:").append(options == null ? "N/A" : Arrays.toString(options))
138                 .append("\tafHints: ").append(afHints == null ? "N/A" : Arrays.toString(afHints))
139                 .append("\tinputType:").append(node.getInputType())
140                 .append('\n');
141 
142         int numberChildren = node.getChildCount();
143         builder.append(prefix).append("# children: ").append(numberChildren)
144                 .append("\ttext: ").append(node.getText())
145                 .append('\n');
146 
147         Log.v(TAG, builder.toString());
148         final String prefix2 = prefix + "  ";
149         for (int i = 0; i < numberChildren; i++) {
150             Log.v(TAG, prefix + "child #" + i);
151             dumpNode(prefix2, node.getChildAt(i));
152         }
153     }
154 }