Add a "Dismiss" option for predicted apps in Launcher

Test: LongPress on a pridicted app to see dismiss options.
Bug:139020180
Change-Id: I877863c65def0d845c0ae2f0987fe7a4f6277565
This commit is contained in:
Samuel Fufa 2019-08-09 16:16:06 -07:00
parent 237441a2b4
commit 866ff00eb3
13 changed files with 106 additions and 13 deletions

View File

@ -118,6 +118,7 @@ enum ControlType {
APP_USAGE_SETTINGS = 18;
BACK_GESTURE = 19;
UNDO = 20;
DISMISS_PREDICTION = 21;
}
enum TipType {

View File

@ -15,8 +15,6 @@
*/
package com.android.launcher3.appprediction;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
import android.annotation.TargetApi;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
@ -34,13 +32,15 @@ import android.os.UserHandle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.util.UiThreadHelper;
import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
/**
* Subclass of app tracker which publishes the data to the prediction engine and gets back results.
@ -174,6 +174,7 @@ public class PredictionAppTracker extends AppLaunchTracker {
new AppTargetId("shortcut:" + shortcutId), packageName, user)
.setClassName(shortcutId)
.build();
sendLaunch(target, container);
}
@ -189,11 +190,32 @@ public class PredictionAppTracker extends AppLaunchTracker {
}
}
@Override
@UiThread
private void sendLaunch(AppTarget target, String container) {
AppTargetEvent event = new AppTargetEvent.Builder(target, AppTargetEvent.ACTION_LAUNCH)
public void onDismissApp(ComponentName cn, UserHandle user, String container) {
if (cn == null) return;
AppTarget target = new AppTarget.Builder(
new AppTargetId("app: " + cn), cn.getPackageName(), user)
.setClassName(cn.getClassName())
.build();
sendDismiss(target, container);
}
@UiThread
private void sendEvent(AppTarget target, String container, int eventId) {
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
.setLaunchLocation(container == null ? CONTAINER_DEFAULT : container)
.build();
Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget();
}
@UiThread
private void sendLaunch(AppTarget target, String container) {
sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH);
}
@UiThread
private void sendDismiss(AppTarget target, String container) {
sendEvent(target, container, AppTargetEvent.ACTION_DISMISS);
}
}

View File

@ -43,6 +43,7 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.allapps.AllAppsStore;
@ -290,7 +291,9 @@ public class PredictionRowView extends LinearLayout implements
for (ComponentKeyMapper mapper : components) {
ItemInfoWithIcon info = mapper.getApp(getAppsStore());
if (info != null) {
predictedApps.add(info);
ItemInfoWithIcon predictedApp = info.clone();
predictedApp.container = LauncherSettings.Favorites.CONTAINER_PREDICTION;
predictedApps.add(predictedApp);
} else {
if (FeatureFlags.IS_DOGFOOD_BUILD) {
Log.e(TAG, "Predicted app not found: " + mapper);

View File

@ -105,6 +105,9 @@
<!-- Label for install drop target. [CHAR_LIMIT=20] -->
<string name="install_drop_target_label">Install</string>
<!-- Label for install dismiss prediction. -->
<string translatable="false" name="dismiss_prediction_label">Dismiss prediction</string>
<!-- Permissions: -->
<skip />
<!-- Permission short label -->

View File

@ -85,6 +85,8 @@ public class AppInfo extends ItemInfoWithIcon {
componentName = info.componentName;
title = Utilities.trim(info.title);
intent = new Intent(info.intent);
user = info.user;
runtimeStatusFlags = info.runtimeStatusFlags;
}
@Override
@ -127,4 +129,9 @@ public class AppInfo extends ItemInfoWithIcon {
info.runtimeStatusFlags |= FLAG_ADAPTIVE_ICON;
}
}
@Override
public AppInfo clone() {
return new AppInfo(this);
}
}

View File

@ -27,6 +27,8 @@ import com.android.launcher3.icons.BitmapInfo;
*/
public abstract class ItemInfoWithIcon extends ItemInfo {
public static final String TAG = "ItemInfoDebug";
/**
* A bitmap version of the application icon.
*/
@ -126,4 +128,8 @@ public abstract class ItemInfoWithIcon extends ItemInfo {
iconColor = info.color;
}
/**
* @return a copy of this
*/
public abstract ItemInfoWithIcon clone();
}

View File

@ -122,11 +122,13 @@ public class LauncherSettings {
*/
public static final int CONTAINER_DESKTOP = -100;
public static final int CONTAINER_HOTSEAT = -101;
public static final int CONTAINER_PREDICTION = -102;
static final String containerToString(int container) {
switch (container) {
case CONTAINER_DESKTOP: return "desktop";
case CONTAINER_HOTSEAT: return "hotseat";
case CONTAINER_PREDICTION: return "prediction";
default: return String.valueOf(container);
}
}

View File

@ -219,4 +219,9 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
}
return cn;
}
@Override
public ItemInfoWithIcon clone() {
return new WorkspaceItemInfo(this);
}
}

