summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHyunyoung Song <hyunyoungs@google.com>2017-02-06 10:46:24 -0800
committerHyunyoung Song <hyunyoungs@google.com>2017-04-04 23:06:30 +0000
commite295acaeb34c474430e68cbfb069a6a6bfea4041 (patch)
tree7575140da81484b2897ad165da8debd51a986eab /src
parentca18746163621211847a2f184d19a6b3e2b4a1c0 (diff)
downloadandroid_packages_apps_Trebuchet-e295acaeb34c474430e68cbfb069a6a6bfea4041.tar.gz
android_packages_apps_Trebuchet-e295acaeb34c474430e68cbfb069a6a6bfea4041.tar.bz2
android_packages_apps_Trebuchet-e295acaeb34c474430e68cbfb069a6a6bfea4041.zip
Launcher dump proto that will be used for:
$ adb shell dumpsys activity provider com.android.launcher3/com.android.launcher3.LauncherProvider To see how the proto is filled: go/launcher-proto-dump b/31772480 Change-Id: I8e0f1e5e38148a3dfeabd2fc057392193b2625dd (cherry picked from commit 6aa3729e98502d4cffc40a7e602628b85d558edd)
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/LauncherModel.java5
-rw-r--r--src/com/android/launcher3/LauncherProvider.java15
-rw-r--r--src/com/android/launcher3/logging/DumpTargetWrapper.java149
-rw-r--r--src/com/android/launcher3/logging/LoggerUtils.java33
-rw-r--r--src/com/android/launcher3/model/BgDataModel.java108
5 files changed, 299 insertions, 11 deletions
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 5a41eeb1f..8e99d47d0 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -127,6 +127,11 @@ public class LauncherModel extends BroadcastReceiver
// our monitoring of the package manager provides all updates and we never
// need to do a requery. This is only ever touched from the loader thread.
private boolean mModelLoaded;
+ public boolean isModelLoaded() {
+ synchronized (mLock) {
+ return mModelLoaded && mLoaderTask == null;
+ }
+ }
/**
* Set of runnables to be called on the background thread after the workspace binding
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 4771649d5..65d76728d 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -47,6 +47,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
+import android.view.ViewGroup;
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
import com.android.launcher3.LauncherSettings.Favorites;
@@ -64,6 +65,8 @@ import com.android.launcher3.util.NoLocaleSqliteContext;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Thunk;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
@@ -86,6 +89,18 @@ public class LauncherProvider extends ContentProvider {
protected DatabaseHelper mOpenHelper;
+ /**
+ * $ adb shell dumpsys activity provider com.android.launcher3
+ */
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ LauncherAppState appState = LauncherAppState.getInstanceNoCreate();
+ if (appState == null || !appState.getModel().isModelLoaded()) {
+ return;
+ }
+ appState.getModel().dumpState("", fd, writer, args);
+ }
+
@Override
public boolean onCreate() {
if (ProviderConfig.IS_DOGFOOD_BUILD) {
diff --git a/src/com/android/launcher3/logging/DumpTargetWrapper.java b/src/com/android/launcher3/logging/DumpTargetWrapper.java
new file mode 100644
index 000000000..2646a2242
--- /dev/null
+++ b/src/com/android/launcher3/logging/DumpTargetWrapper.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.logging;
+
+import android.os.Process;
+import android.text.TextUtils;
+
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.model.nano.LauncherDumpProto;
+import com.android.launcher3.model.nano.LauncherDumpProto.ContainerType;
+import com.android.launcher3.model.nano.LauncherDumpProto.DumpTarget;
+import com.android.launcher3.model.nano.LauncherDumpProto.ItemType;
+import com.android.launcher3.model.nano.LauncherDumpProto.UserType;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class can be used when proto definition doesn't support nesting.
+ */
+public class DumpTargetWrapper {
+ DumpTarget node;
+ ArrayList<DumpTargetWrapper> children;
+
+ public DumpTargetWrapper() {
+ children = new ArrayList<>();
+ }
+
+ public DumpTargetWrapper(DumpTarget t) {
+ this();
+ node = t;
+ }
+
+ public DumpTargetWrapper(int containerType, int id) {
+ this();
+ node = newContainerTarget(containerType, id);
+ }
+
+ public DumpTargetWrapper(ItemInfo info) {
+ this();
+ node = newItemTarget(info);
+ }
+
+ public DumpTarget getDumpTarget() {
+ return node;
+ }
+
+ public void add(DumpTargetWrapper child) {
+ children.add(child);
+ }
+
+ public List<DumpTarget> getFlattenedList() {
+ ArrayList<DumpTarget> list = new ArrayList<>();
+ list.add(node);
+ if (!children.isEmpty()) {
+ for(DumpTargetWrapper t: children) {
+ list.addAll(t.getFlattenedList());
+ }
+ list.add(node); // add a delimiter empty object
+ }
+ return list;
+ }
+ public DumpTarget newItemTarget(ItemInfo info) {
+ DumpTarget dt = new DumpTarget();
+ dt.type = DumpTarget.Type.ITEM;
+
+ switch (info.itemType) {
+ case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
+ dt.itemType = ItemType.APP_ICON;
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
+ dt.itemType = ItemType.UNKNOWN_ITEMTYPE;
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ dt.itemType = ItemType.WIDGET;
+ break;
+ case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
+ dt.itemType = ItemType.SHORTCUT;
+ break;
+ }
+ return dt;
+ }
+
+ public DumpTarget newContainerTarget(int type, int id) {
+ DumpTarget dt = new DumpTarget();
+ dt.type = DumpTarget.Type.CONTAINER;
+ dt.containerType = type;
+ dt.pageId = id;
+ return dt;
+ }
+
+ public static String getDumpTargetStr(DumpTarget t) {
+ if (t == null){
+ return "";
+ }
+ switch (t.type) {
+ case LauncherDumpProto.DumpTarget.Type.ITEM:
+ return getItemStr(t);
+ case LauncherDumpProto.DumpTarget.Type.CONTAINER:
+ String str = LoggerUtils.getFieldName(t.containerType, ContainerType.class);
+ if (t.containerType == ContainerType.WORKSPACE) {
+ str += " id=" + t.pageId;
+ } else if (t.containerType == ContainerType.FOLDER) {
+ str += " grid(" + t.gridX + "," + t.gridY+ ")";
+ }
+ return str;
+ default:
+ return "UNKNOWN TARGET TYPE";
+ }
+ }
+
+ private static String getItemStr(DumpTarget t) {
+ String typeStr = LoggerUtils.getFieldName(t.itemType, ItemType.class);
+ if (!TextUtils.isEmpty(t.packageName)) {
+ typeStr += ", package=" + t.packageName;
+ }
+ if (!TextUtils.isEmpty(t.component)) {
+ typeStr += ", component=" + t.component;
+ }
+ return typeStr + ", grid(" + t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY
+ + "), pageIdx=" + t.pageId + " user=" + t.userType;
+ }
+
+ public DumpTarget writeToDumpTarget(ItemInfo info) {
+ node.component = info.getTargetComponent() == null? "":
+ info.getTargetComponent().flattenToString();
+ node.packageName = info.getIntent() == null? "": info.getIntent().getPackage();
+ node.gridX = info.cellX;
+ node.gridY = info.cellY;
+ node.spanX = info.spanX;
+ node.spanY = info.spanY;
+ node.userType = (info.user.equals(Process.myUserHandle()))? UserType.DEFAULT : UserType.WORK;
+ return node;
+ }
+}
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index c13e8b336..499fdc7d3 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -1,5 +1,21 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package com.android.launcher3.logging;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.SparseArray;
import android.view.View;
@@ -27,7 +43,7 @@ public class LoggerUtils {
private static final ArrayMap<Class, SparseArray<String>> sNameCache = new ArrayMap<>();
private static final String UNKNOWN = "UNKNOWN";
- private static String getFieldName(int value, Class c) {
+ public static String getFieldName(int value, Class c) {
SparseArray<String> cache;
synchronized (sNameCache) {
cache = sNameCache.get(c);
@@ -68,8 +84,13 @@ public class LoggerUtils {
case Target.Type.CONTROL:
return getFieldName(t.controlType, ControlType.class);
case Target.Type.CONTAINER:
- return getFieldName(t.containerType, ContainerType.class)
- + " id=" + t.pageIndex;
+ String str = getFieldName(t.containerType, ContainerType.class);
+ if (t.containerType == ContainerType.WORKSPACE) {
+ str += " id=" + t.pageIndex;
+ } else if (t.containerType == ContainerType.FOLDER) {
+ str += " grid(" + t.gridX + "," + t.gridY+ ")";
+ }
+ return str;
default:
return "UNKNOWN TARGET TYPE";
}
@@ -86,10 +107,8 @@ public class LoggerUtils {
if (t.intentHash != 0) {
typeStr += ", intentHash=" + t.intentHash;
}
- if (t.spanX != 0) {
- typeStr += ", spanX=" + t.spanX;
- }
- return typeStr + ", grid=(" + t.gridX + "," + t.gridY + "), id=" + t.pageIndex;
+ return typeStr + ", grid(" + t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY
+ + "), pageIdx=" + t.pageIndex;
}
public static Target newItemTarget(View v) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 6b64087a2..0e73ca6d3 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -24,19 +24,27 @@ import android.util.MutableInt;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ItemInfo;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.config.ProviderConfig;
+import com.android.launcher3.logging.LoggerUtils;
+import com.android.launcher3.logging.DumpTargetWrapper;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.model.nano.LauncherDumpProto;
+import com.android.launcher3.model.nano.LauncherDumpProto.ContainerType;
+import com.android.launcher3.model.nano.LauncherDumpProto.DumpTarget;
+import com.android.launcher3.model.nano.LauncherDumpProto.ItemType;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.MultiHashMap;
+import com.google.protobuf.nano.MessageNano;
import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -102,21 +110,31 @@ public class BgDataModel {
deepShortcutMap.clear();
}
- // TODO: current dump is very cryptic and hard to understand. Make it more legible.
- public synchronized void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
+ public synchronized void dump(String prefix, FileDescriptor fd, PrintWriter writer,
+ String[] args) {
+ if (args.length > 0 && TextUtils.equals(args[0], "--proto")) {
+ dumpProto(prefix, fd, writer, args);
+ return;
+ }
writer.println(prefix + "Data Model:");
+ writer.print(prefix + " ---- workspace screens: ");
for (int i = 0; i < workspaceScreens.size(); i++) {
- writer.println(prefix + "\tIndex of workspaceScreens:" + workspaceScreens.get(i).toString());
+ writer.print(" " + workspaceScreens.get(i).toString());
}
+ writer.println();
+ writer.println(prefix + " ---- workspace items ");
for (int i = 0; i < workspaceItems.size(); i++) {
writer.println(prefix + '\t' + workspaceItems.get(i).toString());
}
+ writer.println(prefix + " ---- appwidget items ");
for (int i = 0; i < appWidgets.size(); i++) {
writer.println(prefix + '\t' + appWidgets.get(i).toString());
}
+ writer.println(prefix + " ---- folder items ");
for (int i = 0; i< folders.size(); i++) {
writer.println(prefix + '\t' + folders.valueAt(i).toString());
}
+ writer.println(prefix + " ---- items id map ");
for (int i = 0; i< itemsIdMap.size(); i++) {
writer.println(prefix + '\t' + itemsIdMap.valueAt(i).toString());
}
@@ -133,6 +151,88 @@ public class BgDataModel {
}
}
+ private synchronized void dumpProto(String prefix, FileDescriptor fd, PrintWriter writer,
+ String[] args) {
+
+ // Add top parent nodes. (L1)
+ DumpTargetWrapper hotseat = new DumpTargetWrapper(ContainerType.HOTSEAT, 0);
+ LongArrayMap<DumpTargetWrapper> workspaces = new LongArrayMap<>();
+ for (int i = 0; i < workspaceScreens.size(); i++) {
+ workspaces.put(new Long(workspaceScreens.get(i)),
+ new DumpTargetWrapper(ContainerType.WORKSPACE, i));
+ }
+ DumpTargetWrapper dtw;
+ // Add non leaf / non top nodes (L2)
+ for (int i = 0; i < folders.size(); i++) {
+ FolderInfo fInfo = folders.valueAt(i);
+ dtw = new DumpTargetWrapper(ContainerType.FOLDER, folders.size());
+ dtw.writeToDumpTarget(fInfo);
+ for(ShortcutInfo sInfo: fInfo.contents) {
+ DumpTargetWrapper child = new DumpTargetWrapper(sInfo);
+ child.writeToDumpTarget(sInfo);
+ dtw.add(child);
+ }
+ if (fInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ hotseat.add(dtw);
+ } else if (fInfo.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ workspaces.get(new Long(fInfo.screenId)).add(dtw);
+ }
+ }
+ // Add leaf nodes (L3): *Info
+ for (int i = 0; i < workspaceItems.size(); i++) {
+ ItemInfo info = workspaceItems.get(i);
+ if (info instanceof FolderInfo) {
+ continue;
+ }
+ dtw = new DumpTargetWrapper(info);
+ dtw.writeToDumpTarget(info);
+ if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ hotseat.add(dtw);
+ } else if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ workspaces.get(new Long(info.screenId)).add(dtw);
+ }
+ }
+ for (int i = 0; i < appWidgets.size(); i++) {
+ ItemInfo info = appWidgets.get(i);
+ dtw = new DumpTargetWrapper(info);
+ dtw.writeToDumpTarget(info);
+ if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
+ hotseat.add(dtw);
+ } else if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ workspaces.get(new Long(info.screenId)).add(dtw);
+ }
+ }
+
+
+ // Traverse target wrapper
+ ArrayList<DumpTarget> targetList = new ArrayList<>();
+ targetList.addAll(hotseat.getFlattenedList());
+ for (int i = 0; i < workspaces.size(); i++) {
+ targetList.addAll(workspaces.valueAt(i).getFlattenedList());
+ }
+
+ if (args.length > 1 && TextUtils.equals(args[1], "--debug")) {
+ for (int i = 0; i < targetList.size(); i++) {
+ writer.println(prefix + DumpTargetWrapper.getDumpTargetStr(targetList.get(i)));
+ }
+ return;
+ } else {
+ LauncherDumpProto.LauncherImpression proto = new LauncherDumpProto.LauncherImpression();
+ proto.targets = new DumpTarget[targetList.size()];
+ for (int i = 0; i < targetList.size(); i++) {
+ proto.targets[i] = targetList.get(i);
+ }
+ FileOutputStream fos = new FileOutputStream(fd);
+ try {
+
+ fos.write(MessageNano.toByteArray(proto));
+ Log.d(TAG, MessageNano.toByteArray(proto).length + "Bytes");
+ } catch (IOException e) {
+ Log.e(TAG, "Exception writing dumpsys --proto", e);
+ }
+ }
+ }
+
public synchronized void removeItem(Context context, ItemInfo... items) {
removeItem(context, Arrays.asList(items));
}