2019-09-15 22:03:43 -07:00
|
|
|
/*
|
2019-04-19 01:46:51 -07:00
|
|
|
* Copyright (C) 2019 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.
|
|
|
|
|
*/
|
2020-07-27 17:50:33 -07:00
|
|
|
package com.android.launcher3.model;
|
2019-04-19 01:46:51 -07:00
|
|
|
|
2020-08-11 18:49:28 -07:00
|
|
|
import static android.app.prediction.AppTargetEvent.ACTION_DISMISS;
|
|
|
|
|
import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH;
|
|
|
|
|
import static android.app.prediction.AppTargetEvent.ACTION_PIN;
|
2022-03-30 17:46:09 +00:00
|
|
|
import static android.app.prediction.AppTargetEvent.ACTION_UNDISMISS;
|
2020-08-11 18:49:28 -07:00
|
|
|
import static android.app.prediction.AppTargetEvent.ACTION_UNPIN;
|
|
|
|
|
|
|
|
|
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
|
|
|
|
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
|
2021-10-07 16:33:22 +01:00
|
|
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_PREDICTION;
|
2022-01-31 16:08:51 -08:00
|
|
|
import static com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers.ContainerCase.DEVICE_SEARCH_RESULT_CONTAINER;
|
2020-07-15 17:02:16 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
|
2022-03-30 17:46:09 +00:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_DISMISS_PREDICTION_UNDO;
|
2020-08-11 18:49:28 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED;
|
2020-07-15 17:02:16 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
|
2020-08-11 18:49:28 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_REMOVE;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_FOLDER_CREATED;
|
2021-10-08 16:21:05 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
|
2020-07-15 17:02:16 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
|
2021-10-07 16:33:22 +01:00
|
|
|
import static com.android.launcher3.model.PredictionHelper.isTrackedForHotseatPrediction;
|
|
|
|
|
import static com.android.launcher3.model.PredictionHelper.isTrackedForWidgetPrediction;
|
2020-07-27 17:50:33 -07:00
|
|
|
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
2019-08-15 14:53:41 -07:00
|
|
|
|
2019-04-19 01:46:51 -07:00
|
|
|
import android.annotation.TargetApi;
|
|
|
|
|
import android.app.prediction.AppTarget;
|
|
|
|
|
import android.app.prediction.AppTargetEvent;
|
|
|
|
|
import android.app.prediction.AppTargetId;
|
|
|
|
|
import android.content.ComponentName;
|
|
|
|
|
import android.content.Context;
|
2021-03-16 12:26:30 -05:00
|
|
|
import android.content.pm.ShortcutInfo;
|
2019-04-19 01:46:51 -07:00
|
|
|
import android.os.Build;
|
|
|
|
|
import android.os.Handler;
|
|
|
|
|
import android.os.Message;
|
2020-07-15 17:02:16 -07:00
|
|
|
import android.os.Process;
|
|
|
|
|
import android.os.SystemClock;
|
2019-04-19 01:46:51 -07:00
|
|
|
import android.os.UserHandle;
|
2020-07-15 17:02:16 -07:00
|
|
|
import android.text.TextUtils;
|
2019-04-19 01:46:51 -07:00
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
import androidx.annotation.AnyThread;
|
2019-05-14 15:26:19 -07:00
|
|
|
import androidx.annotation.Nullable;
|
2019-08-09 16:16:06 -07:00
|
|
|
import androidx.annotation.WorkerThread;
|
|
|
|
|
|
2022-04-12 14:45:25 -07:00
|
|
|
import com.android.launcher3.Utilities;
|
2020-07-15 17:02:16 -07:00
|
|
|
import com.android.launcher3.logger.LauncherAtom;
|
|
|
|
|
import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
|
|
|
|
|
import com.android.launcher3.logger.LauncherAtom.FolderContainer;
|
|
|
|
|
import com.android.launcher3.logger.LauncherAtom.HotseatContainer;
|
|
|
|
|
import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer;
|
|
|
|
|
import com.android.launcher3.logging.StatsLogManager.EventEnum;
|
|
|
|
|
import com.android.launcher3.pm.UserCache;
|
2021-03-16 12:26:30 -05:00
|
|
|
import com.android.launcher3.shortcuts.ShortcutRequest;
|
2020-07-15 17:02:16 -07:00
|
|
|
import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer;
|
2019-09-15 22:03:43 -07:00
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
import java.util.Locale;
|
2021-03-16 12:26:30 -05:00
|
|
|
import java.util.Optional;
|
2020-08-11 18:49:28 -07:00
|
|
|
import java.util.function.ObjIntConsumer;
|
2020-07-15 17:02:16 -07:00
|
|
|
import java.util.function.Predicate;
|
2019-04-19 01:46:51 -07:00
|
|
|
|
|
|
|
|
/**
|
2020-07-27 17:50:33 -07:00
|
|
|
* Utility class to track stats log and emit corresponding app events
|
2019-04-19 01:46:51 -07:00
|
|
|
*/
|
2020-07-27 17:50:33 -07:00
|
|
|
@TargetApi(Build.VERSION_CODES.R)
|
|
|
|
|
public class AppEventProducer implements StatsLogConsumer {
|
2019-04-19 01:46:51 -07:00
|
|
|
|
2020-07-27 17:50:33 -07:00
|
|
|
private static final int MSG_LAUNCH = 0;
|
2019-04-19 01:46:51 -07:00
|
|
|
|
2020-07-27 17:50:33 -07:00
|
|
|
private final Context mContext;
|
2019-04-19 01:46:51 -07:00
|
|
|
private final Handler mMessageHandler;
|
2020-08-11 18:49:28 -07:00
|
|
|
private final ObjIntConsumer<AppTargetEvent> mCallback;
|
|
|
|
|
|
|
|
|
|
private LauncherAtom.ItemInfo mLastDragItem;
|
2019-04-19 01:46:51 -07:00
|
|
|
|
2020-08-11 18:49:28 -07:00
|
|
|
public AppEventProducer(Context context, ObjIntConsumer<AppTargetEvent> callback) {
|
2019-04-19 01:46:51 -07:00
|
|
|
mContext = context;
|
2020-07-27 17:50:33 -07:00
|
|
|
mMessageHandler = new Handler(MODEL_EXECUTOR.getLooper(), this::handleMessage);
|
|
|
|
|
mCallback = callback;
|
2019-05-14 15:26:19 -07:00
|
|
|
}
|
|
|
|
|
|
2019-04-19 01:46:51 -07:00
|
|
|
@WorkerThread
|
|
|
|
|
private boolean handleMessage(Message msg) {
|
|
|
|
|
switch (msg.what) {
|
|
|
|
|
case MSG_LAUNCH: {
|
2020-08-11 18:49:28 -07:00
|
|
|
mCallback.accept((AppTargetEvent) msg.obj, msg.arg1);
|
2019-04-19 01:46:51 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
@AnyThread
|
2020-08-11 18:49:28 -07:00
|
|
|
private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId, int targetPredictor) {
|
|
|
|
|
sendEvent(toAppTarget(atomInfo), atomInfo, eventId, targetPredictor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@AnyThread
|
|
|
|
|
private void sendEvent(AppTarget target, LauncherAtom.ItemInfo locationInfo, int eventId,
|
|
|
|
|
int targetPredictor) {
|
2022-04-12 14:45:25 -07:00
|
|
|
// TODO: remove the running test check when b/231648228 is fixed.
|
|
|
|
|
if (target != null && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
2020-07-15 17:02:16 -07:00
|
|
|
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
|
2020-08-11 18:49:28 -07:00
|
|
|
.setLaunchLocation(getContainer(locationInfo))
|
2019-05-11 09:30:51 +00:00
|
|
|
.build();
|
2020-08-11 18:49:28 -07:00
|
|
|
mMessageHandler.obtainMessage(MSG_LAUNCH, targetPredictor, 0, event).sendToTarget();
|
2019-04-19 01:46:51 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-09 16:16:06 -07:00
|
|
|
@Override
|
2020-07-15 17:02:16 -07:00
|
|
|
public void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo) {
|
|
|
|
|
if (event == LAUNCHER_APP_LAUNCH_TAP
|
|
|
|
|
|| event == LAUNCHER_TASK_LAUNCH_SWIPE_DOWN
|
|
|
|
|
|| event == LAUNCHER_TASK_LAUNCH_TAP
|
|
|
|
|
|| event == LAUNCHER_QUICKSWITCH_RIGHT
|
|
|
|
|
|| event == LAUNCHER_QUICKSWITCH_LEFT) {
|
2020-08-11 18:49:28 -07:00
|
|
|
sendEvent(atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
|
2020-07-15 17:02:16 -07:00
|
|
|
} else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) {
|
2020-08-11 18:49:28 -07:00
|
|
|
sendEvent(atomInfo, ACTION_DISMISS, CONTAINER_PREDICTION);
|
|
|
|
|
} else if (event == LAUNCHER_ITEM_DRAG_STARTED) {
|
|
|
|
|
mLastDragItem = atomInfo;
|
|
|
|
|
} else if (event == LAUNCHER_ITEM_DROP_COMPLETED) {
|
|
|
|
|
if (mLastDragItem == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (isTrackedForHotseatPrediction(mLastDragItem)) {
|
|
|
|
|
sendEvent(mLastDragItem, ACTION_UNPIN, CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
}
|
2022-02-07 11:09:24 -08:00
|
|
|
if (isTrackedForHotseatPrediction(atomInfo)) {
|
|
|
|
|
sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
}
|
2021-10-07 16:33:22 +01:00
|
|
|
if (isTrackedForWidgetPrediction(atomInfo)) {
|
|
|
|
|
sendEvent(atomInfo, ACTION_PIN, CONTAINER_WIDGETS_PREDICTION);
|
|
|
|
|
}
|
2020-08-11 18:49:28 -07:00
|
|
|
mLastDragItem = null;
|
|
|
|
|
} else if (event == LAUNCHER_ITEM_DROP_FOLDER_CREATED) {
|
|
|
|
|
if (isTrackedForHotseatPrediction(atomInfo)) {
|
|
|
|
|
sendEvent(createTempFolderTarget(), atomInfo, ACTION_PIN,
|
|
|
|
|
CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
sendEvent(atomInfo, ACTION_UNPIN, CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
}
|
|
|
|
|
} else if (event == LAUNCHER_FOLDER_CONVERTED_TO_ICON) {
|
|
|
|
|
if (isTrackedForHotseatPrediction(atomInfo)) {
|
|
|
|
|
sendEvent(createTempFolderTarget(), atomInfo, ACTION_UNPIN,
|
|
|
|
|
CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
}
|
|
|
|
|
} else if (event == LAUNCHER_ITEM_DROPPED_ON_REMOVE) {
|
|
|
|
|
if (mLastDragItem != null && isTrackedForHotseatPrediction(mLastDragItem)) {
|
|
|
|
|
sendEvent(mLastDragItem, ACTION_UNPIN, CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
}
|
2021-10-07 16:33:22 +01:00
|
|
|
if (mLastDragItem != null && isTrackedForWidgetPrediction(mLastDragItem)) {
|
|
|
|
|
sendEvent(mLastDragItem, ACTION_UNPIN, CONTAINER_WIDGETS_PREDICTION);
|
|
|
|
|
}
|
2020-08-11 18:49:28 -07:00
|
|
|
} else if (event == LAUNCHER_HOTSEAT_PREDICTION_PINNED) {
|
|
|
|
|
if (isTrackedForHotseatPrediction(atomInfo)) {
|
|
|
|
|
sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
|
|
|
|
|
}
|
2021-10-08 16:21:05 -07:00
|
|
|
} else if (event == LAUNCHER_ONRESUME) {
|
2021-10-28 17:52:02 +00:00
|
|
|
AppTarget target = new AppTarget.Builder(new AppTargetId("launcher:launcher"),
|
2021-10-08 16:21:05 -07:00
|
|
|
mContext.getPackageName(), Process.myUserHandle())
|
|
|
|
|
.build();
|
|
|
|
|
sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
|
2022-03-30 17:46:09 +00:00
|
|
|
} else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) {
|
|
|
|
|
sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION);
|
2020-07-15 17:02:16 -07:00
|
|
|
}
|
2019-08-09 16:16:06 -07:00
|
|
|
}
|
|
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
@Nullable
|
|
|
|
|
private AppTarget toAppTarget(LauncherAtom.ItemInfo info) {
|
|
|
|
|
UserHandle userHandle = Process.myUserHandle();
|
|
|
|
|
if (info.getIsWork()) {
|
|
|
|
|
userHandle = UserCache.INSTANCE.get(mContext).getUserProfiles().stream()
|
|
|
|
|
.filter(((Predicate<UserHandle>) userHandle::equals).negate())
|
|
|
|
|
.findAny()
|
|
|
|
|
.orElse(null);
|
|
|
|
|
}
|
|
|
|
|
if (userHandle == null) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
ComponentName cn = null;
|
2021-03-16 12:26:30 -05:00
|
|
|
ShortcutInfo shortcutInfo = null;
|
2020-07-15 17:02:16 -07:00
|
|
|
String id = null;
|
|
|
|
|
|
|
|
|
|
switch (info.getItemCase()) {
|
|
|
|
|
case APPLICATION: {
|
|
|
|
|
LauncherAtom.Application app = info.getApplication();
|
|
|
|
|
if ((cn = parseNullable(app.getComponentName())) != null) {
|
|
|
|
|
id = "app:" + cn.getPackageName();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SHORTCUT: {
|
|
|
|
|
LauncherAtom.Shortcut si = info.getShortcut();
|
|
|
|
|
if (!TextUtils.isEmpty(si.getShortcutId())
|
|
|
|
|
&& (cn = parseNullable(si.getShortcutName())) != null) {
|
2021-03-16 12:26:30 -05:00
|
|
|
Optional<ShortcutInfo> opt = new ShortcutRequest(mContext,
|
|
|
|
|
userHandle).forPackage(cn.getPackageName(), si.getShortcutId()).query(
|
|
|
|
|
ShortcutRequest.ALL).stream().findFirst();
|
|
|
|
|
if (opt.isPresent()) {
|
|
|
|
|
shortcutInfo = opt.get();
|
|
|
|
|
} else {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2020-07-15 17:02:16 -07:00
|
|
|
id = "shortcut:" + si.getShortcutId();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case WIDGET: {
|
|
|
|
|
LauncherAtom.Widget widget = info.getWidget();
|
|
|
|
|
if ((cn = parseNullable(widget.getComponentName())) != null) {
|
|
|
|
|
id = "widget:" + cn.getPackageName();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TASK: {
|
|
|
|
|
LauncherAtom.Task task = info.getTask();
|
|
|
|
|
if ((cn = parseNullable(task.getComponentName())) != null) {
|
|
|
|
|
id = "app:" + cn.getPackageName();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-08-11 18:49:28 -07:00
|
|
|
case FOLDER_ICON:
|
|
|
|
|
return createTempFolderTarget();
|
2020-07-15 17:02:16 -07:00
|
|
|
}
|
|
|
|
|
if (id != null && cn != null) {
|
2021-03-16 12:26:30 -05:00
|
|
|
if (shortcutInfo != null) {
|
|
|
|
|
return new AppTarget.Builder(new AppTargetId(id), shortcutInfo).build();
|
|
|
|
|
}
|
2020-07-15 17:02:16 -07:00
|
|
|
return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle)
|
|
|
|
|
.setClassName(cn.getClassName())
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
return null;
|
2019-04-19 01:46:51 -07:00
|
|
|
}
|
2019-08-09 16:16:06 -07:00
|
|
|
|
2021-03-16 12:26:30 -05:00
|
|
|
|
2020-08-11 18:49:28 -07:00
|
|
|
private AppTarget createTempFolderTarget() {
|
|
|
|
|
return new AppTarget.Builder(new AppTargetId("folder:" + SystemClock.uptimeMillis()),
|
|
|
|
|
mContext.getPackageName(), Process.myUserHandle())
|
|
|
|
|
.build();
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
private String getContainer(LauncherAtom.ItemInfo info) {
|
|
|
|
|
ContainerInfo ci = info.getContainerInfo();
|
|
|
|
|
switch (ci.getContainerCase()) {
|
|
|
|
|
case WORKSPACE: {
|
|
|
|
|
// In case the item type is not widgets, the spaceX and spanY default to 1.
|
|
|
|
|
int spanX = info.getWidget().getSpanX();
|
|
|
|
|
int spanY = info.getWidget().getSpanY();
|
|
|
|
|
return getWorkspaceContainerString(ci.getWorkspace(), spanX, spanY);
|
|
|
|
|
}
|
|
|
|
|
case HOTSEAT: {
|
|
|
|
|
return getHotseatContainerString(ci.getHotseat());
|
|
|
|
|
}
|
|
|
|
|
case TASK_SWITCHER_CONTAINER: {
|
|
|
|
|
return "task-switcher";
|
|
|
|
|
}
|
|
|
|
|
case ALL_APPS_CONTAINER: {
|
|
|
|
|
return "all-apps";
|
|
|
|
|
}
|
|
|
|
|
case PREDICTED_HOTSEAT_CONTAINER: {
|
|
|
|
|
return "predictions/hotseat";
|
|
|
|
|
}
|
|
|
|
|
case PREDICTION_CONTAINER: {
|
|
|
|
|
return "predictions";
|
|
|
|
|
}
|
2020-10-12 09:33:00 -07:00
|
|
|
case SHORTCUTS_CONTAINER: {
|
2020-10-14 15:39:38 -07:00
|
|
|
return "deep-shortcuts";
|
2020-10-12 09:33:00 -07:00
|
|
|
}
|
2020-07-15 17:02:16 -07:00
|
|
|
case FOLDER: {
|
|
|
|
|
FolderContainer fc = ci.getFolder();
|
|
|
|
|
switch (fc.getParentContainerCase()) {
|
|
|
|
|
case WORKSPACE:
|
|
|
|
|
return "folder/" + getWorkspaceContainerString(fc.getWorkspace(), 1, 1);
|
|
|
|
|
case HOTSEAT:
|
|
|
|
|
return "folder/" + getHotseatContainerString(fc.getHotseat());
|
|
|
|
|
}
|
|
|
|
|
return "folder";
|
|
|
|
|
}
|
2021-11-10 20:32:55 -08:00
|
|
|
case SEARCH_RESULT_CONTAINER:
|
|
|
|
|
return "search-results";
|
|
|
|
|
case EXTENDED_CONTAINERS: {
|
2022-01-31 16:08:51 -08:00
|
|
|
if (ci.getExtendedContainers().getContainerCase()
|
|
|
|
|
== DEVICE_SEARCH_RESULT_CONTAINER) {
|
|
|
|
|
return "search-results";
|
2021-11-10 20:32:55 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
default: // fall out
|
2020-07-15 17:02:16 -07:00
|
|
|
}
|
|
|
|
|
return "";
|
2019-08-09 16:16:06 -07:00
|
|
|
}
|
|
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
private static String getWorkspaceContainerString(WorkspaceContainer wc, int spanX, int spanY) {
|
|
|
|
|
return String.format(Locale.ENGLISH, "workspace/%d/[%d,%d]/[%d,%d]",
|
|
|
|
|
wc.getPageIndex(), wc.getGridX(), wc.getGridY(), spanX, spanY);
|
2019-08-09 16:16:06 -07:00
|
|
|
}
|
2019-09-15 22:03:43 -07:00
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
private static String getHotseatContainerString(HotseatContainer hc) {
|
2020-08-11 18:49:28 -07:00
|
|
|
return String.format(Locale.ENGLISH, "hotseat/%1$d/[%1$d,0]/[1,1]", hc.getIndex());
|
2019-09-15 22:03:43 -07:00
|
|
|
}
|
|
|
|
|
|
2020-07-15 17:02:16 -07:00
|
|
|
private static ComponentName parseNullable(String componentNameString) {
|
|
|
|
|
return TextUtils.isEmpty(componentNameString)
|
|
|
|
|
? null : ComponentName.unflattenFromString(componentNameString);
|
2019-09-15 22:03:43 -07:00
|
|
|
}
|
2019-04-19 01:46:51 -07:00
|
|
|
}
|