View File

@ -116,6 +116,10 @@ abstract class BaseFlags {
"APP_SEARCH_IMPROVEMENTS", false,
"Adds localized title and keyword search and ranking");
public static final TogglableFlag ENABLE_PREDICTION_DISMISS = new TogglableFlag(
"ENABLE_PREDICTION_DISMISS", false, "Allow option to dimiss apps from predicted list");
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {

View File

@ -51,5 +51,8 @@ public class AppLaunchTracker implements ResourceBasedOverride {
public void onStartApp(ComponentName componentName, UserHandle user,
@Nullable String container) { }
public void onDismissApp(ComponentName componentName, UserHandle user,
@Nullable String container){}
public void onReturnedToHome() { }
}

View File

@ -32,8 +32,17 @@ public class PackageItemInfo extends ItemInfoWithIcon {
this.packageName = packageName;
}
public PackageItemInfo(PackageItemInfo copy) {
this.packageName = copy.packageName;
}
@Override
protected String dumpProperties() {
return super.dumpProperties() + " packageName=" + packageName;
}
@Override
public PackageItemInfo clone() {
return new PackageItemInfo(this);
}
}

View File

@ -1,14 +1,11 @@
package com.android.launcher3.popup;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.drawable.Icon;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
@ -20,23 +17,30 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.WorkspaceItemInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.AppLaunchTracker;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.widget.WidgetsBottomSheet;
import java.util.List;
/**
* Represents a system shortcut for a given app. The shortcut should have a label and icon, and an
* onClickListener that depends on the item that the shortcut services.
*
* Example system shortcuts, defined as inner classes, include Widgets and AppInfo.
* @param <T>
*/
public abstract class SystemShortcut<T extends BaseDraggingActivity> extends ItemInfo {
public abstract class SystemShortcut<T extends BaseDraggingActivity>
extends ItemInfo {
private final int mIconResId;
private final int mLabelResId;
private final Icon mIcon;
@ -201,6 +205,27 @@ public abstract class SystemShortcut<T extends BaseDraggingActivity> extends Ite
}
}
public static class DismissPrediction extends SystemShortcut<Launcher> {
public DismissPrediction() {
super(R.drawable.ic_remove_no_shadow, R.string.dismiss_prediction_label);
}
@Override
public View.OnClickListener getOnClickListener(Launcher activity, ItemInfo itemInfo) {
if (!FeatureFlags.ENABLE_PREDICTION_DISMISS.get()) return null;
if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_PREDICTION) return null;
return (view) -> {
PopupContainerWithArrow.closeAllOpenViews(activity);
activity.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.DISMISS_PREDICTION, ContainerType.DEEPSHORTCUTS);
AppLaunchTracker.INSTANCE.get(view.getContext())
.onDismissApp(itemInfo.getTargetComponent(),
itemInfo.user,
AppLaunchTracker.CONTAINER_PREDICTIONS);
};
}
}
protected static void dismissTaskMenuView(BaseDraggingActivity activity) {
AbstractFloatingView.closeOpenViews(activity, true,
AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE);

View File

@ -39,7 +39,9 @@ public class SystemShortcutFactory implements ResourceBasedOverride {
@SuppressWarnings("unused")
public SystemShortcutFactory() {
this(new SystemShortcut.AppInfo(),
new SystemShortcut.Widgets(), new SystemShortcut.Install());
new SystemShortcut.Widgets(),
new SystemShortcut.Install(),
new SystemShortcut.DismissPrediction());
}
protected SystemShortcutFactory(SystemShortcut... shortcuts) {
@ -53,6 +55,7 @@ public class SystemShortcutFactory implements ResourceBasedOverride {
systemShortcuts.add(systemShortcut);
}
}
return systemShortcuts;
}
}