From 8f1eff7b6cc8621888ee46605c32e601f80a890b Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Thu, 28 May 2015 17:33:40 -0700 Subject: Adding context for app launches. Bug: 21492784 Change-Id: I1b28ac8f44498e1d9770e770b074f19c721c3f10 --- src/com/android/launcher3/BubbleTextView.java | 2 - src/com/android/launcher3/Folder.java | 14 +++- src/com/android/launcher3/Hotseat.java | 10 ++- src/com/android/launcher3/Launcher.java | 14 +--- src/com/android/launcher3/LauncherCallbacks.java | 2 + src/com/android/launcher3/Stats.java | 80 ++++++++++++++++++++-- src/com/android/launcher3/Workspace.java | 10 ++- .../launcher3/allapps/AllAppsContainerView.java | 13 +++- .../launcher3/allapps/AllAppsRecyclerView.java | 18 ++++- .../launcher3/allapps/AlphabeticalAppsList.java | 10 +++ 10 files changed, 147 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index edf502112..240f7c03f 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -28,7 +28,6 @@ import android.graphics.Region; import android.graphics.drawable.Drawable; import android.os.Build; import android.util.AttributeSet; -import android.util.Log; import android.util.SparseArray; import android.util.TypedValue; import android.view.KeyEvent; @@ -36,7 +35,6 @@ import android.view.MotionEvent; import android.view.ViewConfiguration; import android.view.ViewParent; import android.widget.TextView; - import com.android.launcher3.IconCache.IconLoadRequest; import com.android.launcher3.model.PackageItemInfo; diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java index fcfb717ab..94f8fc875 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -29,6 +29,7 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.os.Build; +import android.os.Bundle; import android.text.InputType; import android.text.Selection; import android.text.Spannable; @@ -66,7 +67,8 @@ import java.util.Collections; */ public class Folder extends LinearLayout implements DragSource, View.OnClickListener, View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener, - View.OnFocusChangeListener, DragListener, UninstallSource, AccessibilityDragSource { + View.OnFocusChangeListener, DragListener, UninstallSource, AccessibilityDragSource, + Stats.LaunchSourceProvider { private static final String TAG = "Launcher.Folder"; /** @@ -923,7 +925,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList View v = list.get(i); ItemInfo info = (ItemInfo) v.getTag(); LauncherModel.addItemToDatabase(mLauncher, info, mInfo.id, 0, - info.cellX, info.cellY); + info.cellX, info.cellY); } } @@ -1338,6 +1340,14 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList outRect.right += mScrollAreaOffset; } + @Override + public void fillInLaunchSourceData(Bundle sourceData) { + // Fill in from the folder icon's launch source provider first + Stats.LaunchSourceUtils.populateSourceDataFromAncestorProvider(mFolderIcon, sourceData); + sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, Stats.SUB_CONTAINER_FOLDER); + sourceData.putInt(Stats.SOURCE_EXTRA_SUB_CONTAINER_PAGE, mContent.getCurrentPage()); + } + private class OnScrollHintListener implements OnAlarmListener { private final DragObject mDragObject; diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index ce33164fa..6f097449c 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -19,15 +19,16 @@ package com.android.launcher3; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; -import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.widget.FrameLayout; import android.widget.TextView; -public class Hotseat extends FrameLayout { +public class Hotseat extends FrameLayout + implements Stats.LaunchSourceProvider{ private CellLayout mContent; @@ -160,4 +161,9 @@ public class Hotseat extends FrameLayout { } return false; } + + @Override + public void fillInLaunchSourceData(Bundle sourceData) { + sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOTSEAT); + } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2ff6adc99..867a6e71d 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1531,7 +1531,6 @@ public class Launcher extends Activity * Add a shortcut to the workspace. * * @param data The intent describing the shortcut. - * @param cellInfo The position on screen where to create the shortcut. */ private void completeAddShortcut(Intent data, long container, long screenId, int cellX, int cellY) { @@ -2549,13 +2548,6 @@ public class Launcher extends Activity } } - public void onClickPagedViewIcon(View v) { - startAppShortcutOrInfoActivity(v); - if (mLauncherCallbacks != null) { - mLauncherCallbacks.onClickPagedViewIcon(v); - } - } - @SuppressLint("ClickableViewAccessibility") public boolean onTouch(View v, MotionEvent event) { return false; @@ -2714,7 +2706,7 @@ public class Launcher extends Activity } boolean success = startActivitySafely(v, intent, tag); - mStats.recordLaunch(intent, shortcut); + mStats.recordLaunch(v, intent, shortcut); if (success && v instanceof BubbleTextView) { mWaitingForResume = (BubbleTextView) v; @@ -2936,7 +2928,7 @@ public class Launcher extends Activity } } - boolean startActivity(View v, Intent intent, Object tag) { + private boolean startActivity(View v, Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { // Only launch using the new animation if the shortcut has not opted out (this is a @@ -3007,7 +2999,7 @@ public class Launcher extends Activity return false; } - boolean startActivitySafely(View v, Intent intent, Object tag) { + private boolean startActivitySafely(View v, Intent intent, Object tag) { boolean success = false; if (mIsSafeModeEnabled && !Utilities.isSystemApp(this, intent)) { Toast.makeText(this, R.string.safemode_shortcut_error, Toast.LENGTH_SHORT).show(); diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java index a5f36ba93..70e400bca 100644 --- a/src/com/android/launcher3/LauncherCallbacks.java +++ b/src/com/android/launcher3/LauncherCallbacks.java @@ -56,6 +56,8 @@ public interface LauncherCallbacks { public void bindAllApplications(ArrayList apps); public void onClickFolderIcon(View v); public void onClickAppShortcut(View v); + + @Deprecated public void onClickPagedViewIcon(View v); public void onClickWallpaperPicker(View v); public void onClickSettingsButton(View v); diff --git a/src/com/android/launcher3/Stats.java b/src/com/android/launcher3/Stats.java index 9d06f755f..cb0e252b2 100644 --- a/src/com/android/launcher3/Stats.java +++ b/src/com/android/launcher3/Stats.java @@ -20,9 +20,63 @@ 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; public class Stats { + + /** + * Implemented by containers to provide a launch source for a given child. + */ + public interface LaunchSourceProvider { + void fillInLaunchSourceData(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(sourceData); + } else if (LauncherAppState.isDogfoodBuild()) { + throw new RuntimeException("Expected LaunchSourceProvider"); + } + } + } + private static final boolean DEBUG_BROADCASTS = false; public static final String ACTION_LAUNCH = "com.android.launcher3.action.LAUNCH"; @@ -31,6 +85,22 @@ public class Stats { 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; @@ -56,11 +126,7 @@ public class Stats { } } - public void recordLaunch(Intent intent) { - recordLaunch(intent, null); - } - - public void recordLaunch(Intent intent, ShortcutInfo shortcut) { + public void recordLaunch(View v, Intent intent, ShortcutInfo shortcut) { intent = new Intent(intent); intent.setSourceBounds(null); @@ -72,6 +138,10 @@ public class Stats { .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); } } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 6d5affb59..193a0af6f 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -28,6 +28,7 @@ import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Resources; import android.content.res.TypedArray; @@ -42,6 +43,7 @@ import android.graphics.Region.Op; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Build; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Parcelable; @@ -86,7 +88,7 @@ import java.util.concurrent.atomic.AtomicInteger; public class Workspace extends PagedView implements DropTarget, DragSource, DragScroller, View.OnTouchListener, DragController.DragListener, LauncherTransitionable, ViewGroup.OnHierarchyChangeListener, - Insettable, UninstallSource, AccessibilityDragSource { + Insettable, UninstallSource, AccessibilityDragSource, Stats.LaunchSourceProvider { private static final String TAG = "Launcher.Workspace"; private static boolean ENFORCE_DRAG_EVENT_ORDER = false; @@ -4461,6 +4463,12 @@ public class Workspace extends PagedView mLauncher.getDragLayer().getLocationInDragLayer(this, loc); } + @Override + public void fillInLaunchSourceData(Bundle sourceData) { + sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_HOMESCREEN); + sourceData.putInt(Stats.SOURCE_EXTRA_CONTAINER_PAGE, getCurrentPage()); + } + /** * Used as a workaround to ensure that the AppWidgetService receives the * PACKAGE_ADDED broadcast before updating widgets. diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 84a6462e5..9386500be 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -26,6 +26,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.graphics.drawable.InsetDrawable; import android.os.Build; +import android.os.Bundle; import android.support.v7.widget.RecyclerView; import android.text.Editable; import android.text.TextWatcher; @@ -57,6 +58,7 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherTransitionable; import com.android.launcher3.R; +import com.android.launcher3.Stats; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace; import com.android.launcher3.allapps.AppSearchManager.AppSearchResultCallback; @@ -172,7 +174,7 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable, AlphabeticalAppsList.AdapterChangedCallback, AllAppsGridAdapter.PredictionBarSpacerCallbacks, View.OnTouchListener, View.OnClickListener, View.OnLongClickListener, - ViewTreeObserver.OnPreDrawListener, AppSearchResultCallback { + ViewTreeObserver.OnPreDrawListener, AppSearchResultCallback, Stats.LaunchSourceProvider { public static final boolean GRID_MERGE_SECTIONS = true; @@ -870,6 +872,15 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc return false; } + @Override + public void fillInLaunchSourceData(Bundle sourceData) { + // Since the other cases are caught by the AllAppsRecyclerView LaunchSourceProvider, we just + // handle the prediction bar icons here + sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_ALL_APPS); + sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, + Stats.SUB_CONTAINER_ALL_APPS_PREDICTION); + } + /** * Returns the predicted app in the prediction bar given a set of local coordinates. */ diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java index cc5add3b2..e1b5d918e 100644 --- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java +++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java @@ -18,14 +18,15 @@ package com.android.launcher3.allapps; import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; +import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; - import com.android.launcher3.BaseRecyclerView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; +import com.android.launcher3.Stats; import com.android.launcher3.Utilities; import java.util.List; @@ -33,7 +34,8 @@ import java.util.List; /** * 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 { private AlphabeticalAppsList mApps; private int mNumAppsPerRow; @@ -125,6 +127,18 @@ public class AllAppsRecyclerView extends BaseRecyclerView { addOnItemTouchListener(this); } + @Override + public void fillInLaunchSourceData(Bundle sourceData) { + sourceData.putString(Stats.SOURCE_EXTRA_CONTAINER, Stats.CONTAINER_ALL_APPS); + if (mApps.hasFilter()) { + sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, + Stats.SUB_CONTAINER_ALL_APPS_SEARCH); + } else { + sourceData.putString(Stats.SOURCE_EXTRA_SUB_CONTAINER, + Stats.SUB_CONTAINER_ALL_APPS_A_Z); + } + } + /** * Maps the touch (from 0..1) to the adapter position that should be visible. */ diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 725616fb3..f4d02a1c9 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -46,6 +46,7 @@ public class AlphabeticalAppsList { public static final String TAG = "AlphabeticalAppsList"; private static final boolean DEBUG = false; + private static final boolean DEBUG_PREDICTIONS = false; /** * Info about a section in the alphabetic list @@ -477,6 +478,15 @@ public class AlphabeticalAppsList { mAdapterItems.clear(); mSections.clear(); + if (DEBUG_PREDICTIONS) { + if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) { + mPredictedAppComponents.add(mApps.get(0).componentName); + mPredictedAppComponents.add(mApps.get(0).componentName); + mPredictedAppComponents.add(mApps.get(0).componentName); + mPredictedAppComponents.add(mApps.get(0).componentName); + } + } + // Process the predicted app components mPredictedApps.clear(); if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { -- cgit v1.2.3