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:
parent
237441a2b4
commit
866ff00eb3
|
@ -118,6 +118,7 @@ enum ControlType {
|
|||
APP_USAGE_SETTINGS = 18;
|
||||
BACK_GESTURE = 19;
|
||||
UNDO = 20;
|
||||
DISMISS_PREDICTION = 21;
|
||||
}
|
||||
|
||||
enum TipType {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,4 +219,9 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
|
|||
}
|
||||
return cn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemInfoWithIcon clone() {
|
||||
return new WorkspaceItemInfo(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() { }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue