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 android.text.TextUtils;
19 import android.util.ArrayMap;
20 import android.util.SparseArray;
21 import android.view.View;
22 
23 import com.android.launcher3.ButtonDropTarget;
24 import com.android.launcher3.DeleteDropTarget;
25 import com.android.launcher3.InfoDropTarget;
26 import com.android.launcher3.ItemInfo;
27 import com.android.launcher3.LauncherSettings;
28 import com.android.launcher3.UninstallDropTarget;
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 
36 import java.lang.reflect.Field;
37 import java.lang.reflect.Modifier;
38 
39 /**
40  * Helper methods for logging.
41  */
42 public class LoggerUtils {
43     private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
44     private static final String UNKNOWN = "UNKNOWN";
45 
getFieldName(int value, Class c)46     public static String getFieldName(int value, Class c) {
47         SparseArray<String> cache;
48         synchronized (sNameCache) {
49             cache = sNameCache.get(c);
50             if (cache == null) {
51                 cache = new SparseArray<>();
52                 for (Field f : c.getDeclaredFields()) {
53                     if (f.getType() == int.class && Modifier.isStatic(f.getModifiers())) {
54                         try {
55                             f.setAccessible(true);
56                             cache.put(f.getInt(null), f.getName());
57                         } catch (IllegalAccessException e) {
58                             // Ignore
59                         }
60                     }
61                 }
62                 sNameCache.put(c, cache);
63             }
64         }
65         String result = cache.get(value);
66         return result != null ? result : UNKNOWN;
67     }
68 
getActionStr(Action action)69     public static String getActionStr(Action action) {
70         switch (action.type) {
71             case Action.Type.TOUCH: return getFieldName(action.touch, Action.Touch.class);
72             case Action.Type.COMMAND: return getFieldName(action.command, Action.Command.class);
73             default: return UNKNOWN;
74         }
75     }
76 
getTargetStr(Target t)77     public static String getTargetStr(Target t) {
78         if (t == null){
79             return "";
80         }
81         switch (t.type) {
82             case Target.Type.ITEM:
83                 return getItemStr(t);
84             case Target.Type.CONTROL:
85                 return getFieldName(t.controlType, ControlType.class);
86             case Target.Type.CONTAINER:
87                 String str = getFieldName(t.containerType, ContainerType.class);
88                 if (t.containerType == ContainerType.WORKSPACE) {
89                     str += " id=" + t.pageIndex;
90                 } else if (t.containerType == ContainerType.FOLDER) {
91                     str += " grid(" + t.gridX + "," + t.gridY+ ")";
92                 }
93                 return str;
94             default:
95                 return "UNKNOWN TARGET TYPE";
96         }
97     }
98 
getItemStr(Target t)99     private static String getItemStr(Target t) {
100         String typeStr = getFieldName(t.itemType, ItemType.class);
101         if (t.packageNameHash != 0) {
102             typeStr += ", packageHash=" + t.packageNameHash;
103         }
104         if (t.componentHash != 0) {
105             typeStr += ", componentHash=" + t.componentHash;
106         }
107         if (t.intentHash != 0) {
108             typeStr += ", intentHash=" + t.intentHash;
109         }
110         return typeStr + ", grid(" + t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY
111                 + "), pageIdx=" + t.pageIndex;
112     }
113 
newItemTarget(View v)114     public static Target newItemTarget(View v) {
115         return (v.getTag() instanceof ItemInfo)
116                 ? newItemTarget((ItemInfo) v.getTag())
117                 : newTarget(Target.Type.ITEM);
118     }
119 
newItemTarget(ItemInfo info)120     public static Target newItemTarget(ItemInfo info) {
121         Target t = newTarget(Target.Type.ITEM);
122         switch (info.itemType) {
123             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
124                 t.itemType = ItemType.APP_ICON;
125                 break;
126             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
127                 t.itemType = ItemType.SHORTCUT;
128                 break;
129             case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
130                 t.itemType = ItemType.FOLDER_ICON;
131                 break;
132             case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
133                 t.itemType = ItemType.WIDGET;
134                 break;
135             case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
136                 t.itemType = ItemType.DEEPSHORTCUT;
137                 break;
138         }
139         return t;
140     }
141 
newDropTarget(View v)142     public static Target newDropTarget(View v) {
143         if (!(v instanceof ButtonDropTarget)) {
144             return newTarget(Target.Type.CONTAINER);
145         }
146         Target t = newTarget(Target.Type.CONTROL);
147         if (v instanceof InfoDropTarget) {
148             t.controlType = ControlType.APPINFO_TARGET;
149         } else if (v instanceof UninstallDropTarget) {
150             t.controlType = ControlType.UNINSTALL_TARGET;
151         } else if (v instanceof DeleteDropTarget) {
152             t.controlType = ControlType.REMOVE_TARGET;
153         }
154         return t;
155     }
156 
newTarget(int targetType)157     public static Target newTarget(int targetType) {
158         Target t = new Target();
159         t.type = targetType;
160         return t;
161     }
newContainerTarget(int containerType)162     public static Target newContainerTarget(int containerType) {
163         Target t = newTarget(Target.Type.CONTAINER);
164         t.containerType = containerType;
165         return t;
166     }
167 
newAction(int type)168     public static Action newAction(int type) {
169         Action a = new Action();
170         a.type = type;
171         return a;
172     }
newCommandAction(int command)173     public static Action newCommandAction(int command) {
174         Action a = newAction(Action.Type.COMMAND);
175         a.command = command;
176         return a;
177     }
newTouchAction(int touch)178     public static Action newTouchAction(int touch) {
179         Action a = newAction(Action.Type.TOUCH);
180         a.touch = touch;
181         return a;
182     }
183 
newLauncherEvent(Action action, Target... srcTargets)184     public static LauncherEvent newLauncherEvent(Action action, Target... srcTargets) {
185         LauncherEvent event = new LauncherEvent();
186         event.srcTarget = srcTargets;
187         event.action = action;
188         return event;
189     }
190 }
191