Refactor UserEventLogging, Add predictedRank, replace Bundle with Proto
b/26494415 - Removed bundle object that became redundant now that we have LauncherEvent proto - Combined Stats and UserEventLogger as they are effectively doing same thing - Removed parent field inside Target - added predictedRank target inside Target b/27967359 - make com.android.launcher3.action.LAUNCH broadcast explicit Later CL: finish packageName/intent/componentHash/predictedRank fields Change-Id: I441fb46c834f73e58a4d2324e8da7971e8713ec8
This commit is contained in:
+45
-38
@@ -32,59 +32,66 @@ message Target {
|
|||||||
|
|
||||||
// For container type and item type
|
// For container type and item type
|
||||||
// Used mainly for ContainerType.FOLDER, ItemType.*
|
// Used mainly for ContainerType.FOLDER, ItemType.*
|
||||||
optional Target parent = 2;
|
optional int32 page_index = 2;
|
||||||
optional int32 page_index = 3;
|
optional int32 rank = 3;
|
||||||
optional int32 rank = 4;
|
optional int32 grid_x = 4;
|
||||||
optional int32 grid_x = 5;
|
optional int32 grid_y = 5;
|
||||||
optional int32 grid_y = 6;
|
|
||||||
|
|
||||||
// For container types only
|
// For container types only
|
||||||
optional ContainerType container_type = 7;
|
optional ContainerType container_type = 6;
|
||||||
optional int32 cardinality = 8;
|
optional int32 cardinality = 7;
|
||||||
|
|
||||||
// For control types only
|
// For control types only
|
||||||
optional ControlType control_type = 9;
|
optional ControlType control_type = 8;
|
||||||
|
|
||||||
// For item types only
|
// For item types only
|
||||||
optional ItemType item_type = 10;
|
optional ItemType item_type = 9;
|
||||||
optional int32 package_name_hash = 11;
|
optional int32 package_name_hash = 10;
|
||||||
optional int32 component_hash = 12; // Used for ItemType.WIDGET
|
optional int32 component_hash = 11; // Used for ItemType.WIDGET
|
||||||
optional int32 intent_hash = 13; // Used for ItemType.SHORTCUT
|
optional int32 intent_hash = 12; // Used for ItemType.SHORTCUT
|
||||||
optional int32 span_x = 14 [default = 1];// Used for ItemType.WIDGET
|
optional int32 span_x = 13 [default = 1];// Used for ItemType.WIDGET
|
||||||
optional int32 span_y = 15 [default = 1];// Used for ItemType.WIDGET
|
optional int32 span_y = 14 [default = 1];// Used for ItemType.WIDGET
|
||||||
|
optional int32 predictedRank = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to define what type of item a Target would represent.
|
||||||
enum ItemType {
|
enum ItemType {
|
||||||
APP_ICON = 0;
|
DEFAULT_ITEMTYPE = 0;
|
||||||
SHORTCUT = 1;
|
APP_ICON = 1;
|
||||||
WIDGET = 2;
|
SHORTCUT = 2;
|
||||||
FOLDER_ICON = 3;
|
WIDGET = 3;
|
||||||
|
FOLDER_ICON = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to define what type of container a Target would represent.
|
||||||
enum ContainerType {
|
enum ContainerType {
|
||||||
WORKSPACE = 0;
|
DEFAULT_CONTAINERTYPE = 0;
|
||||||
HOTSEAT = 1;
|
WORKSPACE = 1;
|
||||||
FOLDER = 2;
|
HOTSEAT = 2;
|
||||||
ALLAPPS = 3;
|
FOLDER = 3;
|
||||||
WIDGETS = 4;
|
ALLAPPS = 4;
|
||||||
OVERVIEW = 5;
|
WIDGETS = 5;
|
||||||
PREDICTION = 6;
|
OVERVIEW = 6;
|
||||||
SEARCHRESULT = 7;
|
PREDICTION = 7;
|
||||||
|
SEARCHRESULT = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to define what type of control a Target would represent.
|
||||||
enum ControlType {
|
enum ControlType {
|
||||||
ALL_APPS_BUTTON = 0;
|
DEFAULT_CONTROLTYPE = 0;
|
||||||
WIDGETS_BUTTON = 1;
|
ALL_APPS_BUTTON = 1;
|
||||||
WALLPAPER_BUTTON = 2;
|
WIDGETS_BUTTON = 2;
|
||||||
SETTINGS_BUTTON = 3;
|
WALLPAPER_BUTTON = 3;
|
||||||
REMOVE_TARGET = 4;
|
SETTINGS_BUTTON = 4;
|
||||||
UNINSTALL_TARGET = 5;
|
REMOVE_TARGET = 5;
|
||||||
APPINFO_TARGET = 6;
|
UNINSTALL_TARGET = 6;
|
||||||
RESIZE_HANDLE = 7;
|
APPINFO_TARGET = 7;
|
||||||
FAST_SCROLL_HANDLE = 8;
|
RESIZE_HANDLE = 8;
|
||||||
|
VERTICAL_SCROLL = 9;
|
||||||
// HOME, BACK, GO_TO_PLAYSTORE
|
// HOME, BACK, GO_TO_PLAYSTORE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Used to define the action component of the LauncherEvent.
|
||||||
message Action {
|
message Action {
|
||||||
enum Type {
|
enum Type {
|
||||||
TOUCH = 0;
|
TOUCH = 0;
|
||||||
@@ -113,10 +120,10 @@ message LauncherEvent {
|
|||||||
required Action action = 1;
|
required Action action = 1;
|
||||||
|
|
||||||
// List of targets that touch actions can be operated on.
|
// List of targets that touch actions can be operated on.
|
||||||
optional Target src_target = 2;
|
repeated Target src_target = 2;
|
||||||
optional Target dest_target = 3;
|
repeated Target dest_target = 3;
|
||||||
|
|
||||||
optional int64 action_duration_millis = 4;
|
optional int64 action_duration_millis = 4;
|
||||||
optional int64 elapsed_container_millis = 5;
|
optional int64 elapsed_container_millis = 5;
|
||||||
optional int64 elapsed_session_millis = 6;
|
optional int64 elapsed_session_millis = 6;
|
||||||
}
|
}
|
||||||
@@ -68,6 +68,10 @@
|
|||||||
filter the activities shown in the launcher. Can be empty. -->
|
filter the activities shown in the launcher. Can be empty. -->
|
||||||
<string name="app_filter_class" translatable="false"></string>
|
<string name="app_filter_class" translatable="false"></string>
|
||||||
|
|
||||||
|
<!-- List of package names that com.android.launcher3.action.LAUNCH
|
||||||
|
should be targeting. Can be empty. -->
|
||||||
|
<array name="launch_broadcast_targets" translatable="false"></array>
|
||||||
|
|
||||||
<!-- Name of an icon provider class. -->
|
<!-- Name of an icon provider class. -->
|
||||||
<string name="icon_provider_class" translatable="false"></string>
|
<string name="icon_provider_class" translatable="false"></string>
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package com.android.launcher3;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
@@ -28,8 +27,12 @@ import android.view.ViewDebug;
|
|||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.android.launcher3.logging.UserEventLogger;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
|
|
||||||
public class Hotseat extends FrameLayout
|
public class Hotseat extends FrameLayout
|
||||||
implements Stats.LaunchSourceProvider{
|
implements UserEventLogger.LaunchSourceProvider{
|
||||||
|
|
||||||
private CellLayout mContent;
|
private CellLayout mContent;
|
||||||
|
|
||||||
@@ -157,7 +160,10 @@ public class Hotseat extends FrameLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fillInLaunchSourceData(View v, Bundle sourceData) {
|
public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOTSEAT);
|
target.itemType = LauncherLogProto.APP_ICON;
|
||||||
|
target.gridX = info.cellX;
|
||||||
|
target.gridY = info.cellY;
|
||||||
|
targetParent.containerType = LauncherLogProto.HOTSEAT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ public class Launcher extends Activity
|
|||||||
static final boolean DEBUG_WIDGETS = false;
|
static final boolean DEBUG_WIDGETS = false;
|
||||||
static final boolean DEBUG_STRICT_MODE = false;
|
static final boolean DEBUG_STRICT_MODE = false;
|
||||||
static final boolean DEBUG_RESUME_TIME = false;
|
static final boolean DEBUG_RESUME_TIME = false;
|
||||||
|
static final boolean DEBUG_LOGGING = false;
|
||||||
|
|
||||||
static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run
|
static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run
|
||||||
|
|
||||||
@@ -174,7 +175,7 @@ public class Launcher extends Activity
|
|||||||
protected static final int REQUEST_LAST = 100;
|
protected static final int REQUEST_LAST = 100;
|
||||||
|
|
||||||
// To turn on these properties, type
|
// To turn on these properties, type
|
||||||
// adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
|
// adb shell setprop logTap.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
|
||||||
static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
|
static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
|
||||||
|
|
||||||
// The Intent extra that defines whether to ignore the launch animation
|
// The Intent extra that defines whether to ignore the launch animation
|
||||||
@@ -365,7 +366,6 @@ public class Launcher extends Activity
|
|||||||
int appWidgetId;
|
int appWidgetId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stats mStats;
|
|
||||||
private UserEventLogger mUserEventLogger;
|
private UserEventLogger mUserEventLogger;
|
||||||
|
|
||||||
public FocusIndicatorView mFocusHandler;
|
public FocusIndicatorView mFocusHandler;
|
||||||
@@ -425,7 +425,6 @@ public class Launcher extends Activity
|
|||||||
mDragController = new DragController(this);
|
mDragController = new DragController(this);
|
||||||
mStateTransitionAnimation = new LauncherStateTransitionAnimation(this);
|
mStateTransitionAnimation = new LauncherStateTransitionAnimation(this);
|
||||||
|
|
||||||
mStats = new Stats(this);
|
|
||||||
initLogger();
|
initLogger();
|
||||||
|
|
||||||
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
|
mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
|
||||||
@@ -638,10 +637,6 @@ public class Launcher extends Activity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stats getStats() {
|
|
||||||
return mStats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logger object is a singleton and does not have to be coupled with the foreground activity.
|
* Logger object is a singleton and does not have to be coupled with the foreground activity.
|
||||||
* Since most user event logging is done on the UI, the object is retrieved from the
|
* Since most user event logging is done on the UI, the object is retrieved from the
|
||||||
@@ -652,16 +647,19 @@ public class Launcher extends Activity
|
|||||||
mUserEventLogger = mLauncherCallbacks.getLogger();
|
mUserEventLogger = mLauncherCallbacks.getLogger();
|
||||||
}
|
}
|
||||||
if (mUserEventLogger == null) {
|
if (mUserEventLogger == null) {
|
||||||
mUserEventLogger = new UserEventLogger() {
|
mUserEventLogger = new UserEventLogger(this) {
|
||||||
@Override
|
@Override
|
||||||
public void processEvent(LauncherLogProto.LauncherEvent ev) {
|
public void processEvent(LauncherLogProto.LauncherEvent ev) {
|
||||||
if (ev.action.touch == LauncherLogProto.Action.TAP && ev.srcTarget.itemType == LauncherLogProto.APP_ICON) {
|
if (!DEBUG_LOGGING) {
|
||||||
Log.d(TAG, String.format(Locale.US, "action:%s target:%s\n\telapsed container %d ms session %d ms",
|
return;
|
||||||
LoggerUtils.getActionStr(ev.action),
|
|
||||||
LoggerUtils.getTargetStr(ev.srcTarget),
|
|
||||||
ev.elapsedContainerMillis,
|
|
||||||
ev.elapsedSessionMillis));
|
|
||||||
}
|
}
|
||||||
|
Log.d("UserEvent", String.format(Locale.US,
|
||||||
|
"action:%s\nchild:%s\nparent:%s\nelapsed container %d ms session %d ms",
|
||||||
|
LoggerUtils.getActionStr(ev.action),
|
||||||
|
LoggerUtils.getTargetStr(ev.srcTarget[0]),
|
||||||
|
LoggerUtils.getTargetStr(ev.srcTarget[1]),
|
||||||
|
ev.elapsedContainerMillis,
|
||||||
|
ev.elapsedSessionMillis));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -2705,7 +2703,7 @@ public class Launcher extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean success = startActivitySafely(v, intent, tag);
|
boolean success = startActivitySafely(v, intent, tag);
|
||||||
mStats.recordLaunch(v, intent, shortcut);
|
mUserEventLogger.logLaunch(v, intent);
|
||||||
|
|
||||||
if (success && v instanceof BubbleTextView) {
|
if (success && v instanceof BubbleTextView) {
|
||||||
mWaitingForResume = (BubbleTextView) v;
|
mWaitingForResume = (BubbleTextView) v;
|
||||||
@@ -3488,6 +3486,7 @@ public class Launcher extends Activity
|
|||||||
List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps();
|
List<ComponentKey> apps = mLauncherCallbacks.getPredictedApps();
|
||||||
if (apps != null) {
|
if (apps != null) {
|
||||||
mAppsView.setPredictedApps(apps);
|
mAppsView.setPredictedApps(apps);
|
||||||
|
mUserEventLogger.setPredictedApps(apps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package com.android.launcher3;
|
package com.android.launcher3;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import com.android.launcher3.allapps.AllAppsSearchBarController;
|
import com.android.launcher3.allapps.AllAppsSearchBarController;
|
||||||
import com.android.launcher3.logging.UserEventLogger;
|
import com.android.launcher3.logging.UserEventLogger;
|
||||||
import com.android.launcher3.util.ComponentKey;
|
import com.android.launcher3.util.ComponentKey;
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ public class LauncherFiles {
|
|||||||
|
|
||||||
// TODO: Delete these files on upgrade
|
// TODO: Delete these files on upgrade
|
||||||
public static final List<String> OBSOLETE_FILES = Collections.unmodifiableList(Arrays.asList(
|
public static final List<String> OBSOLETE_FILES = Collections.unmodifiableList(Arrays.asList(
|
||||||
"launches.log",
|
"launches.logTap",
|
||||||
"stats.log",
|
"stats.logTap",
|
||||||
"launcher.preferences",
|
"launcher.preferences",
|
||||||
"com.android.launcher3.compat.PackageInstallerCompatV16.queue"));
|
"com.android.launcher3.compat.PackageInstallerCompatV16.queue"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2012 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;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewParent;
|
|
||||||
|
|
||||||
import com.android.launcher3.config.ProviderConfig;
|
|
||||||
|
|
||||||
public class Stats {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implemented by containers to provide a launch source for a given child.
|
|
||||||
*/
|
|
||||||
public interface LaunchSourceProvider {
|
|
||||||
void fillInLaunchSourceData(View v, Bundle sourceData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helpers to add the source to a launch intent.
|
|
||||||
*/
|
|
||||||
public static class LaunchSourceUtils {
|
|
||||||
/**
|
|
||||||
* Create a default bundle for LaunchSourceProviders to fill in their data.
|
|
||||||
*/
|
|
||||||
public static Bundle createSourceData() {
|
|
||||||
Bundle sourceData = new Bundle();
|
|
||||||
sourceData.putString(SOURCE_EXTRA_CONTAINER, CONTAINER_HOMESCREEN);
|
|
||||||
// Have default container/sub container pages
|
|
||||||
sourceData.putInt(SOURCE_EXTRA_CONTAINER_PAGE, 0);
|
|
||||||
sourceData.putInt(SOURCE_EXTRA_SUB_CONTAINER_PAGE, 0);
|
|
||||||
return sourceData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds the next launch source provider in the parents of the view hierarchy and populates
|
|
||||||
* the source data from that provider.
|
|
||||||
*/
|
|
||||||
public static void populateSourceDataFromAncestorProvider(View v, Bundle sourceData) {
|
|
||||||
if (v == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Stats.LaunchSourceProvider provider = null;
|
|
||||||
ViewParent parent = v.getParent();
|
|
||||||
while (parent != null && parent instanceof View) {
|
|
||||||
if (parent instanceof Stats.LaunchSourceProvider) {
|
|
||||||
provider = (Stats.LaunchSourceProvider) parent;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
parent = parent.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (provider != null) {
|
|
||||||
provider.fillInLaunchSourceData(v, sourceData);
|
|
||||||
} else if (ProviderConfig.IS_DOGFOOD_BUILD) {
|
|
||||||
throw new RuntimeException("Expected LaunchSourceProvider");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final boolean DEBUG_BROADCASTS = false;
|
|
||||||
|
|
||||||
public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH";
|
|
||||||
public static final String EXTRA_INTENT = "intent";
|
|
||||||
public static final String EXTRA_CONTAINER = "container";
|
|
||||||
public static final String EXTRA_SCREEN = "screen";
|
|
||||||
public static final String EXTRA_CELLX = "cellX";
|
|
||||||
public static final String EXTRA_CELLY = "cellY";
|
|
||||||
public static final String EXTRA_SOURCE = "source";
|
|
||||||
|
|
||||||
public static final String SOURCE_EXTRA_CONTAINER = "container";
|
|
||||||
public static final String SOURCE_EXTRA_CONTAINER_PAGE = "container_page";
|
|
||||||
public static final String SOURCE_EXTRA_SUB_CONTAINER = "sub_container";
|
|
||||||
public static final String SOURCE_EXTRA_SUB_CONTAINER_PAGE = "sub_container_page";
|
|
||||||
|
|
||||||
public static final String CONTAINER_SEARCH_BOX = "search_box";
|
|
||||||
public static final String CONTAINER_ALL_APPS = "all_apps";
|
|
||||||
public static final String CONTAINER_HOMESCREEN = "homescreen"; // aka. Workspace
|
|
||||||
public static final String CONTAINER_HOTSEAT = "hotseat";
|
|
||||||
|
|
||||||
public static final String SUB_CONTAINER_FOLDER = "folder";
|
|
||||||
public static final String SUB_CONTAINER_ALL_APPS_A_Z = "a-z";
|
|
||||||
public static final String SUB_CONTAINER_ALL_APPS_PREDICTION = "prediction";
|
|
||||||
public static final String SUB_CONTAINER_ALL_APPS_SEARCH = "search";
|
|
||||||
|
|
||||||
private final Launcher mLauncher;
|
|
||||||
private final String mLaunchBroadcastPermission;
|
|
||||||
|
|
||||||
public Stats(Launcher launcher) {
|
|
||||||
mLauncher = launcher;
|
|
||||||
mLaunchBroadcastPermission =
|
|
||||||
launcher.getResources().getString(R.string.receive_launch_broadcasts_permission);
|
|
||||||
|
|
||||||
if (DEBUG_BROADCASTS) {
|
|
||||||
launcher.registerReceiver(
|
|
||||||
new BroadcastReceiver() {
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
Log.v("Stats", "got broadcast: " + intent + " for launched intent: "
|
|
||||||
+ intent.getStringExtra(EXTRA_INTENT));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new IntentFilter(ACTION_LAUNCH),
|
|
||||||
mLaunchBroadcastPermission,
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void recordLaunch(View v, Intent intent, ShortcutInfo shortcut) {
|
|
||||||
intent = new Intent(intent);
|
|
||||||
intent.setSourceBounds(null);
|
|
||||||
|
|
||||||
final String flat = intent.toUri(0);
|
|
||||||
Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat);
|
|
||||||
if (shortcut != null) {
|
|
||||||
broadcastIntent.putExtra(EXTRA_CONTAINER, shortcut.container)
|
|
||||||
.putExtra(EXTRA_SCREEN, shortcut.screenId)
|
|
||||||
.putExtra(EXTRA_CELLX, shortcut.cellX)
|
|
||||||
.putExtra(EXTRA_CELLY, shortcut.cellY);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bundle sourceExtras = LaunchSourceUtils.createSourceData();
|
|
||||||
LaunchSourceUtils.populateSourceDataFromAncestorProvider(v, sourceExtras);
|
|
||||||
broadcastIntent.putExtra(EXTRA_SOURCE, sourceExtras);
|
|
||||||
mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
|
|
||||||
if (intent.getComponent() != null) {
|
|
||||||
mLauncher.getLogger().logAppLaunch(intent.getComponent().getPackageName(), shortcut, sourceExtras);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,7 +39,6 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.Region.Op;
|
import android.graphics.Region.Op;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
@@ -73,6 +72,9 @@ import com.android.launcher3.dragndrop.DragView;
|
|||||||
import com.android.launcher3.dragndrop.SpringLoadedDragController;
|
import com.android.launcher3.dragndrop.SpringLoadedDragController;
|
||||||
import com.android.launcher3.folder.Folder;
|
import com.android.launcher3.folder.Folder;
|
||||||
import com.android.launcher3.folder.FolderIcon;
|
import com.android.launcher3.folder.FolderIcon;
|
||||||
|
import com.android.launcher3.logging.UserEventLogger;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
import com.android.launcher3.util.LongArrayMap;
|
import com.android.launcher3.util.LongArrayMap;
|
||||||
import com.android.launcher3.util.Thunk;
|
import com.android.launcher3.util.Thunk;
|
||||||
import com.android.launcher3.util.WallpaperOffsetInterpolator;
|
import com.android.launcher3.util.WallpaperOffsetInterpolator;
|
||||||
@@ -92,7 +94,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
public class Workspace extends PagedView
|
public class Workspace extends PagedView
|
||||||
implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
|
implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
|
||||||
DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
|
DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener,
|
||||||
Insettable, DropTargetSource, AccessibilityDragSource, Stats.LaunchSourceProvider {
|
Insettable, DropTargetSource, AccessibilityDragSource, UserEventLogger.LaunchSourceProvider {
|
||||||
private static final String TAG = "Launcher.Workspace";
|
private static final String TAG = "Launcher.Workspace";
|
||||||
|
|
||||||
private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
|
private static boolean ENFORCE_DRAG_EVENT_ORDER = false;
|
||||||
@@ -4264,9 +4266,12 @@ public class Workspace extends PagedView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fillInLaunchSourceData(View v, Bundle sourceData) {
|
public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOMESCREEN);
|
target.itemType = LauncherLogProto.APP_ICON;
|
||||||
sourceData.putInt(Stats.SOURCE_EXTRA_CONTAINER_PAGE, getCurrentPage());
|
target.gridX = info.cellX;
|
||||||
|
target.gridY = info.cellY;
|
||||||
|
target.pageIndex = getCurrentPage();
|
||||||
|
targetParent.containerType = LauncherLogProto.WORKSPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import android.content.Context;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -27,17 +26,19 @@ import android.view.View;
|
|||||||
import com.android.launcher3.BaseRecyclerView;
|
import com.android.launcher3.BaseRecyclerView;
|
||||||
import com.android.launcher3.BubbleTextView;
|
import com.android.launcher3.BubbleTextView;
|
||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
|
import com.android.launcher3.ItemInfo;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.Stats;
|
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
|
import com.android.launcher3.logging.UserEventLogger.LaunchSourceProvider;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A RecyclerView with custom fast scroll support for the all apps view.
|
* A RecyclerView with custom fast scroll support for the all apps view.
|
||||||
*/
|
*/
|
||||||
public class AllAppsRecyclerView extends BaseRecyclerView
|
public class AllAppsRecyclerView extends BaseRecyclerView
|
||||||
implements Stats.LaunchSourceProvider {
|
implements LaunchSourceProvider {
|
||||||
|
|
||||||
private AlphabeticalAppsList mApps;
|
private AlphabeticalAppsList mApps;
|
||||||
private AllAppsFastScrollHelper mFastScrollHelper;
|
private AllAppsFastScrollHelper mFastScrollHelper;
|
||||||
@@ -165,11 +166,9 @@ public class AllAppsRecyclerView extends BaseRecyclerView
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fillInLaunchSourceData(View v, Bundle sourceData) {
|
public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_ALL_APPS);
|
|
||||||
if (mApps.hasFilter()) {
|
if (mApps.hasFilter()) {
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
|
targetParent.containerType = LauncherLogProto.SEARCHRESULT;
|
||||||
Stats.SUB_CONTAINER_ALL_APPS_SEARCH);
|
|
||||||
} else {
|
} else {
|
||||||
if (v instanceof BubbleTextView) {
|
if (v instanceof BubbleTextView) {
|
||||||
BubbleTextView icon = (BubbleTextView) v;
|
BubbleTextView icon = (BubbleTextView) v;
|
||||||
@@ -178,14 +177,13 @@ public class AllAppsRecyclerView extends BaseRecyclerView
|
|||||||
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
|
List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
|
||||||
AlphabeticalAppsList.AdapterItem item = items.get(position);
|
AlphabeticalAppsList.AdapterItem item = items.get(position);
|
||||||
if (item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
|
if (item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) {
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
|
targetParent.containerType = LauncherLogProto.PREDICTION;
|
||||||
Stats.SUB_CONTAINER_ALL_APPS_PREDICTION);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER,
|
|
||||||
Stats.SUB_CONTAINER_ALL_APPS_A_Z);
|
targetParent.containerType = LauncherLogProto.ALLAPPS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import android.graphics.Point;
|
|||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.Selection;
|
import android.text.Selection;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
@@ -70,7 +69,6 @@ import com.android.launcher3.LogDecelerateInterpolator;
|
|||||||
import com.android.launcher3.OnAlarmListener;
|
import com.android.launcher3.OnAlarmListener;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.ShortcutInfo;
|
import com.android.launcher3.ShortcutInfo;
|
||||||
import com.android.launcher3.Stats;
|
|
||||||
import com.android.launcher3.UninstallDropTarget.DropTargetSource;
|
import com.android.launcher3.UninstallDropTarget.DropTargetSource;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.Workspace.ItemOperator;
|
import com.android.launcher3.Workspace.ItemOperator;
|
||||||
@@ -79,6 +77,9 @@ import com.android.launcher3.config.FeatureFlags;
|
|||||||
import com.android.launcher3.dragndrop.DragController;
|
import com.android.launcher3.dragndrop.DragController;
|
||||||
import com.android.launcher3.dragndrop.DragController.DragListener;
|
import com.android.launcher3.dragndrop.DragController.DragListener;
|
||||||
import com.android.launcher3.dragndrop.DragLayer;
|
import com.android.launcher3.dragndrop.DragLayer;
|
||||||
|
import com.android.launcher3.logging.UserEventLogger.LaunchSourceProvider;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
import com.android.launcher3.util.Thunk;
|
import com.android.launcher3.util.Thunk;
|
||||||
import com.android.launcher3.util.UiThreadCircularReveal;
|
import com.android.launcher3.util.UiThreadCircularReveal;
|
||||||
|
|
||||||
@@ -92,7 +93,7 @@ import java.util.Comparator;
|
|||||||
public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
|
public class Folder extends LinearLayout implements DragSource, View.OnClickListener,
|
||||||
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
|
View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener,
|
||||||
View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource,
|
View.OnFocusChangeListener, DragListener, DropTargetSource, AccessibilityDragSource,
|
||||||
Stats.LaunchSourceProvider {
|
LaunchSourceProvider {
|
||||||
private static final String TAG = "Launcher.Folder";
|
private static final String TAG = "Launcher.Folder";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1416,11 +1417,12 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fillInLaunchSourceData(View v, Bundle sourceData) {
|
public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
|
||||||
// Fill in from the folder icon's launch source provider first
|
target.itemType = LauncherLogProto.APP_ICON;
|
||||||
Stats.LaunchSourceUtils.populateSourceDataFromAncestorProvider(mFolderIcon, sourceData);
|
target.gridX = info.cellX;
|
||||||
sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, Stats.SUB_CONTAINER_FOLDER);
|
target.gridY = info.cellY;
|
||||||
sourceData.putInt(Stats.SOURCE_EXTRA_SUB_CONTAINER_PAGE, mContent.getCurrentPage());
|
target.pageIndex = mContent.getCurrentPage();
|
||||||
|
targetParent.containerType = LauncherLogProto.FOLDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class OnScrollHintListener implements OnAlarmListener {
|
private class OnScrollHintListener implements OnAlarmListener {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.ShortcutInfo;
|
import com.android.launcher3.ShortcutInfo;
|
||||||
import com.android.launcher3.Stats;
|
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
@@ -18,16 +17,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
|||||||
*/
|
*/
|
||||||
public class LoggerUtils {
|
public class LoggerUtils {
|
||||||
private static final String TAG = "LoggerUtils";
|
private static final String TAG = "LoggerUtils";
|
||||||
private static final boolean DEBUG = false;
|
|
||||||
|
|
||||||
static int getContainerType(ShortcutInfo shortcut) {
|
|
||||||
switch ((int) shortcut.container) {
|
|
||||||
case LauncherSettings.Favorites.CONTAINER_DESKTOP: return LauncherLogProto.WORKSPACE;
|
|
||||||
case LauncherSettings.Favorites.CONTAINER_HOTSEAT: return LauncherLogProto.HOTSEAT;
|
|
||||||
default:
|
|
||||||
return (int) shortcut.container;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getActionStr(LauncherLogProto.Action action) {
|
public static String getActionStr(LauncherLogProto.Action action) {
|
||||||
switch(action.touch) {
|
switch(action.touch) {
|
||||||
@@ -62,8 +51,10 @@ public class LoggerUtils {
|
|||||||
default: typeStr = "UNKNOWN";
|
default: typeStr = "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|
||||||
return typeStr + " " + t.packageNameHash + " grid=(" + t.gridX + "," + t.gridY + ") "
|
return typeStr + ", packageHash=" + t.packageNameHash
|
||||||
+ getContainerStr(t.parent);
|
+ ", componentHash=" + t.componentHash
|
||||||
|
+ ", intentHash=" + t.intentHash
|
||||||
|
+ ", grid=(" + t.gridX + "," + t.gridY + "), id=" + t.pageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getControlStr(Target t) {
|
private static String getControlStr(Target t) {
|
||||||
@@ -76,7 +67,6 @@ public class LoggerUtils {
|
|||||||
case LauncherLogProto.UNINSTALL_TARGET: return "UNINSTALL_TARGET";
|
case LauncherLogProto.UNINSTALL_TARGET: return "UNINSTALL_TARGET";
|
||||||
case LauncherLogProto.APPINFO_TARGET: return "APPINFO_TARGET";
|
case LauncherLogProto.APPINFO_TARGET: return "APPINFO_TARGET";
|
||||||
case LauncherLogProto.RESIZE_HANDLE: return "RESIZE_HANDLE";
|
case LauncherLogProto.RESIZE_HANDLE: return "RESIZE_HANDLE";
|
||||||
case LauncherLogProto.FAST_SCROLL_HANDLE: return "FAST_SCROLL_HANDLE";
|
|
||||||
default: return "UNKNOWN";
|
default: return "UNKNOWN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,4 +104,22 @@ public class LoggerUtils {
|
|||||||
}
|
}
|
||||||
return str + " id=" + t.pageIndex;
|
return str + " id=" + t.pageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static LauncherLogProto.LauncherEvent initLauncherEvent(
|
||||||
|
int actionType,
|
||||||
|
int childTargetType,
|
||||||
|
int parentTargetType){
|
||||||
|
LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent();
|
||||||
|
|
||||||
|
event.srcTarget = new LauncherLogProto.Target[2];
|
||||||
|
event.srcTarget[0] = new LauncherLogProto.Target();
|
||||||
|
event.srcTarget[0].type = childTargetType;
|
||||||
|
event.srcTarget[1] = new LauncherLogProto.Target();
|
||||||
|
event.srcTarget[1].type = parentTargetType;
|
||||||
|
|
||||||
|
event.action = new LauncherLogProto.Action();
|
||||||
|
event.action.type = actionType;
|
||||||
|
return event;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +1,182 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2012 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;
|
package com.android.launcher3.logging;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewParent;
|
||||||
|
|
||||||
import com.android.launcher3.ShortcutInfo;
|
import com.android.launcher3.ItemInfo;
|
||||||
import com.android.launcher3.Stats;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.config.FeatureFlags;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
|
import com.android.launcher3.util.ComponentKey;
|
||||||
|
|
||||||
import java.util.Locale;
|
import com.google.protobuf.nano.MessageNano;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public abstract class UserEventLogger {
|
public abstract class UserEventLogger {
|
||||||
|
|
||||||
|
private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5;
|
||||||
|
/**
|
||||||
|
* Implemented by containers to provide a launch source for a given child.
|
||||||
|
*/
|
||||||
|
public interface LaunchSourceProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies data from the source to the destination proto.
|
||||||
|
* @param v source of the data
|
||||||
|
* @param info source of the data
|
||||||
|
* @param target dest of the data
|
||||||
|
* @param targetParent dest of the data
|
||||||
|
*/
|
||||||
|
void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively finds the parent of the given child which implements IconLogInfoProvider
|
||||||
|
*/
|
||||||
|
public static LaunchSourceProvider getLaunchProviderRecursive(View v) {
|
||||||
|
ViewParent parent = null;
|
||||||
|
if (v != null) {
|
||||||
|
parent = v.getParent();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optimization to only check up to 5 parents.
|
||||||
|
int count = MAXIMUM_VIEW_HIERARCHY_LEVEL;
|
||||||
|
while (parent != null && count-- > 0) {
|
||||||
|
if (parent instanceof LaunchSourceProvider) {
|
||||||
|
return (LaunchSourceProvider) parent;
|
||||||
|
} else {
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private String TAG = "UserEventLogger";
|
private String TAG = "UserEventLogger";
|
||||||
private boolean DEBUG = false;
|
private static final boolean DEBUG_BROADCASTS = true;
|
||||||
|
|
||||||
|
public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH";
|
||||||
|
public static final String EXTRA_INTENT = "intent";;
|
||||||
|
public static final String EXTRA_SOURCE = "source";
|
||||||
|
|
||||||
|
private final Launcher mLauncher;
|
||||||
|
private final String mLaunchBroadcastPermission;
|
||||||
|
|
||||||
private long mElapsedContainerMillis;
|
private long mElapsedContainerMillis;
|
||||||
private long mElapsedSessionMillis;
|
private long mElapsedSessionMillis;
|
||||||
private long mActionDurationMillis;
|
private long mActionDurationMillis;
|
||||||
|
|
||||||
|
// Used for filling in predictedRank on {@link Target}s.
|
||||||
|
private List<ComponentKey> mPredictedApps;
|
||||||
|
|
||||||
public final void logAppLaunch(String provider, ShortcutInfo shortcut, Bundle bundle) {
|
public UserEventLogger(Launcher launcher) {
|
||||||
if (FeatureFlags.LAUNCHER3_LEGACY_LOGGING) return;
|
mLauncher = launcher;
|
||||||
|
mLaunchBroadcastPermission =
|
||||||
|
launcher.getResources().getString(R.string.receive_launch_broadcasts_permission);
|
||||||
|
|
||||||
LauncherLogProto.LauncherEvent event = new LauncherLogProto.LauncherEvent();
|
if (DEBUG_BROADCASTS) {
|
||||||
event.action = new LauncherLogProto.Action();
|
launcher.registerReceiver(
|
||||||
event.action.type = LauncherLogProto.Action.TOUCH;
|
new BroadcastReceiver() {
|
||||||
event.action.touch = LauncherLogProto.Action.TAP;
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
event.srcTarget = new LauncherLogProto.Target();
|
Log.v(TAG, "got broadcast: " + intent + " for launched intent: "
|
||||||
event.srcTarget.type = LauncherLogProto.Target.ITEM;
|
+ intent.getStringExtra(EXTRA_INTENT));
|
||||||
event.srcTarget.itemType = LauncherLogProto.APP_ICON;
|
}
|
||||||
// TODO: package hash name should be different per device.
|
},
|
||||||
event.srcTarget.packageNameHash = provider.hashCode();
|
new IntentFilter(ACTION_LAUNCH),
|
||||||
|
mLaunchBroadcastPermission,
|
||||||
event.srcTarget.parent = new LauncherLogProto.Target();
|
null
|
||||||
String subContainer = bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER);
|
);
|
||||||
|
|
||||||
if (shortcut != null) {
|
|
||||||
event.srcTarget.parent.containerType = LoggerUtils.getContainerType(shortcut);
|
|
||||||
event.srcTarget.pageIndex = (int) shortcut.screenId;
|
|
||||||
event.srcTarget.gridX = shortcut.cellX;
|
|
||||||
event.srcTarget.gridX = shortcut.cellY;
|
|
||||||
}
|
}
|
||||||
if (subContainer != null) {
|
}
|
||||||
event.srcTarget.parent.type = LauncherLogProto.Target.CONTAINER;
|
|
||||||
if (subContainer.equals(Stats.SUB_CONTAINER_FOLDER)) {
|
|
||||||
event.srcTarget.parent.containerType = LauncherLogProto.FOLDER;
|
|
||||||
} else if (subContainer.equals(Stats.SUB_CONTAINER_ALL_APPS_A_Z)) {
|
|
||||||
event.srcTarget.parent.containerType = LauncherLogProto.ALLAPPS;
|
|
||||||
} else if (subContainer.equals(Stats.CONTAINER_HOTSEAT)) {
|
|
||||||
event.srcTarget.parent.containerType = LauncherLogProto.HOTSEAT;
|
|
||||||
} else if (subContainer.equals(Stats.SUB_CONTAINER_ALL_APPS_PREDICTION)) {
|
|
||||||
event.srcTarget.parent.containerType = LauncherLogProto.PREDICTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG) {
|
// APP_ICON SHORTCUT WIDGET
|
||||||
Log.d(TAG, String.format("parent bundle: %s %s %s %s",
|
// --------------------------------------------------------------
|
||||||
bundle.getString(Stats.SOURCE_EXTRA_CONTAINER),
|
// packageNameHash required optional required
|
||||||
bundle.getString(Stats.SOURCE_EXTRA_CONTAINER_PAGE),
|
// componentNameHash required required
|
||||||
bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER),
|
// intentHash required
|
||||||
bundle.getString(Stats.SOURCE_EXTRA_SUB_CONTAINER_PAGE)));
|
// --------------------------------------------------------------
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Prepare {@link LauncherEvent} and {@link Intent} and then attach the event
|
||||||
|
* to the intent and then broadcast.
|
||||||
|
*/
|
||||||
|
public final void broadcastEvent(LauncherEvent ev, Intent intent) {
|
||||||
|
intent = new Intent(intent);
|
||||||
|
intent.setSourceBounds(null);
|
||||||
|
|
||||||
|
final String flat = intent.toUri(0);
|
||||||
|
Intent broadcastIntent = new Intent(ACTION_LAUNCH).putExtra(EXTRA_INTENT, flat);
|
||||||
|
|
||||||
|
broadcastIntent.putExtra(EXTRA_SOURCE, MessageNano.toByteArray(ev));
|
||||||
|
String[] packages = ((Context)mLauncher).getResources().getStringArray(R.array.launch_broadcast_targets);
|
||||||
|
for(String p: packages) {
|
||||||
|
broadcastIntent.setPackage(p);
|
||||||
|
mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void logLaunch(View v, Intent intent) {
|
||||||
|
LauncherEvent event = LoggerUtils.initLauncherEvent(
|
||||||
|
Action.TOUCH, Target.ITEM, Target.CONTAINER);
|
||||||
|
event.action.touch = Action.TAP;
|
||||||
|
|
||||||
|
// Fill in grid(x,y), pageIndex of the child and container type of the parent
|
||||||
|
// TODO: make this percolate up the view hierarchy if needed.
|
||||||
|
int idx = 0;
|
||||||
|
LaunchSourceProvider provider = getLaunchProviderRecursive(v);
|
||||||
|
provider.fillInLaunchSourceData(v, (ItemInfo) v.getTag(), event.srcTarget[idx], event.srcTarget[idx + 1]);
|
||||||
|
|
||||||
|
// TODO: Fill in all the hashes and the predictedRank
|
||||||
|
|
||||||
|
// Fill in the duration of time spent navigating in Launcher and the container.
|
||||||
event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
|
event.elapsedContainerMillis = System.currentTimeMillis() - mElapsedContainerMillis;
|
||||||
event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
|
event.elapsedSessionMillis = System.currentTimeMillis() - mElapsedSessionMillis;
|
||||||
processEvent(event);
|
processEvent(event);
|
||||||
|
|
||||||
|
broadcastEvent(event, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logTap(View v) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logLongPress() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public void logDragNDrop() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPredictedApps(List<ComponentKey> predictedApps) {
|
||||||
|
mPredictedApps = predictedApps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,25 +184,22 @@ public abstract class UserEventLogger {
|
|||||||
*/
|
*/
|
||||||
public final void resetElapsedContainerMillis() {
|
public final void resetElapsedContainerMillis() {
|
||||||
mElapsedContainerMillis = System.currentTimeMillis();
|
mElapsedContainerMillis = System.currentTimeMillis();
|
||||||
if(DEBUG) {
|
|
||||||
Log.d(TAG, "resetElapsedContainerMillis " + mElapsedContainerMillis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void resetElapsedSessionMillis() {
|
public final void resetElapsedSessionMillis() {
|
||||||
mElapsedSessionMillis = System.currentTimeMillis();
|
mElapsedSessionMillis = System.currentTimeMillis();
|
||||||
mElapsedContainerMillis = System.currentTimeMillis();
|
mElapsedContainerMillis = System.currentTimeMillis();
|
||||||
if(DEBUG) {
|
|
||||||
Log.d(TAG, "resetElapsedSessionMillis " + mElapsedSessionMillis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void resetActionDurationMillis() {
|
public final void resetActionDurationMillis() {
|
||||||
mActionDurationMillis = System.currentTimeMillis();
|
mActionDurationMillis = System.currentTimeMillis();
|
||||||
if(DEBUG) {
|
|
||||||
Log.d(TAG, "resetElapsedContainerMillis " + mElapsedContainerMillis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void processEvent(LauncherLogProto.LauncherEvent ev);
|
public abstract void processEvent(LauncherLogProto.LauncherEvent ev);
|
||||||
}
|
|
||||||
|
public int getPredictedRank(ComponentKey key) {
|
||||||
|
if (mPredictedApps == null) return -1;
|
||||||
|
return mPredictedApps.indexOf(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.android.launcher3.testing;
|
package com.android.launcher3.testing;
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
@@ -12,9 +11,8 @@ import android.widget.FrameLayout;
|
|||||||
import com.android.launcher3.AppInfo;
|
import com.android.launcher3.AppInfo;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.LauncherCallbacks;
|
import com.android.launcher3.LauncherCallbacks;
|
||||||
import com.android.launcher3.compat.UserHandleCompat;
|
|
||||||
import com.android.launcher3.logging.UserEventLogger;
|
|
||||||
import com.android.launcher3.allapps.AllAppsSearchBarController;
|
import com.android.launcher3.allapps.AllAppsSearchBarController;
|
||||||
|
import com.android.launcher3.logging.UserEventLogger;
|
||||||
import com.android.launcher3.util.ComponentKey;
|
import com.android.launcher3.util.ComponentKey;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
|
|||||||
Reference in New Issue
Block a user