1 /* 2 * Copyright (C) 2018 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 androidx.constraintlayout.motion.widget; 18 19 import android.annotation.SuppressLint; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.util.Log; 23 import android.view.MotionEvent; 24 import android.view.View; 25 import android.view.ViewGroup; 26 27 import java.lang.reflect.Field; 28 import java.nio.CharBuffer; 29 30 // @TODO: add description 31 32 /** 33 * Utilities useful for debugging 34 * 35 */ 36 @SuppressLint("LogConditional") 37 public class Debug { 38 39 /** 40 * This logs n elements in the stack 41 * 42 * @param tag 43 * @param msg 44 * @param n 45 * 46 */ logStack(String tag, String msg, int n)47 public static void logStack(String tag, String msg, int n) { 48 StackTraceElement[] st = new Throwable().getStackTrace(); 49 String s = " "; 50 n = Math.min(n, st.length - 1); 51 for (int i = 1; i <= n; i++) { 52 @SuppressWarnings("unused") StackTraceElement ste = st[i]; 53 String stack = ".(" + st[i].getFileName() + ":" + st[i].getLineNumber() 54 + ") " + st[i].getMethodName(); 55 s += " "; 56 Log.v(tag, msg + s + stack + s); 57 } 58 } 59 60 /** 61 * This logs n elements in the stack 62 * 63 * @param msg 64 * @param n 65 * 66 */ printStack(String msg, int n)67 public static void printStack(String msg, int n) { 68 StackTraceElement[] st = new Throwable().getStackTrace(); 69 String s = " "; 70 n = Math.min(n, st.length - 1); 71 for (int i = 1; i <= n; i++) { 72 @SuppressWarnings("unused") StackTraceElement ste = st[i]; 73 String stack = ".(" + st[i].getFileName() + ":" + st[i].getLineNumber() + ") "; 74 s += " "; 75 System.out.println(msg + s + stack + s); 76 } 77 } 78 79 /** 80 * This provides return the name of a view 81 * 82 * @param view 83 * @return name of view 84 * 85 */ getName(View view)86 public static String getName(View view) { 87 try { 88 Context context = view.getContext(); 89 return context.getResources().getResourceEntryName(view.getId()); 90 } catch (Exception ex) { 91 return "UNKNOWN"; 92 } 93 } 94 95 // @TODO: add description 96 97 /** 98 * @param obj 99 */ dumpPoc(Object obj)100 public static void dumpPoc(Object obj) { 101 StackTraceElement s = new Throwable().getStackTrace()[1]; 102 String loc = ".(" + s.getFileName() + ":" + s.getLineNumber() + ")"; 103 Class c = obj.getClass(); 104 System.out.println(loc + "------------- " + c.getName() + " --------------------"); 105 Field[] declaredFields = c.getFields(); 106 for (int i = 0; i < declaredFields.length; i++) { 107 Field declaredField = declaredFields[i]; 108 109 try { 110 Object value = declaredField.get(obj); 111 if (!declaredField.getName().startsWith("layout_constraint")) { 112 continue; 113 } 114 if (value instanceof Integer && value.toString().equals("-1")) { 115 continue; 116 } 117 if (value instanceof Integer && value.toString().equals("0")) { 118 continue; 119 } 120 if (value instanceof Float && value.toString().equals("1.0")) { 121 continue; 122 } 123 if (value instanceof Float && value.toString().equals("0.5")) { 124 continue; 125 } 126 System.out.println(loc + " " + declaredField.getName() + " " + value); 127 } catch (IllegalAccessException e) { 128 129 } 130 131 } 132 System.out.println(loc + "------------- " + c.getSimpleName() + " --------------------"); 133 134 } 135 136 /** 137 * This returns the name of a view given its id 138 * 139 * @param context 140 * @param id 141 * @return name of view 142 * 143 */ getName(Context context, int id)144 public static String getName(Context context, int id) { 145 try { 146 if (id != -1) { 147 return context.getResources().getResourceEntryName(id); 148 } else { 149 return "UNKNOWN"; 150 } 151 } catch (Exception ex) { 152 return "?" + id; 153 } 154 } 155 156 /** 157 * This returns the name of a view given its id 158 * 159 * @param context 160 * @param id 161 * @return name of view 162 * 163 */ getName(Context context, int[] id)164 public static String getName(Context context, int[] id) { 165 try { 166 String str = id.length + "["; 167 for (int i = 0; i < id.length; i++) { 168 str += (i == 0) ? "" : " "; 169 String tmp = null; 170 try { 171 tmp = context.getResources().getResourceEntryName(id[i]); 172 } catch (Resources.NotFoundException e) { 173 tmp = "? " + id[i] + " "; 174 } 175 176 str += tmp; 177 178 } 179 return str + "]"; 180 } catch (Exception ex) { 181 Log.v("DEBUG", ex.toString()); 182 return "UNKNOWN"; 183 } 184 } 185 186 /** 187 * convert an id number to an id String useful in debugging 188 * 189 * @param layout 190 * @param stateId 191 * @return 192 */ getState(MotionLayout layout, int stateId)193 public static String getState(MotionLayout layout, int stateId) { 194 return getState(layout, stateId, -1); 195 } 196 197 /** 198 * convert an id number to an id String useful in debugging 199 * 200 * @param layout 201 * @param stateId 202 * @param len trim if string > len 203 * @return 204 */ getState(MotionLayout layout, int stateId, int len)205 public static String getState(MotionLayout layout, int stateId, int len) { 206 if (stateId == -1) { 207 return "UNDEFINED"; 208 } 209 Context context = layout.getContext(); 210 String str = context.getResources().getResourceEntryName(stateId); 211 if (len != -1) { 212 if (str.length() > len) { 213 str = str.replaceAll("([^_])[aeiou]+", "$1"); // del vowels ! at start 214 } 215 if (str.length() > len) { 216 int n = str.replaceAll("[^_]", "").length(); // count number of "_" 217 if (n > 0) { 218 int extra = (str.length() - len) / n; 219 String reg = CharBuffer.allocate(extra).toString().replace('\0', '.') + "_"; 220 str = str.replaceAll(reg, "_"); 221 } 222 } 223 } 224 return str; 225 } 226 227 /** 228 * Convert a motion event action to a string 229 * 230 * @param event 231 * @return 232 */ getActionType(MotionEvent event)233 public static String getActionType(MotionEvent event) { 234 int type = event.getAction(); 235 Field[] fields = MotionEvent.class.getFields(); 236 for (int i = 0; i < fields.length; i++) { 237 Field field = fields[i]; 238 try { 239 if (java.lang.reflect.Modifier.isStatic(field.getModifiers()) 240 && field.getType().equals(Integer.TYPE) 241 && field.getInt(null) == type) { 242 return field.getName(); 243 } 244 } catch (IllegalAccessException e) { 245 } 246 } 247 return "---"; 248 } 249 250 /** 251 * Get file name and location where this method is called. 252 * Formatting it such that it is clickable by Intellij 253 * 254 * @return (filename : line_no) 255 */ getLocation()256 public static String getLocation() { 257 StackTraceElement s = new Throwable().getStackTrace()[1]; 258 return ".(" + s.getFileName() + ":" + s.getLineNumber() + ")"; 259 } 260 261 /** 262 * Get file name and location where this method is called. 263 * Formatting it such that it is clickable by Intellij 264 * 265 * @return (filename : line_no) 266 */ getLoc()267 public static String getLoc() { 268 StackTraceElement s = new Throwable().getStackTrace()[1]; 269 return ".(" + s.getFileName() + ":" + s.getLineNumber() + ") " + s.getMethodName() + "()"; 270 } 271 272 /** 273 * Get file name and location where this method is called. 274 * Formatting it such that it is clickable by Intellij 275 * 276 * @return (filename : line_no) 277 */ getLocation2()278 public static String getLocation2() { 279 StackTraceElement s = new Throwable().getStackTrace()[2]; 280 return ".(" + s.getFileName() + ":" + s.getLineNumber() + ")"; 281 } 282 283 /** 284 * Get file name and location where this method is called. 285 * Formatting it such that it is clickable by Intellij 286 * 287 * @return (filename : line_no) 288 */ getCallFrom(int n)289 public static String getCallFrom(int n) { 290 StackTraceElement s = new Throwable().getStackTrace()[2 + n]; 291 return ".(" + s.getFileName() + ":" + s.getLineNumber() + ")"; 292 } 293 294 // @TODO: add description 295 296 /** 297 * 298 * @param layout 299 * @param str 300 */ dumpLayoutParams(ViewGroup layout, String str)301 public static void dumpLayoutParams(ViewGroup layout, String str) { 302 StackTraceElement s = new Throwable().getStackTrace()[1]; 303 String loc = ".(" + s.getFileName() + ":" + s.getLineNumber() + ") " + str + " "; 304 int n = layout.getChildCount(); 305 System.out.println(str + " children " + n); 306 for (int i = 0; i < n; i++) { 307 View v = layout.getChildAt(i); 308 System.out.println(loc + " " + getName(v)); 309 ViewGroup.LayoutParams param = v.getLayoutParams(); 310 Field[] declaredFields = param.getClass().getFields(); 311 for (int k = 0; k < declaredFields.length; k++) { 312 Field declaredField = declaredFields[k]; 313 314 try { 315 Object value = declaredField.get(param); 316 String name = declaredField.getName(); 317 if (!name.contains("To")) { 318 continue; 319 } 320 if (value.toString().equals("-1")) { 321 continue; 322 } 323 324 System.out.println(loc + " " + declaredField.getName() + " " + value); 325 } catch (IllegalAccessException e) { 326 327 } 328 329 } 330 331 } 332 } 333 334 // @TODO: add description 335 336 /** 337 * 338 * @param param 339 * @param str 340 */ dumpLayoutParams(ViewGroup.LayoutParams param, String str)341 public static void dumpLayoutParams(ViewGroup.LayoutParams param, String str) { 342 StackTraceElement s = new Throwable().getStackTrace()[1]; 343 String loc = ".(" + s.getFileName() + ":" + s.getLineNumber() + ") " + str + " "; 344 System.out.println(" >>>>>>>>>>>>>>>>>>. dump " + loc + " " + param.getClass().getName()); 345 346 Field[] declaredFields = param.getClass().getFields(); 347 for (int k = 0; k < declaredFields.length; k++) { 348 Field declaredField = declaredFields[k]; 349 350 try { 351 Object value = declaredField.get(param); 352 String name = declaredField.getName(); 353 if (!name.contains("To")) { 354 continue; 355 } 356 if (value.toString().equals("-1")) { 357 continue; 358 } 359 // if (value instanceof Integer && value.toString().equals("-1")) { 360 // continue; 361 // } 362 363 System.out.println(loc + " " + name + " " + value); 364 } catch (IllegalAccessException e) { 365 366 } 367 368 } 369 System.out.println(" <<<<<<<<<<<<<<<<< dump " + loc); 370 371 } 372 } 373