1 /* 2 * Copyright (C) 2016 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.android.launcher3.logging; 17 18 import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR; 19 20 import android.util.ArrayMap; 21 import android.util.SparseArray; 22 import android.view.View; 23 24 import com.android.launcher3.AppInfo; 25 import com.android.launcher3.ButtonDropTarget; 26 import com.android.launcher3.ItemInfo; 27 import com.android.launcher3.LauncherSettings; 28 import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension; 29 import com.android.launcher3.userevent.nano.LauncherLogProto.Action; 30 import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; 31 import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; 32 import com.android.launcher3.userevent.nano.LauncherLogProto.ItemType; 33 import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent; 34 import com.android.launcher3.userevent.nano.LauncherLogProto.Target; 35 import com.android.launcher3.userevent.nano.LauncherLogProto.TipType; 36 import com.android.launcher3.util.InstantAppResolver; 37 38 import java.lang.reflect.Field; 39 import java.lang.reflect.Modifier; 40 41 /** 42 * Helper methods for logging. 43 */ 44 public class LoggerUtils { 45 private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>(); 46 private static final String UNKNOWN = "UNKNOWN"; 47 getFieldName(int value, Class c)48 public static String getFieldName(int value, Class c) { 49 SparseArray<String> cache; 50 synchronized (sNameCache) { 51 cache = sNameCache.get(c); 52 if (cache == null) { 53 cache = new SparseArray<>(); 54 for (Field f : c.getDeclaredFields()) { 55 if (f.getType() == int.class && Modifier.isStatic(f.getModifiers())) { 56 try { 57 f.setAccessible(true); 58 cache.put(f.getInt(null), f.getName()); 59 } catch (IllegalAccessException e) { 60 // Ignore 61 } 62 } 63 } 64 sNameCache.put(c, cache); 65 } 66 } 67 String result = cache.get(value); 68 return result != null ? result : UNKNOWN; 69 } 70 getActionStr(Action action)71 public static String getActionStr(Action action) { 72 String str = ""; 73 switch (action.type) { 74 case Action.Type.TOUCH: 75 str += getFieldName(action.touch, Action.Touch.class); 76 if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING) { 77 str += " direction=" + getFieldName(action.dir, Action.Direction.class); 78 } 79 break; 80 case Action.Type.COMMAND: 81 str += getFieldName(action.command, Action.Command.class); 82 break; 83 default: return getFieldName(action.type, Action.Type.class); 84 } 85 if (action.touch == Action.Touch.SWIPE || action.touch == Action.Touch.FLING || 86 (action.command == Action.Command.BACK && action.dir != Action.Direction.NONE)) { 87 str += " direction=" + getFieldName(action.dir, Action.Direction.class); 88 } 89 return str; 90 } 91 getTargetStr(Target t)92 public static String getTargetStr(Target t) { 93 if (t == null){ 94 return ""; 95 } 96 String str = ""; 97 switch (t.type) { 98 case Target.Type.ITEM: 99 str = getItemStr(t); 100 break; 101 case Target.Type.CONTROL: 102 str = getFieldName(t.controlType, ControlType.class); 103 break; 104 case Target.Type.CONTAINER: 105 str = getFieldName(t.containerType, ContainerType.class); 106 if (t.containerType == ContainerType.WORKSPACE || 107 t.containerType == ContainerType.HOTSEAT || 108 t.containerType == NAVBAR) { 109 str += " id=" + t.pageIndex; 110 } else if (t.containerType == ContainerType.FOLDER) { 111 str += " grid(" + t.gridX + "," + t.gridY + ")"; 112 } 113 break; 114 default: 115 str += "UNKNOWN TARGET TYPE"; 116 } 117 118 if (t.spanX != 1 || t.spanY != 1) { 119 str += " span(" + t.spanX + "," + t.spanY + ")"; 120 } 121 122 if (t.tipType != TipType.DEFAULT_NONE) { 123 str += " " + getFieldName(t.tipType, TipType.class); 124 } 125 126 return str; 127 } 128 getItemStr(Target t)129 private static String getItemStr(Target t) { 130 String typeStr = getFieldName(t.itemType, ItemType.class); 131 if (t.packageNameHash != 0) { 132 typeStr += ", packageHash=" + t.packageNameHash; 133 } 134 if (t.componentHash != 0) { 135 typeStr += ", componentHash=" + t.componentHash; 136 } 137 if (t.intentHash != 0) { 138 typeStr += ", intentHash=" + t.intentHash; 139 } 140 if ((t.packageNameHash != 0 || t.componentHash != 0 || t.intentHash != 0) && 141 t.itemType != ItemType.TASK) { 142 typeStr += ", predictiveRank=" + t.predictedRank + ", grid(" + t.gridX + "," + t.gridY 143 + "), span(" + t.spanX + "," + t.spanY 144 + "), pageIdx=" + t.pageIndex; 145 146 } 147 if (t.searchQueryLength != 0) { 148 typeStr += ", searchQueryLength=" + t.searchQueryLength; 149 } 150 151 if (t.itemType == ItemType.TASK) { 152 typeStr += ", pageIdx=" + t.pageIndex; 153 } 154 return typeStr; 155 } 156 newItemTarget(int itemType)157 public static Target newItemTarget(int itemType) { 158 Target t = newTarget(Target.Type.ITEM); 159 t.itemType = itemType; 160 return t; 161 } 162 newItemTarget(View v, InstantAppResolver instantAppResolver)163 public static Target newItemTarget(View v, InstantAppResolver instantAppResolver) { 164 return (v != null) && (v.getTag() instanceof ItemInfo) 165 ? newItemTarget((ItemInfo) v.getTag(), instantAppResolver) 166 : newTarget(Target.Type.ITEM); 167 } 168 newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver)169 public static Target newItemTarget(ItemInfo info, InstantAppResolver instantAppResolver) { 170 Target t = newTarget(Target.Type.ITEM); 171 172 switch (info.itemType) { 173 case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION: 174 t.itemType = (instantAppResolver != null && info instanceof AppInfo 175 && instantAppResolver.isInstantApp(((AppInfo) info)) ) 176 ? ItemType.WEB_APP 177 : ItemType.APP_ICON; 178 t.predictedRank = -100; // Never assigned 179 break; 180 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT: 181 t.itemType = ItemType.SHORTCUT; 182 break; 183 case LauncherSettings.Favorites.ITEM_TYPE_FOLDER: 184 t.itemType = ItemType.FOLDER_ICON; 185 break; 186 case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: 187 t.itemType = ItemType.WIDGET; 188 break; 189 case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT: 190 t.itemType = ItemType.DEEPSHORTCUT; 191 break; 192 } 193 return t; 194 } 195 newDropTarget(View v)196 public static Target newDropTarget(View v) { 197 if (!(v instanceof ButtonDropTarget)) { 198 return newTarget(Target.Type.CONTAINER); 199 } 200 if (v instanceof ButtonDropTarget) { 201 return ((ButtonDropTarget) v).getDropTargetForLogging(); 202 } 203 return newTarget(Target.Type.CONTROL); 204 } 205 newTarget(int targetType, TargetExtension extension)206 public static Target newTarget(int targetType, TargetExtension extension) { 207 Target t = new Target(); 208 t.type = targetType; 209 t.extension = extension; 210 return t; 211 } 212 newTarget(int targetType)213 public static Target newTarget(int targetType) { 214 Target t = new Target(); 215 t.type = targetType; 216 return t; 217 } 218 newControlTarget(int controlType)219 public static Target newControlTarget(int controlType) { 220 Target t = newTarget(Target.Type.CONTROL); 221 t.controlType = controlType; 222 return t; 223 } 224 newContainerTarget(int containerType)225 public static Target newContainerTarget(int containerType) { 226 Target t = newTarget(Target.Type.CONTAINER); 227 t.containerType = containerType; 228 return t; 229 } 230 newAction(int type)231 public static Action newAction(int type) { 232 Action a = new Action(); 233 a.type = type; 234 return a; 235 } 236 newCommandAction(int command)237 public static Action newCommandAction(int command) { 238 Action a = newAction(Action.Type.COMMAND); 239 a.command = command; 240 return a; 241 } 242 newTouchAction(int touch)243 public static Action newTouchAction(int touch) { 244 Action a = newAction(Action.Type.TOUCH); 245 a.touch = touch; 246 return a; 247 } 248 newLauncherEvent(Action action, Target... srcTargets)249 public static LauncherEvent newLauncherEvent(Action action, Target... srcTargets) { 250 LauncherEvent event = new LauncherEvent(); 251 event.srcTarget = srcTargets; 252 event.action = action; 253 return event; 254 } 255 } 256