Decouple feature flag and predictions am: 685e29b236

Change-Id: I97a7ababd83371b4876c2c3119cea20e8cc5070c
This commit is contained in:
Samuel Fufa
2020-05-07 18:32:18 +00:00
committed by Automerger Merge Worker
4 changed files with 39 additions and 58 deletions
@@ -48,6 +48,7 @@ import com.android.launcher3.views.Snackbar;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.IntStream;
/** /**
* Controller class for managing user onboaridng flow for hybrid hotseat * Controller class for managing user onboaridng flow for hybrid hotseat
@@ -110,7 +111,8 @@ public class HotseatEduController {
ItemInfo info = (ItemInfo) view.getTag(); ItemInfo info = (ItemInfo) view.getTag();
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) { if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
folders.add((FolderInfo) info); folders.add((FolderInfo) info);
} else if (info instanceof WorkspaceItemInfo) { } else if (info instanceof WorkspaceItemInfo && info.container == LauncherSettings
.Favorites.CONTAINER_HOTSEAT) {
putIntoFolder.add((WorkspaceItemInfo) info); putIntoFolder.add((WorkspaceItemInfo) info);
} }
} }
@@ -206,6 +208,7 @@ public class HotseatEduController {
View child = mHotseat.getChildAt(i, 0); View child = mHotseat.getChildAt(i, 0);
if (child == null || child.getTag() == null) continue; if (child == null || child.getTag() == null) continue;
ItemInfo tag = (ItemInfo) child.getTag(); ItemInfo tag = (ItemInfo) child.getTag();
if (tag.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) continue;
mLauncher.getModelWriter().moveItemInDatabase(tag, mLauncher.getModelWriter().moveItemInDatabase(tag,
LauncherSettings.Favorites.CONTAINER_DESKTOP, pageId, i, toRow); LauncherSettings.Favorites.CONTAINER_DESKTOP, pageId, i, toRow);
mNewItems.add(tag); mNewItems.add(tag);
@@ -300,13 +303,23 @@ public class HotseatEduController {
} }
void showEdu() { void showEdu() {
int childCount = mHotseat.getShortcutsAndWidgets().getChildCount();
CellLayout cellLayout = mLauncher.getWorkspace().getScreenWithId(Workspace.FIRST_SCREEN_ID);
// hotseat is already empty and does not require migration. show edu tip // hotseat is already empty and does not require migration. show edu tip
if (mHotseat.getShortcutsAndWidgets().getChildCount() == 0) { boolean requiresMigration = IntStream.range(0, childCount).anyMatch(i -> {
new ArrowTipView(mLauncher).show(mLauncher.getString(R.string.hotseat_auto_enrolled), View v = mHotseat.getShortcutsAndWidgets().getChildAt(i);
return v != null && v.getTag() != null && ((ItemInfo) v.getTag()).container
!= LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
});
boolean canMigrateToFirstPage = cellLayout.makeSpaceForHotseatMigration(false);
if (requiresMigration && canMigrateToFirstPage) {
showDialog();
} else {
new ArrowTipView(mLauncher).show(mLauncher.getString(
requiresMigration ? R.string.hotseat_tip_no_empty_slots
: R.string.hotseat_auto_enrolled),
mHotseat.getTop()); mHotseat.getTop());
finishOnboarding(); finishOnboarding();
} else {
showDialog();
} }
} }
@@ -16,9 +16,6 @@
package com.android.launcher3.hybridhotseat; package com.android.launcher3.hybridhotseat;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.logging.LoggerUtils.newAction;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
@@ -32,7 +29,6 @@ import android.app.prediction.AppTargetId;
import android.content.ComponentName; import android.content.ComponentName;
import android.os.Bundle; import android.os.Bundle;
import android.os.Process; import android.os.Process;
import android.provider.DeviceConfig;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@@ -60,7 +56,6 @@ import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.IconCache;
import com.android.launcher3.logging.FileLog; import com.android.launcher3.logging.FileLog;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfo;
@@ -70,12 +65,12 @@ import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.uioverrides.DeviceFlag;
import com.android.launcher3.uioverrides.PredictedAppIcon; import com.android.launcher3.uioverrides.PredictedAppIcon;
import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.ComponentKey;
import java.lang.ref.WeakReference;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -155,9 +150,9 @@ public class HotseatPredictionController implements DragController.DragListener,
} }
/** /**
* Returns whether or not the prediction controller is ready to show predictions * Returns whether or not user has seen hybrid hotseat education
*/ */
public boolean isReady() { public boolean isEduSeen() {
return mLauncher.getSharedPrefs().getBoolean(HotseatEduController.KEY_HOTSEAT_EDU_SEEN, return mLauncher.getSharedPrefs().getBoolean(HotseatEduController.KEY_HOTSEAT_EDU_SEEN,
false); false);
} }
@@ -186,7 +181,7 @@ public class HotseatPredictionController implements DragController.DragListener,
} }
private void fillGapsWithPrediction(boolean animate, Runnable callback) { private void fillGapsWithPrediction(boolean animate, Runnable callback) {
if (!isReady() || mUIUpdatePaused || mDragObject != null) { if (mUIUpdatePaused || mDragObject != null) {
return; return;
} }
List<WorkspaceItemInfo> predictedApps = mapToWorkspaceItemInfo(mComponentKeyMappers); List<WorkspaceItemInfo> predictedApps = mapToWorkspaceItemInfo(mComponentKeyMappers);
@@ -262,6 +257,10 @@ public class HotseatPredictionController implements DragController.DragListener,
if (mAppPredictor != null) { if (mAppPredictor != null) {
mAppPredictor.destroy(); mAppPredictor.destroy();
} }
if (mHotseatEduController != null) {
mHotseatEduController.destroy();
mHotseatEduController = null;
}
} }
/** /**
@@ -291,11 +290,16 @@ public class HotseatPredictionController implements DragController.DragListener,
.setPredictedTargetCount(mHotSeatItemsCount) .setPredictedTargetCount(mHotSeatItemsCount)
.setExtras(getAppPredictionContextExtra()) .setExtras(getAppPredictionContextExtra())
.build()); .build());
mAppPredictor.registerPredictionUpdates(mLauncher.getMainExecutor(), WeakReference<HotseatPredictionController> controllerRef = new WeakReference<>(this);
this::setPredictedApps); mAppPredictor.registerPredictionUpdates(mLauncher.getApplicationContext().getMainExecutor(),
list -> {
if (controllerRef.get() != null) {
controllerRef.get().setPredictedApps(list);
}
});
setPauseUIUpdate(false); setPauseUIUpdate(false);
performBetaCheck(); if (!isEduSeen()) {
if (!isReady()) {
mHotseatEduController = new HotseatEduController(mLauncher, this::createPredictor); mHotseatEduController = new HotseatEduController(mLauncher, this::createPredictor);
} }
mAppPredictor.requestPredictionUpdate(); mAppPredictor.requestPredictionUpdate();
@@ -386,9 +390,8 @@ public class HotseatPredictionController implements DragController.DragListener,
predictionLog.append("]"); predictionLog.append("]");
if (Utilities.IS_DEBUG_DEVICE) FileLog.d(TAG, predictionLog.toString()); if (Utilities.IS_DEBUG_DEVICE) FileLog.d(TAG, predictionLog.toString());
updateDependencies(); updateDependencies();
if (isReady()) {
fillGapsWithPrediction(); fillGapsWithPrediction();
} else if (mHotseatEduController != null) { if (!isEduSeen() && mHotseatEduController != null) {
mHotseatEduController.setPredictedApps(mapToWorkspaceItemInfo(mComponentKeyMappers)); mHotseatEduController.setPredictedApps(mapToWorkspaceItemInfo(mComponentKeyMappers));
} }
// should invalidate cache if AiAi sends empty list of AppTargets // should invalidate cache if AiAi sends empty list of AppTargets
@@ -682,42 +685,6 @@ public class HotseatPredictionController implements DragController.DragListener,
} }
} }
private void performBetaCheck() {
if (isReady()) return;
int hotseatItemsCount = mHotseat.getShortcutsAndWidgets().getChildCount();
int maxItems = DeviceConfig.getInt(
DeviceFlag.NAMESPACE_LAUNCHER, "max_homepage_items_for_migration", 5);
// -1 to exclude smart space
int workspaceItemCount = mLauncher.getWorkspace().getScreenWithId(
Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets().getChildCount() - 1;
// opt user into the feature without onboarding tip or migration if they don't have any
// open spots in their hotseat and have more than maxItems in their hotseat + workspace
if (hotseatItemsCount == mHotSeatItemsCount && workspaceItemCount + hotseatItemsCount
> maxItems) {
mLauncher.getSharedPrefs().edit().putBoolean(HotseatEduController.KEY_HOTSEAT_EDU_SEEN,
true).apply();
LauncherLogProto.Action action = newAction(LauncherLogProto.Action.Type.TOUCH);
LauncherLogProto.Target target = newContainerTarget(LauncherLogProto.ContainerType.TIP);
action.touch = LauncherLogProto.Action.Touch.TAP;
target.tipType = LauncherLogProto.TipType.HYBRID_HOTSEAT;
target.controlType = LauncherLogProto.ControlType.HYBRID_HOTSEAT_CANCELED;
// temporarily encode details in log target (go/hotseat_migration)
target.rank = 2;
target.cardinality = (workspaceItemCount * 1000) + hotseatItemsCount;
target.pageIndex = maxItems;
LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
UserEventDispatcher.newInstance(mLauncher).dispatchUserEvent(event, null);
}
}
/** /**
* Fill in predicted_rank field based on app prediction. * Fill in predicted_rank field based on app prediction.
* Only applicable when {@link ItemInfo#itemType} is PREDICTED_HOTSEAT * Only applicable when {@link ItemInfo#itemType} is PREDICTED_HOTSEAT
@@ -170,6 +170,7 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
super.onDestroy(); super.onDestroy();
if (mHotseatPredictionController != null) { if (mHotseatPredictionController != null) {
mHotseatPredictionController.destroy(); mHotseatPredictionController.destroy();
mHotseatPredictionController = null;
} }
} }
@@ -117,8 +117,8 @@ public final class FeatureFlags {
"ASSISTANT_GIVES_LAUNCHER_FOCUS", false, "ASSISTANT_GIVES_LAUNCHER_FOCUS", false,
"Allow Launcher to handle nav bar gestures while Assistant is running over it"); "Allow Launcher to handle nav bar gestures while Assistant is running over it");
public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = new DeviceFlag( public static final BooleanFlag ENABLE_HYBRID_HOTSEAT = getDebugFlag(
"ENABLE_HYBRID_HOTSEAT", false, "Fill gaps in hotseat with predicted apps"); "ENABLE_HYBRID_HOTSEAT", true, "Fill gaps in hotseat with predicted apps");
public static final BooleanFlag HOTSEAT_MIGRATE_TO_FOLDER = new DeviceFlag( public static final BooleanFlag HOTSEAT_MIGRATE_TO_FOLDER = new DeviceFlag(
"HOTSEAT_MIGRATE_TO_FOLDER", false, "Should move hotseat items into a folder"); "HOTSEAT_MIGRATE_TO_FOLDER", false, "Should move hotseat items into a folder");