Merge "Delays removal of extra screen when dropping an app." into ub-launcher3-master
diff --git a/Android.mk b/Android.mk
index 91ecccb..25f5412 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,6 +28,7 @@
androidx.recyclerview_recyclerview \
androidx.dynamicanimation_dynamicanimation \
androidx.preference_preference \
+ androidx.slice_slice-view \
iconloader_base
LOCAL_STATIC_JAVA_LIBRARIES := \
@@ -149,12 +150,9 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
- $(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, src_shortcuts_overrides)
-LOCAL_RESOURCE_DIR := \
- $(LOCAL_PATH)/quickstep/res \
- $(LOCAL_PATH)/quickstep/recents_ui_overrides/res
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
LOCAL_PROGUARD_ENABLED := disabled
@@ -183,9 +181,7 @@
LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3
LOCAL_REQUIRED_MODULES := privapp_whitelist_com.android.launcher3
-LOCAL_RESOURCE_DIR := \
- $(LOCAL_PATH)/quickstep/res \
- $(LOCAL_PATH)/quickstep/recents_ui_overrides/res
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/quickstep/res
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
@@ -220,12 +216,10 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
- $(call all-java-files-under, quickstep/recents_ui_overrides/src) \
$(call all-java-files-under, go/src)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
- $(LOCAL_PATH)/quickstep/recents_ui_overrides/res \
$(LOCAL_PATH)/go/res
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
diff --git a/go/AndroidManifest.xml b/go/AndroidManifest.xml
index f84a82e..f36439d 100644
--- a/go/AndroidManifest.xml
+++ b/go/AndroidManifest.xml
@@ -46,6 +46,12 @@
tools:node="replace" >
</activity>
+ <service
+ android:name="com.android.launcher3.notification.NotificationListener"
+ android:label="@string/notification_dots_service_title"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
+ android:enabled="false"
+ tools:node="replace" />
</application>
</manifest>
diff --git a/go/res/values-v26/bools.xml b/go/res/values-v26/bools.xml
deleted file mode 100644
index cc4a7ba..0000000
--- a/go/res/values-v26/bools.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/* Copyright 2017, 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.
-*/
--->
-
-<resources>
- <bool name="notification_badging_enabled">false</bool>
-</resources>
\ No newline at end of file
diff --git a/go/res/values/dimens.xml b/go/res/values/dimens.xml
deleted file mode 100644
index f1b1053..0000000
--- a/go/res/values/dimens.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<resources>
- <!-- Dynamic Grid -->
- <dimen name="dynamic_grid_hotseat_size">60dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LoaderResults.java
index 7130531..5f71061 100644
--- a/go/src/com/android/launcher3/model/LoaderResults.java
+++ b/go/src/com/android/launcher3/model/LoaderResults.java
@@ -20,7 +20,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.Callbacks;
-import com.android.launcher3.util.LooperExecutor;
/**
* Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
@@ -29,12 +28,7 @@
public LoaderResults(LauncherAppState app, BgDataModel dataModel,
AllAppsList allAppsList, Callbacks[] callbacks) {
- this(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
- }
-
- public LoaderResults(LauncherAppState app, BgDataModel dataModel,
- AllAppsList allAppsList, Callbacks[] callbacks, LooperExecutor executor) {
- super(app, dataModel, allAppsList, callbacks, executor);
+ super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
}
@Override
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
index 3b3dc01..89b3831 100644
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -41,6 +41,7 @@
// True is the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = true;
+ public static final boolean GO_DISABLE_NOTIFICATION_DOTS = true;
private static final ArrayList<WidgetListRowEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
deleted file mode 100644
index 7b8070a..0000000
--- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java
+++ /dev/null
@@ -1,317 +0,0 @@
-<<<<<<< HEAD (cc6caf Merge "Let launcher to provide its own OverscrollPlugin" int)
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.launcher3.icons.cache;
-
-import android.content.ComponentName;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.database.sqlite.SQLiteException;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.SparseBooleanArray;
-
-import com.android.launcher3.icons.cache.BaseIconCache.IconDB;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.Stack;
-
-/**
- * Utility class to handle updating the Icon cache
- */
-public class IconCacheUpdateHandler {
-
- private static final String TAG = "IconCacheUpdateHandler";
-
- /**
- * In this mode, all invalid icons are marked as to-be-deleted in {@link #mItemsToDelete}.
- * This mode is used for the first run.
- */
- private static final boolean MODE_SET_INVALID_ITEMS = true;
-
- /**
- * In this mode, any valid icon is removed from {@link #mItemsToDelete}. This is used for all
- * subsequent runs, which essentially acts as set-union of all valid items.
- */
- private static final boolean MODE_CLEAR_VALID_ITEMS = false;
-
- private static final Object ICON_UPDATE_TOKEN = new Object();
-
- private final HashMap<String, PackageInfo> mPkgInfoMap;
- private final BaseIconCache mIconCache;
-
- private final ArrayMap<UserHandle, Set<String>> mPackagesToIgnore = new ArrayMap<>();
-
- private final SparseBooleanArray mItemsToDelete = new SparseBooleanArray();
- private boolean mFilterMode = MODE_SET_INVALID_ITEMS;
-
- IconCacheUpdateHandler(BaseIconCache cache) {
- mIconCache = cache;
-
- mPkgInfoMap = new HashMap<>();
-
- // Remove all active icon update tasks.
- mIconCache.mWorkerHandler.removeCallbacksAndMessages(ICON_UPDATE_TOKEN);
-
- createPackageInfoMap();
- }
-
- /**
- * Sets a package to ignore for processing
- */
- public void addPackagesToIgnore(UserHandle userHandle, String packageName) {
- Set<String> packages = mPackagesToIgnore.get(userHandle);
- if (packages == null) {
- packages = new HashSet<>();
- mPackagesToIgnore.put(userHandle, packages);
- }
- packages.add(packageName);
- }
-
- private void createPackageInfoMap() {
- PackageManager pm = mIconCache.mPackageManager;
- for (PackageInfo info :
- pm.getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES)) {
- mPkgInfoMap.put(info.packageName, info);
- }
- }
-
- /**
- * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
- * the DB and are updated.
- * @return The set of packages for which icons have updated.
- */
- public <T> void updateIcons(List<T> apps, CachingLogic<T> cachingLogic,
- OnUpdateCallback onUpdateCallback) {
- // Filter the list per user
- HashMap<UserHandle, HashMap<ComponentName, T>> userComponentMap = new HashMap<>();
- int count = apps.size();
- for (int i = 0; i < count; i++) {
- T app = apps.get(i);
- UserHandle userHandle = cachingLogic.getUser(app);
- HashMap<ComponentName, T> componentMap = userComponentMap.get(userHandle);
- if (componentMap == null) {
- componentMap = new HashMap<>();
- userComponentMap.put(userHandle, componentMap);
- }
- componentMap.put(cachingLogic.getComponent(app), app);
- }
-
- for (Entry<UserHandle, HashMap<ComponentName, T>> entry : userComponentMap.entrySet()) {
- updateIconsPerUser(entry.getKey(), entry.getValue(), cachingLogic, onUpdateCallback);
- }
-
- // From now on, clear every valid item from the global valid map.
- mFilterMode = MODE_CLEAR_VALID_ITEMS;
- }
-
- /**
- * Updates the persistent DB, such that only entries corresponding to {@param apps} remain in
- * the DB and are updated.
- * @return The set of packages for which icons have updated.
- */
- @SuppressWarnings("unchecked")
- private <T> void updateIconsPerUser(UserHandle user, HashMap<ComponentName, T> componentMap,
- CachingLogic<T> cachingLogic, OnUpdateCallback onUpdateCallback) {
- Set<String> ignorePackages = mPackagesToIgnore.get(user);
- if (ignorePackages == null) {
- ignorePackages = Collections.emptySet();
- }
- long userSerial = mIconCache.getSerialNumberForUser(user);
-
- Stack<T> appsToUpdate = new Stack<>();
-
- try (Cursor c = mIconCache.mIconDb.query(
- new String[]{IconDB.COLUMN_ROWID, IconDB.COLUMN_COMPONENT,
- IconDB.COLUMN_LAST_UPDATED, IconDB.COLUMN_VERSION,
- IconDB.COLUMN_SYSTEM_STATE},
- IconDB.COLUMN_USER + " = ? ",
- new String[]{Long.toString(userSerial)})) {
-
- final int indexComponent = c.getColumnIndex(IconDB.COLUMN_COMPONENT);
- final int indexLastUpdate = c.getColumnIndex(IconDB.COLUMN_LAST_UPDATED);
- final int indexVersion = c.getColumnIndex(IconDB.COLUMN_VERSION);
- final int rowIndex = c.getColumnIndex(IconDB.COLUMN_ROWID);
- final int systemStateIndex = c.getColumnIndex(IconDB.COLUMN_SYSTEM_STATE);
-
- while (c.moveToNext()) {
- String cn = c.getString(indexComponent);
- ComponentName component = ComponentName.unflattenFromString(cn);
- PackageInfo info = mPkgInfoMap.get(component.getPackageName());
-
- int rowId = c.getInt(rowIndex);
- if (info == null) {
- if (!ignorePackages.contains(component.getPackageName())) {
-
- if (mFilterMode == MODE_SET_INVALID_ITEMS) {
- mIconCache.remove(component, user);
- mItemsToDelete.put(rowId, true);
- }
- }
- continue;
- }
- if ((info.applicationInfo.flags & ApplicationInfo.FLAG_IS_DATA_ONLY) != 0) {
- // Application is not present
- continue;
- }
-
- long updateTime = c.getLong(indexLastUpdate);
- int version = c.getInt(indexVersion);
- T app = componentMap.remove(component);
- if (version == info.versionCode
- && updateTime == cachingLogic.getLastUpdatedTime(app, info)
- && TextUtils.equals(c.getString(systemStateIndex),
- mIconCache.getIconSystemState(info.packageName))) {
-
- if (mFilterMode == MODE_CLEAR_VALID_ITEMS) {
- mItemsToDelete.put(rowId, false);
- }
- continue;
- }
-
- if (app == null) {
- if (mFilterMode == MODE_SET_INVALID_ITEMS) {
- mIconCache.remove(component, user);
- mItemsToDelete.put(rowId, true);
- }
- } else {
- appsToUpdate.add(app);
- }
- }
- } catch (SQLiteException e) {
- Log.d(TAG, "Error reading icon cache", e);
- // Continue updating whatever we have read so far
- }
-
- // Insert remaining apps.
- if (!componentMap.isEmpty() || !appsToUpdate.isEmpty()) {
- Stack<T> appsToAdd = new Stack<>();
- appsToAdd.addAll(componentMap.values());
- new SerializedIconUpdateTask(userSerial, user, appsToAdd, appsToUpdate, cachingLogic,
- onUpdateCallback).scheduleNext();
- }
- }
-
- /**
- * Commits all updates as part of the update handler to disk. Not more calls should be made
- * to this class after this.
- */
- public void finish() {
- // Commit all deletes
- int deleteCount = 0;
- StringBuilder queryBuilder = new StringBuilder()
- .append(IconDB.COLUMN_ROWID)
- .append(" IN (");
-
- int count = mItemsToDelete.size();
- for (int i = 0; i < count; i++) {
- if (mItemsToDelete.valueAt(i)) {
- if (deleteCount > 0) {
- queryBuilder.append(", ");
- }
- queryBuilder.append(mItemsToDelete.keyAt(i));
- deleteCount++;
- }
- }
- queryBuilder.append(')');
-
- if (deleteCount > 0) {
- mIconCache.mIconDb.delete(queryBuilder.toString(), null);
- }
- }
-
- /**
- * A runnable that updates invalid icons and adds missing icons in the DB for the provided
- * LauncherActivityInfo list. Items are updated/added one at a time, so that the
- * worker thread doesn't get blocked.
- */
- private class SerializedIconUpdateTask<T> implements Runnable {
- private final long mUserSerial;
- private final UserHandle mUserHandle;
- private final Stack<T> mAppsToAdd;
- private final Stack<T> mAppsToUpdate;
- private final CachingLogic<T> mCachingLogic;
- private final HashSet<String> mUpdatedPackages = new HashSet<>();
- private final OnUpdateCallback mOnUpdateCallback;
-
- SerializedIconUpdateTask(long userSerial, UserHandle userHandle,
- Stack<T> appsToAdd, Stack<T> appsToUpdate, CachingLogic<T> cachingLogic,
- OnUpdateCallback onUpdateCallback) {
- mUserHandle = userHandle;
- mUserSerial = userSerial;
- mAppsToAdd = appsToAdd;
- mAppsToUpdate = appsToUpdate;
- mCachingLogic = cachingLogic;
- mOnUpdateCallback = onUpdateCallback;
- }
-
- @Override
- public void run() {
- if (!mAppsToUpdate.isEmpty()) {
- T app = mAppsToUpdate.pop();
- String pkg = mCachingLogic.getComponent(app).getPackageName();
- PackageInfo info = mPkgInfoMap.get(pkg);
-
- mIconCache.addIconToDBAndMemCache(
- app, mCachingLogic, info, mUserSerial, true /*replace existing*/);
- mUpdatedPackages.add(pkg);
-
- if (mAppsToUpdate.isEmpty() && !mUpdatedPackages.isEmpty()) {
- // No more app to update. Notify callback.
- mOnUpdateCallback.onPackageIconsUpdated(mUpdatedPackages, mUserHandle);
- }
-
- // Let it run one more time.
- scheduleNext();
- } else if (!mAppsToAdd.isEmpty()) {
- T app = mAppsToAdd.pop();
- PackageInfo info = mPkgInfoMap.get(mCachingLogic.getComponent(app).getPackageName());
- // We do not check the mPkgInfoMap when generating the mAppsToAdd. Although every
- // app should have package info, this is not guaranteed by the api
- if (info != null) {
- mIconCache.addIconToDBAndMemCache(app, mCachingLogic, info,
- mUserSerial, false /*replace existing*/);
- }
-
- if (!mAppsToAdd.isEmpty()) {
- scheduleNext();
- }
- }
- }
-
- public void scheduleNext() {
- mIconCache.mWorkerHandler.postAtTime(this, ICON_UPDATE_TOKEN,
- SystemClock.uptimeMillis() + 1);
- }
- }
-
- public interface OnUpdateCallback {
-
- void onPackageIconsUpdated(HashSet<String> updatedPackages, UserHandle user);
- }
-}
-=======
->>>>>>> CHANGE (805b52 Removes iconloaderlib from Launcher3.)
diff --git a/quickstep/recents_ui_overrides/res/values/colors.xml b/quickstep/recents_ui_overrides/res/values/colors.xml
deleted file mode 100644
index f03f118..0000000
--- a/quickstep/recents_ui_overrides/res/values/colors.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<resources>
- <color name="chip_hint_foreground_color">#fff</color>
- <color name="chip_scrim_start_color">#39000000</color>
-
- <color name="all_apps_label_text">#61000000</color>
- <color name="all_apps_label_text_dark">#61FFFFFF</color>
- <color name="all_apps_prediction_row_separator">#3c000000</color>
- <color name="all_apps_prediction_row_separator_dark">#3cffffff</color>
-</resources>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/res/values/dimens.xml b/quickstep/recents_ui_overrides/res/values/dimens.xml
deleted file mode 100644
index 9266b06..0000000
--- a/quickstep/recents_ui_overrides/res/values/dimens.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<resources>
- <dimen name="chip_hint_border_width">1dp</dimen>
- <dimen name="chip_hint_corner_radius">20dp</dimen>
- <dimen name="chip_hint_outer_padding">20dp</dimen>
- <dimen name="chip_hint_start_padding">10dp</dimen>
- <dimen name="chip_hint_end_padding">12dp</dimen>
- <dimen name="chip_hint_horizontal_margin">20dp</dimen>
- <dimen name="chip_hint_vertical_offset">16dp</dimen>
- <dimen name="chip_hint_elevation">2dp</dimen>
- <dimen name="chip_icon_size">16dp</dimen>
- <dimen name="chip_text_height">26dp</dimen>
- <dimen name="chip_text_top_padding">4dp</dimen>
- <dimen name="chip_text_start_padding">10dp</dimen>
- <dimen name="chip_text_size">14sp</dimen>
-
- <dimen name="all_apps_prediction_row_divider_height">17dp</dimen>
- <dimen name="all_apps_label_top_padding">16dp</dimen>
- <dimen name="all_apps_label_bottom_padding">8dp</dimen>
- <dimen name="all_apps_label_text_size">14sp</dimen>
-
- <!-- Minimum distance to swipe to trigger accessibility gesture -->
- <dimen name="accessibility_gesture_min_swipe_distance">80dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/REMOVED.txt b/quickstep/recents_ui_overrides/src/REMOVED.txt
new file mode 100644
index 0000000..c3a3eaf
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/REMOVED.txt
@@ -0,0 +1,2 @@
+Temp file to prevent build breakage.
+Will be removed in followup cl.
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java
deleted file mode 100644
index d200868..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/ComponentKeyMapper.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * 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.
- */
-
-package com.android.launcher3.appprediction;
-
-import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
-
-import com.android.launcher3.allapps.AllAppsStore;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.util.ComponentKey;
-
-public class ComponentKeyMapper {
-
- protected final ComponentKey componentKey;
- private final DynamicItemCache mCache;
-
- public ComponentKeyMapper(ComponentKey key, DynamicItemCache cache) {
- componentKey = key;
- mCache = cache;
- }
-
- public String getPackage() {
- return componentKey.componentName.getPackageName();
- }
-
- public String getComponentClass() {
- return componentKey.componentName.getClassName();
- }
-
- public ComponentKey getComponentKey() {
- return componentKey;
- }
-
- @Override
- public String toString() {
- return componentKey.toString();
- }
-
- public ItemInfoWithIcon getApp(AllAppsStore store) {
- AppInfo item = store.getApp(componentKey);
- if (item != null) {
- return item;
- } else if (getComponentClass().equals(COMPONENT_CLASS_MARKER)) {
- return mCache.getInstantApp(componentKey.componentName.getPackageName());
- } else {
- return mCache.getShortcutInfo(componentKey);
- }
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
deleted file mode 100644
index ab96b1340..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/DynamicItemCache.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/**
- * 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.
- */
-package com.android.launcher3.appprediction;
-
-import static android.content.pm.PackageManager.MATCH_INSTANT;
-
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ShortcutInfo;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import androidx.annotation.MainThread;
-import androidx.annotation.Nullable;
-import androidx.annotation.UiThread;
-import androidx.annotation.WorkerThread;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.allapps.AllAppsStore;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.InstantAppResolver;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Utility class which loads and caches predicted items like instant apps and shortcuts, before
- * they can be displayed on the UI
- */
-public class DynamicItemCache {
-
- private static final String TAG = "DynamicItemCache";
- private static final boolean DEBUG = false;
- private static final String DEFAULT_URL = "default-url";
-
- private static final int BG_MSG_LOAD_SHORTCUTS = 1;
- private static final int BG_MSG_LOAD_INSTANT_APPS = 2;
-
- private static final int UI_MSG_UPDATE_SHORTCUTS = 1;
- private static final int UI_MSG_UPDATE_INSTANT_APPS = 2;
-
- private final Context mContext;
- private final Handler mWorker;
- private final Handler mUiHandler;
- private final InstantAppResolver mInstantAppResolver;
- private final Runnable mOnUpdateCallback;
- private final IconCache mIconCache;
-
- private final Map<ComponentKey, WorkspaceItemInfo> mShortcuts;
- private final Map<String, InstantAppItemInfo> mInstantApps;
-
- public DynamicItemCache(Context context, Runnable onUpdateCallback) {
- mContext = context;
- mWorker = new Handler(MODEL_EXECUTOR.getLooper(), this::handleWorkerMessage);
- mUiHandler = new Handler(Looper.getMainLooper(), this::handleUiMessage);
- mInstantAppResolver = InstantAppResolver.newInstance(context);
- mOnUpdateCallback = onUpdateCallback;
- mIconCache = LauncherAppState.getInstance(mContext).getIconCache();
-
- mShortcuts = new HashMap<>();
- mInstantApps = new HashMap<>();
- }
-
- public void cacheItems(List<ShortcutKey> shortcutKeys, List<String> pkgNames) {
- if (!shortcutKeys.isEmpty()) {
- mWorker.removeMessages(BG_MSG_LOAD_SHORTCUTS);
- Message.obtain(mWorker, BG_MSG_LOAD_SHORTCUTS, shortcutKeys).sendToTarget();
- }
- if (!pkgNames.isEmpty()) {
- mWorker.removeMessages(BG_MSG_LOAD_INSTANT_APPS);
- Message.obtain(mWorker, BG_MSG_LOAD_INSTANT_APPS, pkgNames).sendToTarget();
- }
- }
-
- private boolean handleWorkerMessage(Message msg) {
- switch (msg.what) {
- case BG_MSG_LOAD_SHORTCUTS: {
- List<ShortcutKey> shortcutKeys = msg.obj != null ?
- (List<ShortcutKey>) msg.obj : Collections.EMPTY_LIST;
- Map<ShortcutKey, WorkspaceItemInfo> shortcutKeyAndInfos = new ArrayMap<>();
- for (ShortcutKey shortcutKey : shortcutKeys) {
- WorkspaceItemInfo workspaceItemInfo = loadShortcutWorker(shortcutKey);
- if (workspaceItemInfo != null) {
- shortcutKeyAndInfos.put(shortcutKey, workspaceItemInfo);
- }
- }
- Message.obtain(mUiHandler, UI_MSG_UPDATE_SHORTCUTS, shortcutKeyAndInfos)
- .sendToTarget();
- return true;
- }
- case BG_MSG_LOAD_INSTANT_APPS: {
- List<String> pkgNames = msg.obj != null ?
- (List<String>) msg.obj : Collections.EMPTY_LIST;
- List<InstantAppItemInfo> instantAppItemInfos = new ArrayList<>();
- for (String pkgName : pkgNames) {
- InstantAppItemInfo instantAppItemInfo = loadInstantApp(pkgName);
- if (instantAppItemInfo != null) {
- instantAppItemInfos.add(instantAppItemInfo);
- }
- }
- Message.obtain(mUiHandler, UI_MSG_UPDATE_INSTANT_APPS, instantAppItemInfos)
- .sendToTarget();
- return true;
- }
- }
-
- return false;
- }
-
- private boolean handleUiMessage(Message msg) {
- switch (msg.what) {
- case UI_MSG_UPDATE_SHORTCUTS: {
- mShortcuts.clear();
- mShortcuts.putAll((Map<ShortcutKey, WorkspaceItemInfo>) msg.obj);
- mOnUpdateCallback.run();
- return true;
- }
- case UI_MSG_UPDATE_INSTANT_APPS: {
- List<InstantAppItemInfo> instantAppItemInfos = (List<InstantAppItemInfo>) msg.obj;
- mInstantApps.clear();
- for (InstantAppItemInfo instantAppItemInfo : instantAppItemInfos) {
- mInstantApps.put(instantAppItemInfo.getTargetComponent().getPackageName(),
- instantAppItemInfo);
- }
- mOnUpdateCallback.run();
- if (DEBUG) {
- Log.d(TAG, String.format("Cache size: %d, Cache: %s",
- mInstantApps.size(), mInstantApps.toString()));
- }
- return true;
- }
- }
-
- return false;
- }
-
- @WorkerThread
- private WorkspaceItemInfo loadShortcutWorker(ShortcutKey shortcutKey) {
- List<ShortcutInfo> details = shortcutKey.buildRequest(mContext).query(ShortcutRequest.ALL);
- if (!details.isEmpty()) {
- WorkspaceItemInfo si = new WorkspaceItemInfo(details.get(0), mContext);
- mIconCache.getShortcutIcon(si, details.get(0));
- return si;
- }
- if (DEBUG) {
- Log.d(TAG, "No shortcut found: " + shortcutKey.toString());
- }
- return null;
- }
-
- private InstantAppItemInfo loadInstantApp(String pkgName) {
- PackageManager pm = mContext.getPackageManager();
-
- try {
- ApplicationInfo ai = pm.getApplicationInfo(pkgName, 0);
- if (!mInstantAppResolver.isInstantApp(ai)) {
- return null;
- }
- } catch (PackageManager.NameNotFoundException e) {
- return null;
- }
-
- String url = retrieveDefaultUrl(pkgName, pm);
- if (url == null) {
- Log.w(TAG, "no default-url available for pkg " + pkgName);
- return null;
- }
-
- Intent intent = new Intent(Intent.ACTION_VIEW)
- .addCategory(Intent.CATEGORY_BROWSABLE)
- .setData(Uri.parse(url));
- InstantAppItemInfo info = new InstantAppItemInfo(intent, pkgName);
- IconCache iconCache = LauncherAppState.getInstance(mContext).getIconCache();
- iconCache.getTitleAndIcon(info, false);
- if (info.bitmap.icon == null || iconCache.isDefaultIcon(info.bitmap, info.user)) {
- return null;
- }
- return info;
- }
-
- @Nullable
- public static String retrieveDefaultUrl(String pkgName, PackageManager pm) {
- Intent mainIntent = new Intent().setAction(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_LAUNCHER).setPackage(pkgName);
- List<ResolveInfo> resolveInfos = pm.queryIntentActivities(
- mainIntent, MATCH_INSTANT | PackageManager.GET_META_DATA);
- String url = null;
- for (ResolveInfo resolveInfo : resolveInfos) {
- if (resolveInfo.activityInfo.metaData != null
- && resolveInfo.activityInfo.metaData.containsKey(DEFAULT_URL)) {
- url = resolveInfo.activityInfo.metaData.getString(DEFAULT_URL);
- }
- }
- return url;
- }
-
- @UiThread
- public InstantAppItemInfo getInstantApp(String pkgName) {
- return mInstantApps.get(pkgName);
- }
-
- @MainThread
- public WorkspaceItemInfo getShortcutInfo(ComponentKey key) {
- return mShortcuts.get(key);
- }
-
- /**
- * requests and caches icons for app targets
- */
- public void updateDependencies(List<ComponentKeyMapper> componentKeyMappers,
- AllAppsStore appsStore, IconCache.ItemInfoUpdateReceiver callback, int itemCount) {
- List<String> instantAppsToLoad = new ArrayList<>();
- List<ShortcutKey> shortcutsToLoad = new ArrayList<>();
- int total = componentKeyMappers.size();
- for (int i = 0, count = 0; i < total && count < itemCount; i++) {
- ComponentKeyMapper mapper = componentKeyMappers.get(i);
- // Update instant apps
- if (COMPONENT_CLASS_MARKER.equals(mapper.getComponentClass())) {
- instantAppsToLoad.add(mapper.getPackage());
- count++;
- } else if (mapper.getComponentKey() instanceof ShortcutKey) {
- shortcutsToLoad.add((ShortcutKey) mapper.getComponentKey());
- count++;
- } else {
- // Reload high res icon
- AppInfo info = (AppInfo) mapper.getApp(appsStore);
- if (info != null) {
- if (info.usingLowResIcon()) {
- mIconCache.updateIconInBackground(callback, info);
- }
- count++;
- }
- }
- }
- cacheItems(shortcutsToLoad, instantAppsToLoad);
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
deleted file mode 100644
index b94e633..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
+++ /dev/null
@@ -1,723 +0,0 @@
-/*
- * 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.
- */
-package com.android.launcher3.hybridhotseat;
-
-import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
-import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
-import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.hybridhotseat.HotseatEduController.getSettingsIntent;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.app.prediction.AppPredictionContext;
-import android.app.prediction.AppPredictionManager;
-import android.app.prediction.AppPredictor;
-import android.app.prediction.AppTarget;
-import android.app.prediction.AppTargetEvent;
-import android.content.ComponentName;
-import android.os.Process;
-import android.util.Log;
-import android.view.HapticFeedbackConstants;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.DragSource;
-import com.android.launcher3.DropTarget;
-import com.android.launcher3.Hotseat;
-import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsStore;
-import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.appprediction.ComponentKeyMapper;
-import com.android.launcher3.appprediction.DynamicItemCache;
-import com.android.launcher3.dragndrop.DragController;
-import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.icons.IconCache;
-import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
-import com.android.launcher3.logger.LauncherAtom.PredictedHotseatContainer;
-import com.android.launcher3.logging.InstanceId;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.FolderInfo;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.popup.SystemShortcut;
-import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.touch.ItemLongClickListener;
-import com.android.launcher3.uioverrides.PredictedAppIcon;
-import com.android.launcher3.uioverrides.QuickstepLauncher;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.OnboardingPrefs;
-import com.android.launcher3.views.ArrowTipView;
-import com.android.launcher3.views.Snackbar;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.OptionalInt;
-import java.util.stream.IntStream;
-
-/**
- * Provides prediction ability for the hotseat. Fills gaps in hotseat with predicted items, allows
- * pinning of predicted apps and manages replacement of predicted apps with user drag.
- */
-public class HotseatPredictionController implements DragController.DragListener,
- View.OnAttachStateChangeListener, SystemShortcut.Factory<QuickstepLauncher>,
- InvariantDeviceProfile.OnIDPChangeListener, AllAppsStore.OnUpdateListener,
- IconCache.ItemInfoUpdateReceiver, DragSource {
-
- private static final String TAG = "PredictiveHotseat";
- private static final boolean DEBUG = false;
-
- private static final String PREDICTION_CLIENT = "hotseat";
- private DropTarget.DragObject mDragObject;
- private int mHotSeatItemsCount;
- private int mPredictedSpotsCount = 0;
-
- private Launcher mLauncher;
- private final Hotseat mHotseat;
-
- private final HotseatRestoreHelper mRestoreHelper;
-
- private List<ComponentKeyMapper> mComponentKeyMappers = new ArrayList<>();
-
- private DynamicItemCache mDynamicItemCache;
-
- private final HotseatPredictionModel mPredictionModel;
- private AppPredictor mAppPredictor;
- private AllAppsStore mAllAppsStore;
- private AnimatorSet mIconRemoveAnimators;
- private boolean mUIUpdatePaused = false;
- private boolean mIsDestroyed = false;
-
-
- private List<PredictedAppIcon.PredictedIconOutlineDrawing> mOutlineDrawings = new ArrayList<>();
-
- private final View.OnLongClickListener mPredictionLongClickListener = v -> {
- if (!ItemLongClickListener.canStartDrag(mLauncher)) return false;
- if (mLauncher.getWorkspace().isSwitchingState()) return false;
- if (!mLauncher.getOnboardingPrefs().getBoolean(
- OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN)) {
- Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled,
- R.string.hotseat_prediction_settings, null,
- () -> mLauncher.startActivity(getSettingsIntent()));
- mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN);
- mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
- return true;
- }
- // Start the drag
- mLauncher.getWorkspace().beginDragShared(v, this, new DragOptions());
- return true;
- };
-
- public HotseatPredictionController(Launcher launcher) {
- mLauncher = launcher;
- mHotseat = launcher.getHotseat();
- mAllAppsStore = mLauncher.getAppsView().getAppsStore();
- LauncherAppState appState = LauncherAppState.getInstance(launcher);
- mPredictionModel = (HotseatPredictionModel) appState.getPredictionModel();
- mAllAppsStore.addUpdateListener(this);
- mDynamicItemCache = new DynamicItemCache(mLauncher, this::fillGapsWithPrediction);
- mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
- launcher.getDeviceProfile().inv.addOnChangeListener(this);
- mHotseat.addOnAttachStateChangeListener(this);
- mRestoreHelper = new HotseatRestoreHelper(mLauncher);
- if (mHotseat.isAttachedToWindow()) {
- onViewAttachedToWindow(mHotseat);
- }
- }
-
- /**
- * Shows appropriate hotseat education based on prediction enabled and migration states.
- */
- public void showEdu() {
- mLauncher.getStateManager().goToState(NORMAL, true, () -> {
- if (mComponentKeyMappers.isEmpty()) {
- // launcher has empty predictions set
- Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_disabled,
- R.string.hotseat_prediction_settings, null,
- () -> mLauncher.startActivity(getSettingsIntent()));
- } else if (getPredictedIcons().size() >= (mHotSeatItemsCount + 1) / 2) {
- showDiscoveryTip();
- } else {
- HotseatEduController eduController = new HotseatEduController(mLauncher,
- mRestoreHelper,
- this::createPredictor);
- eduController.setPredictedApps(mapToWorkspaceItemInfo(mComponentKeyMappers));
- eduController.showEdu();
- }
- });
- }
-
- /**
- * Shows educational tip for hotseat if user does not go through Tips app.
- */
- private void showDiscoveryTip() {
- if (getPredictedIcons().isEmpty()) {
- new ArrowTipView(mLauncher).show(
- mLauncher.getString(R.string.hotseat_tip_no_empty_slots), mHotseat.getTop());
- } else {
- Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled,
- R.string.hotseat_prediction_settings, null,
- () -> mLauncher.startActivity(getSettingsIntent()));
- }
- }
-
- /**
- * Returns if hotseat client has predictions
- */
- public boolean hasPredictions() {
- return !mComponentKeyMappers.isEmpty();
- }
-
- @Override
- public void onViewAttachedToWindow(View view) {
- mLauncher.getDragController().addDragListener(this);
- }
-
- @Override
- public void onViewDetachedFromWindow(View view) {
- mLauncher.getDragController().removeDragListener(this);
- }
-
- private void fillGapsWithPrediction() {
- fillGapsWithPrediction(false, null);
- }
-
- private void fillGapsWithPrediction(boolean animate, Runnable callback) {
- if (mUIUpdatePaused || mDragObject != null) {
- return;
- }
- List<WorkspaceItemInfo> predictedApps = mapToWorkspaceItemInfo(mComponentKeyMappers);
- if (mComponentKeyMappers.isEmpty() != predictedApps.isEmpty()) {
- // Safely ignore update as AppsList is not ready yet. This will called again once
- // apps are ready (HotseatPredictionController#onAppsUpdated)
- return;
- }
- int predictionIndex = 0;
- ArrayList<WorkspaceItemInfo> newItems = new ArrayList<>();
- // make sure predicted icon removal and filling predictions don't step on each other
- if (mIconRemoveAnimators != null && mIconRemoveAnimators.isRunning()) {
- mIconRemoveAnimators.addListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- fillGapsWithPrediction(animate, callback);
- mIconRemoveAnimators.removeListener(this);
- }
- });
- return;
- }
- for (int rank = 0; rank < mHotSeatItemsCount; rank++) {
- View child = mHotseat.getChildAt(
- mHotseat.getCellXFromOrder(rank),
- mHotseat.getCellYFromOrder(rank));
-
- if (child != null && !isPredictedIcon(child)) {
- continue;
- }
- if (predictedApps.size() <= predictionIndex) {
- // Remove predicted apps from the past
- if (isPredictedIcon(child)) {
- mHotseat.removeView(child);
- }
- continue;
- }
- WorkspaceItemInfo predictedItem = predictedApps.get(predictionIndex++);
- if (isPredictedIcon(child) && child.isEnabled()) {
- PredictedAppIcon icon = (PredictedAppIcon) child;
- icon.applyFromWorkspaceItem(predictedItem);
- icon.finishBinding(mPredictionLongClickListener);
- } else {
- newItems.add(predictedItem);
- }
- preparePredictionInfo(predictedItem, rank);
- }
- mPredictedSpotsCount = predictionIndex;
- bindItems(newItems, animate, callback);
- }
-
- private void bindItems(List<WorkspaceItemInfo> itemsToAdd, boolean animate, Runnable callback) {
- AnimatorSet animationSet = new AnimatorSet();
- for (WorkspaceItemInfo item : itemsToAdd) {
- PredictedAppIcon icon = PredictedAppIcon.createIcon(mHotseat, item);
- mLauncher.getWorkspace().addInScreenFromBind(icon, item);
- icon.finishBinding(mPredictionLongClickListener);
- if (animate) {
- animationSet.play(ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 0.2f, 1));
- }
- }
- if (animate) {
- if (callback != null) {
- animationSet.addListener(AnimationSuccessListener.forRunnable(callback));
- }
- animationSet.start();
- } else {
- if (callback != null) callback.run();
- }
- }
-
- /**
- * Unregisters callbacks and frees resources
- */
- public void destroy() {
- mIsDestroyed = true;
- mAllAppsStore.removeUpdateListener(this);
- mLauncher.getDeviceProfile().inv.removeOnChangeListener(this);
- mHotseat.removeOnAttachStateChangeListener(this);
- if (mAppPredictor != null) {
- mAppPredictor.destroy();
- }
- }
-
- /**
- * start and pauses predicted apps update on the hotseat
- */
- public void setPauseUIUpdate(boolean paused) {
- mUIUpdatePaused = paused;
- if (!paused) {
- fillGapsWithPrediction();
- }
- }
-
- /**
- * Creates App Predictor with all the current apps pinned on the hotseat
- */
- public void createPredictor() {
- AppPredictionManager apm = mLauncher.getSystemService(AppPredictionManager.class);
- if (apm == null) {
- return;
- }
- if (mAppPredictor != null) {
- mAppPredictor.destroy();
- mAppPredictor = null;
- }
- WeakReference<HotseatPredictionController> controllerRef = new WeakReference<>(this);
-
-
- mPredictionModel.createBundle(bundle -> {
- if (mIsDestroyed) return;
- mAppPredictor = apm.createAppPredictionSession(
- new AppPredictionContext.Builder(mLauncher)
- .setUiSurface(PREDICTION_CLIENT)
- .setPredictedTargetCount(mHotSeatItemsCount)
- .setExtras(bundle)
- .build());
- mAppPredictor.registerPredictionUpdates(
- mLauncher.getApplicationContext().getMainExecutor(),
- list -> {
- if (controllerRef.get() != null) {
- controllerRef.get().setPredictedApps(list);
- }
- });
- mAppPredictor.requestPredictionUpdate();
- });
- setPauseUIUpdate(false);
- }
-
- /**
- * Create WorkspaceItemInfo objects and binds PredictedAppIcon views for cached predicted items.
- */
- public void showCachedItems(List<AppInfo> apps, IntArray ranks) {
- if (hasPredictions() && mAppPredictor != null) {
- mAppPredictor.requestPredictionUpdate();
- fillGapsWithPrediction();
- return;
- }
- int count = Math.min(ranks.size(), apps.size());
- List<WorkspaceItemInfo> items = new ArrayList<>(count);
- for (int i = 0; i < count; i++) {
- WorkspaceItemInfo item = new WorkspaceItemInfo(apps.get(i));
- ComponentKey componentKey = new ComponentKey(item.getTargetComponent(), item.user);
- preparePredictionInfo(item, ranks.get(i));
- items.add(item);
-
- mComponentKeyMappers.add(new ComponentKeyMapper(componentKey, mDynamicItemCache));
- }
- updateDependencies();
- bindItems(items, false, null);
- }
-
- private void setPredictedApps(List<AppTarget> appTargets) {
- mComponentKeyMappers.clear();
- if (appTargets.isEmpty()) {
- mRestoreHelper.restoreBackup();
- }
- StringBuilder predictionLog = new StringBuilder("predictedApps: [\n");
- ArrayList<ComponentKey> componentKeys = new ArrayList<>();
- for (AppTarget appTarget : appTargets) {
- ComponentKey key;
- if (appTarget.getShortcutInfo() != null) {
- key = ShortcutKey.fromInfo(appTarget.getShortcutInfo());
- } else {
- key = new ComponentKey(new ComponentName(appTarget.getPackageName(),
- appTarget.getClassName()), appTarget.getUser());
- }
- componentKeys.add(key);
- predictionLog.append(key.toString());
- predictionLog.append(",rank:");
- predictionLog.append(appTarget.getRank());
- predictionLog.append("\n");
- mComponentKeyMappers.add(new ComponentKeyMapper(key, mDynamicItemCache));
- }
- predictionLog.append("]");
- if (Utilities.IS_DEBUG_DEVICE) {
- HotseatFileLog.INSTANCE.get(mLauncher).log(TAG, predictionLog.toString());
- }
- updateDependencies();
- fillGapsWithPrediction();
- mPredictionModel.cachePredictionComponentKeys(componentKeys);
- }
-
- private void updateDependencies() {
- mDynamicItemCache.updateDependencies(mComponentKeyMappers, mAllAppsStore, this,
- mHotSeatItemsCount);
- }
-
- /**
- * Pins a predicted app icon into place.
- */
- public void pinPrediction(ItemInfo info) {
- PredictedAppIcon icon = (PredictedAppIcon) mHotseat.getChildAt(
- mHotseat.getCellXFromOrder(info.rank),
- mHotseat.getCellYFromOrder(info.rank));
- if (icon == null) {
- return;
- }
- WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo((WorkspaceItemInfo) info);
- mLauncher.getModelWriter().addItemToDatabase(workspaceItemInfo,
- LauncherSettings.Favorites.CONTAINER_HOTSEAT, workspaceItemInfo.screenId,
- workspaceItemInfo.cellX, workspaceItemInfo.cellY);
- ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 1, 0.8f, 1).start();
- icon.pin(workspaceItemInfo);
- AppTarget appTarget = mPredictionModel.getAppTargetFromInfo(workspaceItemInfo);
- if (appTarget != null) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(appTarget,
- AppTargetEvent.ACTION_PIN, workspaceItemInfo));
- }
- }
-
- private List<WorkspaceItemInfo> mapToWorkspaceItemInfo(
- List<ComponentKeyMapper> components) {
- AllAppsStore allAppsStore = mLauncher.getAppsView().getAppsStore();
- if (allAppsStore.getApps().length == 0) {
- return Collections.emptyList();
- }
-
- List<WorkspaceItemInfo> predictedApps = new ArrayList<>();
- for (ComponentKeyMapper mapper : components) {
- ItemInfoWithIcon info = mapper.getApp(allAppsStore);
- if (info instanceof AppInfo) {
- WorkspaceItemInfo predictedApp = new WorkspaceItemInfo((AppInfo) info);
- predictedApp.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
- predictedApps.add(predictedApp);
- } else if (info instanceof WorkspaceItemInfo) {
- WorkspaceItemInfo predictedApp = new WorkspaceItemInfo((WorkspaceItemInfo) info);
- predictedApp.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
- predictedApps.add(predictedApp);
- } else {
- if (DEBUG) {
- Log.e(TAG, "Predicted app not found: " + mapper);
- }
- }
- // Stop at the number of hotseat items
- if (predictedApps.size() == mHotSeatItemsCount) {
- break;
- }
- }
- return predictedApps;
- }
-
- private List<PredictedAppIcon> getPredictedIcons() {
- List<PredictedAppIcon> icons = new ArrayList<>();
- ViewGroup vg = mHotseat.getShortcutsAndWidgets();
- for (int i = 0; i < vg.getChildCount(); i++) {
- View child = vg.getChildAt(i);
- if (isPredictedIcon(child)) {
- icons.add((PredictedAppIcon) child);
- }
- }
- return icons;
- }
-
- private void removePredictedApps(List<PredictedAppIcon.PredictedIconOutlineDrawing> outlines,
- ItemInfo draggedInfo) {
- if (mIconRemoveAnimators != null) {
- mIconRemoveAnimators.end();
- }
- mIconRemoveAnimators = new AnimatorSet();
- removeOutlineDrawings();
- for (PredictedAppIcon icon : getPredictedIcons()) {
- if (!icon.isEnabled()) {
- continue;
- }
- if (icon.getTag().equals(draggedInfo)) {
- mHotseat.removeView(icon);
- continue;
- }
- int rank = ((WorkspaceItemInfo) icon.getTag()).rank;
- outlines.add(new PredictedAppIcon.PredictedIconOutlineDrawing(
- mHotseat.getCellXFromOrder(rank), mHotseat.getCellYFromOrder(rank), icon));
- icon.setEnabled(false);
- ObjectAnimator animator = ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 0);
- animator.addListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- if (icon.getParent() != null) {
- mHotseat.removeView(icon);
- }
- }
- });
- mIconRemoveAnimators.play(animator);
- }
- mIconRemoveAnimators.start();
- }
-
- private void notifyItemAction(AppTargetEvent event) {
- if (mAppPredictor != null) {
- mAppPredictor.notifyAppTargetEvent(event);
- }
- }
-
- @Override
- public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
- removePredictedApps(mOutlineDrawings, dragObject.dragInfo);
- mDragObject = dragObject;
- if (mOutlineDrawings.isEmpty()) return;
- for (PredictedAppIcon.PredictedIconOutlineDrawing outlineDrawing : mOutlineDrawings) {
- mHotseat.addDelegatedCellDrawing(outlineDrawing);
- }
- mHotseat.invalidate();
- }
-
- /**
- * Unpins pinned app when it's converted into a folder
- */
- public void folderCreatedFromWorkspaceItem(ItemInfo itemInfo, FolderInfo folderInfo) {
- AppTarget folderTarget = mPredictionModel.getAppTargetFromInfo(folderInfo);
- AppTarget itemTarget = mPredictionModel.getAppTargetFromInfo(itemInfo);
- if (folderTarget != null && HotseatPredictionModel.isTrackedForPrediction(folderInfo)) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(folderTarget,
- AppTargetEvent.ACTION_PIN, folderInfo));
- }
- // using folder info with isTrackedForPrediction as itemInfo.container is already changed
- // to folder by this point
- if (itemTarget != null && HotseatPredictionModel.isTrackedForPrediction(folderInfo)) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(itemTarget,
- AppTargetEvent.ACTION_UNPIN, folderInfo
- ));
- }
- }
-
- /**
- * Pins workspace item created when all folder items are removed but one
- */
- public void folderConvertedToWorkspaceItem(ItemInfo itemInfo, FolderInfo folderInfo) {
- AppTarget folderTarget = mPredictionModel.getAppTargetFromInfo(folderInfo);
- AppTarget itemTarget = mPredictionModel.getAppTargetFromInfo(itemInfo);
- if (folderTarget != null && HotseatPredictionModel.isTrackedForPrediction(folderInfo)) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(folderTarget,
- AppTargetEvent.ACTION_UNPIN, folderInfo));
- }
- if (itemTarget != null && HotseatPredictionModel.isTrackedForPrediction(itemInfo)) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(itemTarget,
- AppTargetEvent.ACTION_PIN, itemInfo));
- }
- }
-
- @Override
- public void onDragEnd() {
- if (mDragObject == null) {
- return;
- }
-
- ItemInfo dragInfo = mDragObject.dragInfo;
- if (mDragObject.isMoved()) {
- AppTarget appTarget = mPredictionModel.getAppTargetFromInfo(dragInfo);
- //always send pin event first to prevent AiAi from predicting an item moved within
- // the same page
- if (appTarget != null && HotseatPredictionModel.isTrackedForPrediction(dragInfo)) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(appTarget,
- AppTargetEvent.ACTION_PIN, dragInfo));
- }
- if (appTarget != null && HotseatPredictionModel.isTrackedForPrediction(
- mDragObject.originalDragInfo)) {
- notifyItemAction(mPredictionModel.wrapAppTargetWithLocation(appTarget,
- AppTargetEvent.ACTION_UNPIN, mDragObject.originalDragInfo));
- }
- }
- mDragObject = null;
- fillGapsWithPrediction(true, this::removeOutlineDrawings);
- }
-
-
- @Nullable
- @Override
- public SystemShortcut<QuickstepLauncher> getShortcut(QuickstepLauncher activity,
- ItemInfo itemInfo) {
- if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
- return null;
- }
- return new PinPrediction(activity, itemInfo);
- }
-
- private void preparePredictionInfo(WorkspaceItemInfo itemInfo, int rank) {
- itemInfo.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
- itemInfo.rank = rank;
- itemInfo.cellX = mHotseat.getCellXFromOrder(rank);
- itemInfo.cellY = mHotseat.getCellYFromOrder(rank);
- itemInfo.screenId = rank;
- }
-
- private void removeOutlineDrawings() {
- if (mOutlineDrawings.isEmpty()) return;
- for (PredictedAppIcon.PredictedIconOutlineDrawing outlineDrawing : mOutlineDrawings) {
- mHotseat.removeDelegatedCellDrawing(outlineDrawing);
- }
- mHotseat.invalidate();
- mOutlineDrawings.clear();
- }
-
- @Override
- public void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
- if ((changeFlags & CHANGE_FLAG_GRID) != 0) {
- this.mHotSeatItemsCount = profile.numHotseatIcons;
- createPredictor();
- }
- }
-
- @Override
- public void onAppsUpdated() {
- fillGapsWithPrediction();
- }
-
- @Override
- public void reapplyItemInfo(ItemInfoWithIcon info) {
- }
-
- @Override
- public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) {
- //Does nothing
- }
-
- @Override
- public void fillInLogContainerData(ItemInfo childInfo, LauncherLogProto.Target child,
- ArrayList<LauncherLogProto.Target> parents) {
- mHotseat.fillInLogContainerData(childInfo, child, parents);
- }
-
- /**
- * Logs rank info based on current list of predicted items
- */
- public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
- if (Utilities.IS_DEBUG_DEVICE) {
- final String pkg = itemInfo.getTargetComponent() != null
- ? itemInfo.getTargetComponent().getPackageName() : "unknown";
- HotseatFileLog.INSTANCE.get(mLauncher).log("UserEvent",
- "appLaunch: packageName:" + pkg + ",isWorkApp:" + (itemInfo.user != null
- && !Process.myUserHandle().equals(itemInfo.user))
- + ",launchLocation:" + itemInfo.container);
- }
-
- if (itemInfo.getTargetComponent() == null || itemInfo.user == null) {
- return;
- }
-
- final ComponentKey key = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
-
- final List<ComponentKeyMapper> predictedApps = new ArrayList<>(mComponentKeyMappers);
- OptionalInt rank = IntStream.range(0, predictedApps.size())
- .filter(index -> key.equals(predictedApps.get(index).getComponentKey()))
- .findFirst();
- if (!rank.isPresent()) {
- return;
- }
-
- int cardinality = 0;
- for (PredictedAppIcon icon : getPredictedIcons()) {
- ItemInfo info = (ItemInfo) icon.getTag();
- cardinality |= 1 << info.screenId;
- }
-
- PredictedHotseatContainer.Builder containerBuilder = PredictedHotseatContainer.newBuilder();
- containerBuilder.setCardinality(cardinality);
- if (itemInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
- containerBuilder.setIndex(rank.getAsInt());
- }
- mLauncher.getStatsLogManager().logger()
- .withInstanceId(instanceId)
- .withRank(rank.getAsInt())
- .withContainerInfo(ContainerInfo.newBuilder()
- .setPredictedHotseatContainer(containerBuilder)
- .build())
- .log(LAUNCHER_HOTSEAT_RANKED);
- }
-
- private class PinPrediction extends SystemShortcut<QuickstepLauncher> {
-
- private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo) {
- super(R.drawable.ic_pin, R.string.pin_prediction, target,
- itemInfo);
- }
-
- @Override
- public void onClick(View view) {
- dismissTaskMenuView(mTarget);
- pinPrediction(mItemInfo);
- }
- }
-
- /**
- * Fill in predicted_rank field based on app prediction.
- * Only applicable when {@link ItemInfo#itemType} is PREDICTED_HOTSEAT
- */
- public static void encodeHotseatLayoutIntoPredictionRank(
- @NonNull ItemInfo itemInfo, @NonNull LauncherLogProto.Target target) {
- QuickstepLauncher launcher = QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
- if (launcher == null || launcher.getHotseatPredictionController() == null
- || itemInfo.getTargetComponent() == null) {
- return;
- }
- HotseatPredictionController controller = launcher.getHotseatPredictionController();
-
- final ComponentKey k = new ComponentKey(itemInfo.getTargetComponent(), itemInfo.user);
-
- final List<ComponentKeyMapper> predictedApps = controller.mComponentKeyMappers;
- OptionalInt rank = IntStream.range(0, predictedApps.size())
- .filter((i) -> k.equals(predictedApps.get(i).getComponentKey()))
- .findFirst();
-
- target.predictedRank = 10000 + (controller.mPredictedSpotsCount * 100)
- + (rank.isPresent() ? rank.getAsInt() + 1 : 0);
- }
-
- private static boolean isPredictedIcon(View view) {
- return view instanceof PredictedAppIcon && view.getTag() instanceof WorkspaceItemInfo
- && ((WorkspaceItemInfo) view.getTag()).container
- == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
deleted file mode 100644
index fc9a11b..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewPeekState.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.
- */
-package com.android.launcher3.uioverrides.states;
-
-import com.android.launcher3.Launcher;
-
-public class OverviewPeekState extends OverviewState {
- private static final float OVERVIEW_OFFSET = 0.7f;
-
- public OverviewPeekState(int id) {
- super(id);
- }
-
- @Override
- public float[] getOverviewScaleAndOffset(Launcher launcher) {
- return new float[] {NO_SCALE, OVERVIEW_OFFSET};
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
deleted file mode 100644
index fac478e..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.launcher3.uioverrides.touchcontrollers;
-
-import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
-import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
-import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_PEEK;
-import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
-import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM;
-import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherState;
-import com.android.launcher3.anim.AnimationSuccessListener;
-import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.states.StateAnimationConfig;
-import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
-import com.android.launcher3.testing.TestProtocol;
-import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
-import com.android.launcher3.util.VibratorWrapper;
-import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.util.MotionPauseDetector;
-import com.android.quickstep.views.RecentsView;
-
-/**
- * Touch controller which handles swipe and hold to go to Overview
- */
-public class FlingAndHoldTouchController extends PortraitStatesTouchController {
-
- private static final long PEEK_IN_ANIM_DURATION = 240;
- private static final long PEEK_OUT_ANIM_DURATION = 100;
- private static final float MAX_DISPLACEMENT_PERCENT = 0.75f;
-
- protected final MotionPauseDetector mMotionPauseDetector;
- private final float mMotionPauseMinDisplacement;
- private final float mMotionPauseMaxDisplacement;
-
- private AnimatorSet mPeekAnim;
-
- public FlingAndHoldTouchController(Launcher l) {
- super(l, false /* allowDragToOverview */);
- mMotionPauseDetector = new MotionPauseDetector(l);
- mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
- mMotionPauseMaxDisplacement = getMotionPauseMaxDisplacement();
- }
-
- protected float getMotionPauseMaxDisplacement() {
- return getShiftRange() * MAX_DISPLACEMENT_PERCENT;
- }
-
- @Override
- protected long getAtomicDuration() {
- return QuickstepAtomicAnimationFactory.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
- }
-
- @Override
- public void onDragStart(boolean start, float startDisplacement) {
- mMotionPauseDetector.clear();
-
- super.onDragStart(start, startDisplacement);
-
- if (handlingOverviewAnim()) {
- mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
- }
-
- if (mAtomicAnim != null) {
- mAtomicAnim.cancel();
- }
- }
-
- protected void onMotionPauseChanged(boolean isPaused) {
- RecentsView recentsView = mLauncher.getOverviewPanel();
- recentsView.setOverviewStateEnabled(isPaused);
- if (mPeekAnim != null) {
- mPeekAnim.cancel();
- }
- LauncherState fromState = isPaused ? NORMAL : OVERVIEW_PEEK;
- LauncherState toState = isPaused ? OVERVIEW_PEEK : NORMAL;
- long peekDuration = isPaused ? PEEK_IN_ANIM_DURATION : PEEK_OUT_ANIM_DURATION;
-
- StateAnimationConfig config = new StateAnimationConfig();
- config.duration = peekDuration;
- config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
- mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
- fromState, toState, config);
- mPeekAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mPeekAnim = null;
- }
- });
- mPeekAnim.start();
- VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
-
- mLauncher.getDragLayer().getScrim().createSysuiMultiplierAnim(isPaused ? 0 : 1)
- .setDuration(peekDuration).start();
- }
-
- /**
- * @return Whether we are handling the overview animation, rather than
- * having it as part of the existing animation to the target state.
- */
- protected boolean handlingOverviewAnim() {
- int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
- return mStartState == NORMAL && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
- }
-
- @Override
- protected StateAnimationConfig getConfigForStates(
- LauncherState fromState, LauncherState toState) {
- if (fromState == NORMAL && toState == ALL_APPS) {
- StateAnimationConfig builder = new StateAnimationConfig();
- // Fade in prediction icons quickly, then rest of all apps after reaching overview.
- float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
- - OVERVIEW.getVerticalProgress(mLauncher);
- builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
- ACCEL,
- 0,
- ALL_APPS_CONTENT_FADE_THRESHOLD));
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
- ACCEL,
- progressToReachOverview,
- progressToReachOverview + ALL_APPS_CONTENT_FADE_THRESHOLD));
-
- // Get workspace out of the way quickly, to prepare for potential pause.
- builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
- builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
- builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
- return builder;
- } else if (fromState == ALL_APPS && toState == NORMAL) {
- StateAnimationConfig builder = new StateAnimationConfig();
- // Keep all apps/predictions opaque until the very end of the transition.
- float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
- builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
- DEACCEL,
- progressToReachOverview - ALL_APPS_CONTENT_FADE_THRESHOLD,
- progressToReachOverview));
- builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
- DEACCEL,
- 1 - ALL_APPS_CONTENT_FADE_THRESHOLD,
- 1));
- return builder;
- }
- return super.getConfigForStates(fromState, toState);
- }
-
- @Override
- public boolean onDrag(float displacement, MotionEvent event) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.PAUSE_NOT_DETECTED, "FlingAndHoldTouchController");
- }
- float upDisplacement = -displacement;
- mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
- || upDisplacement < mMotionPauseMinDisplacement
- || upDisplacement > mMotionPauseMaxDisplacement);
- mMotionPauseDetector.addPosition(event);
- return super.onDrag(displacement, event);
- }
-
- @Override
- public void onDragEnd(float velocity) {
- if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
- goToOverviewOnDragEnd(velocity);
- } else {
- super.onDragEnd(velocity);
- }
-
- View searchView = mLauncher.getAppsView().getSearchView();
- if (searchView instanceof FeedbackHandler) {
- ((FeedbackHandler) searchView).resetFeedback();
- }
- mMotionPauseDetector.clear();
- }
-
- protected void goToOverviewOnDragEnd(float velocity) {
- if (mPeekAnim != null) {
- mPeekAnim.cancel();
- }
-
- Animator overviewAnim = mLauncher.createAtomicAnimationFactory()
- .createStateElementAnimation(INDEX_PAUSE_TO_OVERVIEW_ANIM);
- mAtomicAnim = new AnimatorSet();
- mAtomicAnim.addListener(new AnimationSuccessListener() {
- @Override
- public void onAnimationSuccess(Animator animator) {
- onSwipeInteractionCompleted(OVERVIEW, Touch.SWIPE);
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- if (mCancelled) {
- StateAnimationConfig config = new StateAnimationConfig();
- config.animFlags = PLAY_ATOMIC_OVERVIEW_PEEK;
- config.duration = PEEK_OUT_ANIM_DURATION;
- mPeekAnim = mLauncher.getStateManager().createAtomicAnimation(
- mFromState, mToState, config);
- mPeekAnim.start();
- }
- mAtomicAnim = null;
- }
- });
- mAtomicAnim.play(overviewAnim);
- mAtomicAnim.start();
- }
-
- @Override
- protected void goToTargetState(LauncherState targetState, int logAction) {
- if (mPeekAnim != null && mPeekAnim.isStarted()) {
- // Don't jump to the target state until overview is no longer peeking.
- mPeekAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- FlingAndHoldTouchController.super.goToTargetState(targetState, logAction);
- }
- });
- } else {
- super.goToTargetState(targetState, logAction);
- }
- }
-
- @Override
- @AnimationFlags
- protected int updateAnimComponentsOnReinit(@AnimationFlags int animComponents) {
- if (handlingOverviewAnim()) {
- // We don't want the state transition to all apps to animate overview,
- // as that will cause a jump after our atomic animation.
- return animComponents | SKIP_OVERVIEW;
- } else {
- return animComponents;
- }
- }
-
- /**
- * Interface for views with feedback animation requiring reset
- */
- public interface FeedbackHandler {
-
- /**
- * reset searchWidget feedback
- */
- void resetFeedback();
- }
-
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java
deleted file mode 100644
index 85006da..0000000
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ShelfPeekAnim.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.
- */
-package com.android.quickstep.util;
-
-import static com.android.launcher3.LauncherState.BACKGROUND_APP;
-import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
-import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.view.animation.Interpolator;
-
-import com.android.launcher3.Launcher;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.uioverrides.states.OverviewState;
-
-/**
- * Animates the shelf between states HIDE, PEEK, and OVERVIEW.
- */
-public class ShelfPeekAnim {
-
- public static final Interpolator INTERPOLATOR = OVERSHOOT_1_2;
- public static final long DURATION = 240;
-
- private final Launcher mLauncher;
-
- private ShelfAnimState mShelfState;
- private boolean mIsPeeking;
-
- public ShelfPeekAnim(Launcher launcher) {
- mLauncher = launcher;
- }
-
- /**
- * Animates to the given state, canceling the previous animation if it was still running.
- */
- public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
- if (mShelfState == shelfState || FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
- return;
- }
- mLauncher.getStateManager().cancelStateElementAnimation(INDEX_SHELF_ANIM);
- mShelfState = shelfState;
- mIsPeeking = mShelfState == ShelfAnimState.PEEK || mShelfState == ShelfAnimState.HIDE;
- if (mShelfState == ShelfAnimState.CANCEL) {
- return;
- }
- float shelfHiddenProgress = BACKGROUND_APP.getVerticalProgress(mLauncher);
- float shelfOverviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
- // Peek based on default overview progress so we can see hotseat if we're showing
- // that instead of predictions in overview.
- float defaultOverviewProgress = OverviewState.getDefaultVerticalProgress(mLauncher);
- float shelfPeekingProgress = shelfHiddenProgress
- - (shelfHiddenProgress - defaultOverviewProgress) * 0.25f;
- float toProgress = mShelfState == ShelfAnimState.HIDE
- ? shelfHiddenProgress
- : mShelfState == ShelfAnimState.PEEK
- ? shelfPeekingProgress
- : shelfOverviewProgress;
- Animator shelfAnim = mLauncher.getStateManager()
- .createStateElementAnimation(INDEX_SHELF_ANIM, toProgress);
- shelfAnim.setInterpolator(interpolator);
- shelfAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationCancel(Animator animation) {
- mShelfState = ShelfAnimState.CANCEL;
- }
-
- @Override
- public void onAnimationEnd(Animator animator) {
- mIsPeeking = mShelfState == ShelfAnimState.PEEK;
- }
- });
- shelfAnim.setDuration(duration).start();
- }
-
- /** @return Whether the shelf is currently peeking or animating to or from peeking. */
- public boolean isPeeking() {
- return mIsPeeking;
- }
-
- /** The various shelf states we can animate to. */
- public enum ShelfAnimState {
- HIDE(true), PEEK(true), OVERVIEW(false), CANCEL(false);
-
- ShelfAnimState(boolean shouldPreformHaptic) {
- this.shouldPreformHaptic = shouldPreformHaptic;
- }
-
- public final boolean shouldPreformHaptic;
- }
-}
diff --git a/quickstep/recents_ui_overrides/res/drawable/all_apps_edu_circle.xml b/quickstep/res/drawable/all_apps_edu_circle.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/drawable/all_apps_edu_circle.xml
rename to quickstep/res/drawable/all_apps_edu_circle.xml
diff --git a/quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml b/quickstep/res/drawable/chip_hint_background_light.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/drawable/chip_hint_background_light.xml
rename to quickstep/res/drawable/chip_hint_background_light.xml
diff --git a/quickstep/recents_ui_overrides/res/drawable/chip_scrim_gradient.xml b/quickstep/res/drawable/chip_scrim_gradient.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/drawable/chip_scrim_gradient.xml
rename to quickstep/res/drawable/chip_scrim_gradient.xml
diff --git a/quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml b/quickstep/res/drawable/hotseat_edu_notification_icon.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/drawable/hotseat_edu_notification_icon.xml
rename to quickstep/res/drawable/hotseat_edu_notification_icon.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/all_apps_edu_view.xml b/quickstep/res/layout/all_apps_edu_view.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/layout/all_apps_edu_view.xml
rename to quickstep/res/layout/all_apps_edu_view.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml
rename to quickstep/res/layout/fallback_recents_activity.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/floating_header_content.xml b/quickstep/res/layout/floating_header_content.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/layout/floating_header_content.xml
rename to quickstep/res/layout/floating_header_content.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/layout/overview_panel.xml
rename to quickstep/res/layout/overview_panel.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/predicted_app_icon.xml b/quickstep/res/layout/predicted_app_icon.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/layout/predicted_app_icon.xml
rename to quickstep/res/layout/predicted_app_icon.xml
diff --git a/quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml b/quickstep/res/layout/predicted_hotseat_edu.xml
similarity index 100%
rename from quickstep/recents_ui_overrides/res/layout/predicted_hotseat_edu.xml
rename to quickstep/res/layout/predicted_hotseat_edu.xml
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 40da136..449fe10 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -16,4 +16,12 @@
<resources>
<color name="back_arrow_color_light">#FFFFFFFF</color>
<color name="back_arrow_color_dark">#99000000</color>
+
+ <color name="chip_hint_foreground_color">#fff</color>
+ <color name="chip_scrim_start_color">#39000000</color>
+
+ <color name="all_apps_label_text">#61000000</color>
+ <color name="all_apps_label_text_dark">#61FFFFFF</color>
+ <color name="all_apps_prediction_row_separator">#3c000000</color>
+ <color name="all_apps_prediction_row_separator_dark">#3cffffff</color>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index a57112b..9ec303a 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -37,4 +37,6 @@
<integer name="assistant_gesture_corner_deg_threshold">20</integer>
<string name="wellbeing_provider_pkg" translatable="false"/>
+
+ <integer name="max_depth_blur_radius">150</integer>
</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 6737c5f..313db8c 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -30,7 +30,6 @@
<dimen name="recents_page_spacing">10dp</dimen>
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
- <dimen name="overview_peek_distance">96dp</dimen>
<!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
loading full resolution screenshots. -->
@@ -102,4 +101,26 @@
<dimen name="swipe_edu_circle_size">64dp</dimen>
<dimen name="swipe_edu_width">80dp</dimen>
<dimen name="swipe_edu_max_height">184dp</dimen>
+
+ <dimen name="chip_hint_border_width">1dp</dimen>
+ <dimen name="chip_hint_corner_radius">20dp</dimen>
+ <dimen name="chip_hint_outer_padding">20dp</dimen>
+ <dimen name="chip_hint_start_padding">10dp</dimen>
+ <dimen name="chip_hint_end_padding">12dp</dimen>
+ <dimen name="chip_hint_horizontal_margin">20dp</dimen>
+ <dimen name="chip_hint_vertical_offset">16dp</dimen>
+ <dimen name="chip_hint_elevation">2dp</dimen>
+ <dimen name="chip_icon_size">16dp</dimen>
+ <dimen name="chip_text_height">26dp</dimen>
+ <dimen name="chip_text_top_padding">4dp</dimen>
+ <dimen name="chip_text_start_padding">10dp</dimen>
+ <dimen name="chip_text_size">14sp</dimen>
+
+ <dimen name="all_apps_prediction_row_divider_height">17dp</dimen>
+ <dimen name="all_apps_label_top_padding">16dp</dimen>
+ <dimen name="all_apps_label_bottom_padding">8dp</dimen>
+ <dimen name="all_apps_label_text_size">14sp</dimen>
+
+ <!-- Minimum distance to swipe to trigger accessibility gesture -->
+ <dimen name="accessibility_gesture_min_swipe_distance">80dp</dimen>
</resources>
diff --git a/quickstep/recents_ui_overrides/res/values/override.xml b/quickstep/res/values/override.xml
similarity index 92%
rename from quickstep/recents_ui_overrides/res/values/override.xml
rename to quickstep/res/values/override.xml
index 1937164..8f4ce43 100644
--- a/quickstep/recents_ui_overrides/res/values/override.xml
+++ b/quickstep/res/values/override.xml
@@ -27,9 +27,6 @@
<string name="user_event_dispatcher_class" translatable="false">com.android.quickstep.logging.UserEventDispatcherExtension</string>
- <string name="prediction_model_class" translatable="false">com.android.launcher3.hybridhotseat.HotseatPredictionModel</string>
-
<string name="model_delegate_class" translatable="false">com.android.launcher3.model.QuickstepModelDelegate</string>
</resources>
-
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 235df42..68111d2 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -26,12 +26,10 @@
import android.animation.ValueAnimator;
import android.content.Intent;
import android.content.IntentSender;
-import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CancellationSignal;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.model.WellbeingModel;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.proxy.ProxyActivityStarter;
@@ -40,17 +38,14 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.uioverrides.RecentsViewStateController;
-import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
import com.android.quickstep.SystemUiProxy;
-import com.android.quickstep.util.QuickstepOnboardingPrefs;
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
-import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -73,10 +68,7 @@
(context, arg1, arg2) -> SystemUiProxy.INSTANCE.get(context).setBackButtonAlpha(
Float.intBitsToFloat(arg1), arg2 != 0);
- private final ShelfPeekAnim mShelfPeekAnim = new ShelfPeekAnim(this);
-
private OverviewActionsView mActionsView;
- protected HotseatPredictionController mHotseatPredictionController;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -196,7 +188,7 @@
}
private boolean isOverviewActionsEnabled() {
- return FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this);
+ return removeShelfFromOverview(this);
}
public <T extends OverviewActionsView> T getActionsView() {
@@ -225,11 +217,6 @@
}
@Override
- protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
- return new QuickstepOnboardingPrefs(this, sharedPrefs);
- }
-
- @Override
public void useFadeOutAnimationForLauncherStart(CancellationSignal signal) {
QuickstepAppTransitionManagerImpl appTransitionManager =
(QuickstepAppTransitionManagerImpl) getAppTransitionManager();
@@ -317,17 +304,6 @@
Stream.of(WellbeingModel.SHORTCUT_FACTORY));
}
- public ShelfPeekAnim getShelfPeekAnim() {
- return mShelfPeekAnim;
- }
-
- /**
- * Returns Prediction controller for hybrid hotseat
- */
- public HotseatPredictionController getHotseatPredictionController() {
- return mHotseatPredictionController;
- }
-
public void setHintUserWillBeActive() {
addActivityFlags(ACTIVITY_STATE_USER_WILL_BE_ACTIVE);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
rename to quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AllAppsTipView.java b/quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java
similarity index 91%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AllAppsTipView.java
rename to quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java
index 8477b10..98bf483 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AllAppsTipView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java
@@ -19,7 +19,6 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_DISCOVERY_BOUNCE;
import static com.android.launcher3.AbstractFloatingView.TYPE_ON_BOARD_POPUP;
import static com.android.launcher3.LauncherState.ALL_APPS;
-import static com.android.quickstep.logging.UserEventDispatcherExtension.ALL_APPS_PREDICTION_TIPS;
import android.os.UserManager;
@@ -31,7 +30,6 @@
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.views.ArrowTipView;
-import com.android.systemui.shared.system.LauncherEventUtil;
/**
* ArrowTip helper aligned just above prediction apps, shown to users that enter all apps for the
@@ -57,8 +55,7 @@
floatingHeaderView.findFixedRowByType(PredictionRowView.class).getLocationOnScreen(coords);
ArrowTipView arrowTipView = new ArrowTipView(launcher).setOnClosedCallback(() -> {
launcher.getSharedPrefs().edit().putBoolean(ALL_APPS_TIP_SEEN, true).apply();
- launcher.getUserEventDispatcher().logActionTip(LauncherEventUtil.DISMISS,
- ALL_APPS_PREDICTION_TIPS);
+ // TODO: add log to WW
});
arrowTipView.show(launcher.getString(R.string.all_apps_prediction_tip), coords[1]);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/AppsDividerView.java
rename to quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/InstantAppItemInfo.java b/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
rename to quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java
rename to quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduActivity.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduActivity.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduActivity.java
rename to quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduActivity.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
similarity index 95%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
rename to quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index 4f95254..4451e7a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -47,35 +47,27 @@
*/
public class HotseatEduController {
- public static final String HOTSEAT_EDU_ACTION =
- "com.android.launcher3.action.SHOW_HYBRID_HOTSEAT_EDU";
public static final String SETTINGS_ACTION =
"android.settings.ACTION_CONTENT_SUGGESTIONS_SETTINGS";
private final Launcher mLauncher;
private final Hotseat mHotseat;
- private HotseatRestoreHelper mRestoreHelper;
private List<WorkspaceItemInfo> mPredictedApps;
private HotseatEduDialog mActiveDialog;
private ArrayList<ItemInfo> mNewItems = new ArrayList<>();
private IntArray mNewScreens = null;
- private Runnable mOnOnboardingComplete;
- HotseatEduController(Launcher launcher, HotseatRestoreHelper restoreHelper, Runnable runnable) {
+ HotseatEduController(Launcher launcher) {
mLauncher = launcher;
mHotseat = launcher.getHotseat();
- mRestoreHelper = restoreHelper;
- mOnOnboardingComplete = runnable;
}
/**
* Checks what type of migration should be used and migrates hotseat
*/
void migrate() {
- if (mRestoreHelper != null) {
- mRestoreHelper.createBackup();
- }
+ HotseatRestoreHelper.createBackup(mLauncher);
if (FeatureFlags.HOTSEAT_MIGRATE_TO_FOLDER.get()) {
migrateToFolder();
} else {
@@ -227,7 +219,7 @@
}
void finishOnboarding() {
- mOnOnboardingComplete.run();
+ mLauncher.getModel().onWorkspaceUiChanged();
}
void showDimissTip() {
@@ -284,4 +276,3 @@
return new Intent(SETTINGS_ACTION).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
}
-
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
rename to quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
index 2b3f395..39bf008 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatEduDialog.java
@@ -40,7 +40,6 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.uioverrides.PredictedAppIcon;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.views.AbstractSlideInView;
import java.util.List;
@@ -123,16 +122,6 @@
}
@Override
- public void logActionCommand(int command) {
- // Since this is on-boarding popup, it is not a user controlled action.
- }
-
- @Override
- public int getLogContainerType() {
- return LauncherLogProto.ContainerType.TIP;
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_ON_BOARD_POPUP) != 0;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java
rename to quickstep/src/com/android/launcher3/hybridhotseat/HotseatFileLog.java
diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
new file mode 100644
index 0000000..151a113
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java
@@ -0,0 +1,451 @@
+/*
+ * 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.
+ */
+package com.android.launcher3.hybridhotseat;
+
+import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
+import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.hybridhotseat.HotseatEduController.getSettingsIntent;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_PREDICTION_PINNED;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOTSEAT_RANKED;
+
+import android.animation.Animator;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.ComponentName;
+import android.os.Process;
+import android.view.HapticFeedbackConstants;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.DragSource;
+import com.android.launcher3.DropTarget;
+import com.android.launcher3.Hotseat;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.dragndrop.DragController;
+import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.graphics.DragPreviewProvider;
+import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
+import com.android.launcher3.logger.LauncherAtom.PredictedHotseatContainer;
+import com.android.launcher3.logging.InstanceId;
+import com.android.launcher3.model.BgDataModel.FixedContainerItems;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.touch.ItemLongClickListener;
+import com.android.launcher3.uioverrides.PredictedAppIcon;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.views.ArrowTipView;
+import com.android.launcher3.views.Snackbar;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Provides prediction ability for the hotseat. Fills gaps in hotseat with predicted items, allows
+ * pinning of predicted apps and manages replacement of predicted apps with user drag.
+ */
+public class HotseatPredictionController implements DragController.DragListener,
+ SystemShortcut.Factory<QuickstepLauncher>, InvariantDeviceProfile.OnIDPChangeListener,
+ DragSource {
+
+ private int mHotSeatItemsCount;
+
+ private Launcher mLauncher;
+ private final Hotseat mHotseat;
+
+ private List<ItemInfo> mPredictedItems = Collections.emptyList();
+
+ private AnimatorSet mIconRemoveAnimators;
+ private boolean mUIUpdatePaused = false;
+ private boolean mDragInProgress = false;
+
+ private List<PredictedAppIcon.PredictedIconOutlineDrawing> mOutlineDrawings = new ArrayList<>();
+
+ private final View.OnLongClickListener mPredictionLongClickListener = v -> {
+ if (!ItemLongClickListener.canStartDrag(mLauncher)) return false;
+ if (mLauncher.getWorkspace().isSwitchingState()) return false;
+ if (!mLauncher.getOnboardingPrefs().getBoolean(
+ OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN)) {
+ Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled,
+ R.string.hotseat_prediction_settings, null,
+ () -> mLauncher.startActivity(getSettingsIntent()));
+ mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.HOTSEAT_LONGPRESS_TIP_SEEN);
+ mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ return true;
+ }
+
+ // Start the drag
+ // Use a new itemInfo so that the original predicted item is stable
+ WorkspaceItemInfo dragItem = new WorkspaceItemInfo((WorkspaceItemInfo) v.getTag());
+ v.setVisibility(View.INVISIBLE);
+ mLauncher.getWorkspace().beginDragShared(
+ v, null, this, dragItem, new DragPreviewProvider(v), new DragOptions());
+ return true;
+ };
+
+ public HotseatPredictionController(Launcher launcher) {
+ mLauncher = launcher;
+ mHotseat = launcher.getHotseat();
+ mHotSeatItemsCount = mLauncher.getDeviceProfile().inv.numHotseatIcons;
+ mLauncher.getDragController().addDragListener(this);
+
+ launcher.getDeviceProfile().inv.addOnChangeListener(this);
+ }
+
+ /**
+ * Shows appropriate hotseat education based on prediction enabled and migration states.
+ */
+ public void showEdu() {
+ mLauncher.getStateManager().goToState(NORMAL, true, () -> {
+ if (mPredictedItems.isEmpty()) {
+ // launcher has empty predictions set
+ Snackbar.show(mLauncher, R.string.hotsaet_tip_prediction_disabled,
+ R.string.hotseat_prediction_settings, null,
+ () -> mLauncher.startActivity(getSettingsIntent()));
+ } else if (getPredictedIcons().size() >= (mHotSeatItemsCount + 1) / 2) {
+ showDiscoveryTip();
+ } else {
+ HotseatEduController eduController = new HotseatEduController(mLauncher);
+ eduController.setPredictedApps(mPredictedItems.stream()
+ .map(i -> (WorkspaceItemInfo) i)
+ .collect(Collectors.toList()));
+ eduController.showEdu();
+ }
+ });
+ }
+
+ /**
+ * Shows educational tip for hotseat if user does not go through Tips app.
+ */
+ private void showDiscoveryTip() {
+ if (getPredictedIcons().isEmpty()) {
+ new ArrowTipView(mLauncher).show(
+ mLauncher.getString(R.string.hotseat_tip_no_empty_slots), mHotseat.getTop());
+ } else {
+ Snackbar.show(mLauncher, R.string.hotseat_tip_gaps_filled,
+ R.string.hotseat_prediction_settings, null,
+ () -> mLauncher.startActivity(getSettingsIntent()));
+ }
+ }
+
+ /**
+ * Returns if hotseat client has predictions
+ */
+ public boolean hasPredictions() {
+ return !mPredictedItems.isEmpty();
+ }
+
+ private void fillGapsWithPrediction() {
+ fillGapsWithPrediction(false, null);
+ }
+
+ private void fillGapsWithPrediction(boolean animate, Runnable callback) {
+ if (mUIUpdatePaused || mDragInProgress) {
+ return;
+ }
+
+ int predictionIndex = 0;
+ ArrayList<WorkspaceItemInfo> newItems = new ArrayList<>();
+ // make sure predicted icon removal and filling predictions don't step on each other
+ if (mIconRemoveAnimators != null && mIconRemoveAnimators.isRunning()) {
+ mIconRemoveAnimators.addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ fillGapsWithPrediction(animate, callback);
+ mIconRemoveAnimators.removeListener(this);
+ }
+ });
+ return;
+ }
+ for (int rank = 0; rank < mHotSeatItemsCount; rank++) {
+ View child = mHotseat.getChildAt(
+ mHotseat.getCellXFromOrder(rank),
+ mHotseat.getCellYFromOrder(rank));
+
+ if (child != null && !isPredictedIcon(child)) {
+ continue;
+ }
+ if (mPredictedItems.size() <= predictionIndex) {
+ // Remove predicted apps from the past
+ if (isPredictedIcon(child)) {
+ mHotseat.removeView(child);
+ }
+ continue;
+ }
+ WorkspaceItemInfo predictedItem =
+ (WorkspaceItemInfo) mPredictedItems.get(predictionIndex++);
+ if (isPredictedIcon(child) && child.isEnabled()) {
+ PredictedAppIcon icon = (PredictedAppIcon) child;
+ icon.applyFromWorkspaceItem(predictedItem);
+ icon.finishBinding(mPredictionLongClickListener);
+ } else {
+ newItems.add(predictedItem);
+ }
+ preparePredictionInfo(predictedItem, rank);
+ }
+ bindItems(newItems, animate, callback);
+ }
+
+ private void bindItems(List<WorkspaceItemInfo> itemsToAdd, boolean animate, Runnable callback) {
+ AnimatorSet animationSet = new AnimatorSet();
+ for (WorkspaceItemInfo item : itemsToAdd) {
+ PredictedAppIcon icon = PredictedAppIcon.createIcon(mHotseat, item);
+ mLauncher.getWorkspace().addInScreenFromBind(icon, item);
+ icon.finishBinding(mPredictionLongClickListener);
+ if (animate) {
+ animationSet.play(ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 0.2f, 1));
+ }
+ }
+ if (animate) {
+ if (callback != null) {
+ animationSet.addListener(AnimationSuccessListener.forRunnable(callback));
+ }
+ animationSet.start();
+ } else {
+ if (callback != null) callback.run();
+ }
+ }
+
+ /**
+ * Unregisters callbacks and frees resources
+ */
+ public void destroy() {
+ mLauncher.getDeviceProfile().inv.removeOnChangeListener(this);
+ }
+
+ /**
+ * start and pauses predicted apps update on the hotseat
+ */
+ public void setPauseUIUpdate(boolean paused) {
+ mUIUpdatePaused = paused;
+ if (!paused) {
+ fillGapsWithPrediction();
+ }
+ }
+
+ /**
+ * Sets or updates the predicted items
+ */
+ public void setPredictedItems(FixedContainerItems items) {
+ mPredictedItems = items.items;
+ if (mPredictedItems.isEmpty()) {
+ HotseatRestoreHelper.restoreBackup(mLauncher);
+ }
+ fillGapsWithPrediction();
+ }
+
+ /**
+ * Pins a predicted app icon into place.
+ */
+ public void pinPrediction(ItemInfo info) {
+ PredictedAppIcon icon = (PredictedAppIcon) mHotseat.getChildAt(
+ mHotseat.getCellXFromOrder(info.rank),
+ mHotseat.getCellYFromOrder(info.rank));
+ if (icon == null) {
+ return;
+ }
+ WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo((WorkspaceItemInfo) info);
+ mLauncher.getModelWriter().addItemToDatabase(workspaceItemInfo,
+ LauncherSettings.Favorites.CONTAINER_HOTSEAT, workspaceItemInfo.screenId,
+ workspaceItemInfo.cellX, workspaceItemInfo.cellY);
+ ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 1, 0.8f, 1).start();
+ icon.pin(workspaceItemInfo);
+ mLauncher.getStatsLogManager().logger()
+ .withItemInfo(workspaceItemInfo)
+ .log(LAUNCHER_HOTSEAT_PREDICTION_PINNED);
+ }
+
+ private List<PredictedAppIcon> getPredictedIcons() {
+ List<PredictedAppIcon> icons = new ArrayList<>();
+ ViewGroup vg = mHotseat.getShortcutsAndWidgets();
+ for (int i = 0; i < vg.getChildCount(); i++) {
+ View child = vg.getChildAt(i);
+ if (isPredictedIcon(child)) {
+ icons.add((PredictedAppIcon) child);
+ }
+ }
+ return icons;
+ }
+
+ private void removePredictedApps(List<PredictedAppIcon.PredictedIconOutlineDrawing> outlines,
+ DropTarget.DragObject dragObject) {
+ if (mIconRemoveAnimators != null) {
+ mIconRemoveAnimators.end();
+ }
+ mIconRemoveAnimators = new AnimatorSet();
+ removeOutlineDrawings();
+ for (PredictedAppIcon icon : getPredictedIcons()) {
+ if (!icon.isEnabled()) {
+ continue;
+ }
+ if (dragObject.dragSource == this && icon.equals(dragObject.originalView)) {
+ mHotseat.removeView(icon);
+ continue;
+ }
+ int rank = ((WorkspaceItemInfo) icon.getTag()).rank;
+ outlines.add(new PredictedAppIcon.PredictedIconOutlineDrawing(
+ mHotseat.getCellXFromOrder(rank), mHotseat.getCellYFromOrder(rank), icon));
+ icon.setEnabled(false);
+ ObjectAnimator animator = ObjectAnimator.ofFloat(icon, SCALE_PROPERTY, 0);
+ animator.addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ if (icon.getParent() != null) {
+ mHotseat.removeView(icon);
+ }
+ }
+ });
+ mIconRemoveAnimators.play(animator);
+ }
+ mIconRemoveAnimators.start();
+ }
+
+ @Override
+ public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
+ removePredictedApps(mOutlineDrawings, dragObject);
+ if (mOutlineDrawings.isEmpty()) return;
+ for (PredictedAppIcon.PredictedIconOutlineDrawing outlineDrawing : mOutlineDrawings) {
+ mHotseat.addDelegatedCellDrawing(outlineDrawing);
+ }
+ mDragInProgress = true;
+ mHotseat.invalidate();
+ }
+
+ @Override
+ public void onDragEnd() {
+ mDragInProgress = false;
+ fillGapsWithPrediction(true, this::removeOutlineDrawings);
+ }
+
+ @Nullable
+ @Override
+ public SystemShortcut<QuickstepLauncher> getShortcut(QuickstepLauncher activity,
+ ItemInfo itemInfo) {
+ if (itemInfo.container != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
+ return null;
+ }
+ return new PinPrediction(activity, itemInfo);
+ }
+
+ private void preparePredictionInfo(WorkspaceItemInfo itemInfo, int rank) {
+ itemInfo.container = LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
+ itemInfo.rank = rank;
+ itemInfo.cellX = mHotseat.getCellXFromOrder(rank);
+ itemInfo.cellY = mHotseat.getCellYFromOrder(rank);
+ itemInfo.screenId = rank;
+ }
+
+ private void removeOutlineDrawings() {
+ if (mOutlineDrawings.isEmpty()) return;
+ for (PredictedAppIcon.PredictedIconOutlineDrawing outlineDrawing : mOutlineDrawings) {
+ mHotseat.removeDelegatedCellDrawing(outlineDrawing);
+ }
+ mHotseat.invalidate();
+ mOutlineDrawings.clear();
+ }
+
+ @Override
+ public void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
+ this.mHotSeatItemsCount = profile.numHotseatIcons;
+ }
+
+ @Override
+ public void onDropCompleted(View target, DropTarget.DragObject d, boolean success) {
+ //Does nothing
+ }
+
+ /**
+ * Logs rank info based on current list of predicted items
+ */
+ public void logLaunchedAppRankingInfo(@NonNull ItemInfo itemInfo, InstanceId instanceId) {
+ if (Utilities.IS_DEBUG_DEVICE) {
+ final String pkg = itemInfo.getTargetComponent() != null
+ ? itemInfo.getTargetComponent().getPackageName() : "unknown";
+ HotseatFileLog.INSTANCE.get(mLauncher).log("UserEvent",
+ "appLaunch: packageName:" + pkg + ",isWorkApp:" + (itemInfo.user != null
+ && !Process.myUserHandle().equals(itemInfo.user))
+ + ",launchLocation:" + itemInfo.container);
+ }
+
+
+ ComponentName targetCN = itemInfo.getTargetComponent();
+ if (targetCN == null) {
+ return;
+ }
+ int rank = -1;
+ for (int i = mPredictedItems.size() - 1; i >= 0; i--) {
+ ItemInfo info = mPredictedItems.get(i);
+ if (targetCN.equals(info.getTargetComponent()) && itemInfo.user.equals(info.user)) {
+ rank = i;
+ break;
+ }
+ }
+ if (rank < 0) {
+ return;
+ }
+
+ int cardinality = 0;
+ for (PredictedAppIcon icon : getPredictedIcons()) {
+ ItemInfo info = (ItemInfo) icon.getTag();
+ cardinality |= 1 << info.screenId;
+ }
+
+ PredictedHotseatContainer.Builder containerBuilder = PredictedHotseatContainer.newBuilder();
+ containerBuilder.setCardinality(cardinality);
+ if (itemInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
+ containerBuilder.setIndex(rank);
+ }
+ mLauncher.getStatsLogManager().logger()
+ .withInstanceId(instanceId)
+ .withRank(rank)
+ .withContainerInfo(ContainerInfo.newBuilder()
+ .setPredictedHotseatContainer(containerBuilder)
+ .build())
+ .log(LAUNCHER_HOTSEAT_RANKED);
+ }
+
+ private class PinPrediction extends SystemShortcut<QuickstepLauncher> {
+
+ private PinPrediction(QuickstepLauncher target, ItemInfo itemInfo) {
+ super(R.drawable.ic_pin, R.string.pin_prediction, target,
+ itemInfo);
+ }
+
+ @Override
+ public void onClick(View view) {
+ dismissTaskMenuView(mTarget);
+ pinPrediction(mItemInfo);
+ }
+ }
+
+ private static boolean isPredictedIcon(View view) {
+ return view instanceof PredictedAppIcon && view.getTag() instanceof WorkspaceItemInfo
+ && ((WorkspaceItemInfo) view.getTag()).container
+ == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
similarity index 66%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
rename to quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
index 5a038d2..8f31c22 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionModel.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.hybridhotseat;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import android.app.prediction.AppTarget;
import android.app.prediction.AppTargetEvent;
@@ -24,13 +24,10 @@
import android.content.Context;
import android.os.Bundle;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Workspace;
-import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
-import com.android.launcher3.model.PredictionModel;
+import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -38,55 +35,48 @@
import java.util.ArrayList;
import java.util.Locale;
-import java.util.function.Consumer;
/**
* Model helper for app predictions in workspace
*/
-public class HotseatPredictionModel extends PredictionModel {
+public class HotseatPredictionModel {
private static final String APP_LOCATION_HOTSEAT = "hotseat";
private static final String APP_LOCATION_WORKSPACE = "workspace";
private static final String BUNDLE_KEY_PIN_EVENTS = "pin_events";
private static final String BUNDLE_KEY_CURRENT_ITEMS = "current_items";
-
- public HotseatPredictionModel(Context context) { }
-
/**
- * Creates and returns bundle using workspace items and cached items
+ * Creates and returns bundle using workspace items
*/
- public void createBundle(Consumer<Bundle> cb) {
- LauncherAppState appState = LauncherAppState.getInstance(mContext);
- appState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
- @Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
- Bundle bundle = new Bundle();
- ArrayList<AppTargetEvent> events = new ArrayList<>();
- ArrayList<ItemInfo> workspaceItems = new ArrayList<>(dataModel.workspaceItems);
- workspaceItems.addAll(dataModel.appWidgets);
- for (ItemInfo item : workspaceItems) {
- AppTarget target = getAppTargetFromInfo(item);
- if (target != null && !isTrackedForPrediction(item)) continue;
- events.add(wrapAppTargetWithLocation(target, AppTargetEvent.ACTION_PIN, item));
- }
- ArrayList<AppTarget> currentTargets = new ArrayList<>();
- for (ItemInfo itemInfo : dataModel.cachedPredictedItems) {
- AppTarget target = getAppTargetFromInfo(itemInfo);
- if (target != null) currentTargets.add(target);
- }
- bundle.putParcelableArrayList(BUNDLE_KEY_PIN_EVENTS, events);
- bundle.putParcelableArrayList(BUNDLE_KEY_CURRENT_ITEMS, currentTargets);
- MAIN_EXECUTOR.execute(() -> cb.accept(bundle));
+ public static Bundle convertDataModelToAppTargetBundle(Context context, BgDataModel dataModel) {
+ Bundle bundle = new Bundle();
+ ArrayList<AppTargetEvent> events = new ArrayList<>();
+ ArrayList<ItemInfo> workspaceItems = new ArrayList<>(dataModel.workspaceItems);
+ workspaceItems.addAll(dataModel.appWidgets);
+ for (ItemInfo item : workspaceItems) {
+ AppTarget target = getAppTargetFromInfo(context, item);
+ if (target != null && !isTrackedForPrediction(item)) continue;
+ events.add(wrapAppTargetWithLocation(target, AppTargetEvent.ACTION_PIN, item));
+ }
+ ArrayList<AppTarget> currentTargets = new ArrayList<>();
+ FixedContainerItems hotseatItems = dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION);
+ if (hotseatItems != null) {
+ for (ItemInfo itemInfo : hotseatItems.items) {
+ AppTarget target = getAppTargetFromInfo(context, itemInfo);
+ if (target != null) currentTargets.add(target);
}
- });
+ }
+ bundle.putParcelableArrayList(BUNDLE_KEY_PIN_EVENTS, events);
+ bundle.putParcelableArrayList(BUNDLE_KEY_CURRENT_ITEMS, currentTargets);
+ return bundle;
}
/**
* Creates and returns for {@link AppTarget} object given an {@link ItemInfo}. Returns null
* if item is not supported prediction
*/
- public AppTarget getAppTargetFromInfo(ItemInfo info) {
+ public static AppTarget getAppTargetFromInfo(Context context, ItemInfo info) {
if (info == null) return null;
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
&& info instanceof LauncherAppWidgetInfo
@@ -107,17 +97,17 @@
shortcutKey.componentName.getPackageName(), shortcutKey.user).build();
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
return new AppTarget.Builder(new AppTargetId("folder:" + info.id),
- mContext.getPackageName(), info.user).build();
+ context.getPackageName(), info.user).build();
}
return null;
}
-
/**
* Creates and returns {@link AppTargetEvent} from an {@link AppTarget}, action, and item
* location using {@link ItemInfo}
*/
- public AppTargetEvent wrapAppTargetWithLocation(AppTarget target, int action, ItemInfo info) {
+ public static AppTargetEvent wrapAppTargetWithLocation(
+ AppTarget target, int action, ItemInfo info) {
String location = String.format(Locale.ENGLISH, "%s/%d/[%d,%d]/[%d,%d]",
info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
? APP_LOCATION_HOTSEAT : APP_LOCATION_WORKSPACE,
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
similarity index 81%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
rename to quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
index 9e7c9fb..90f762e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
+++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatRestoreHelper.java
@@ -19,8 +19,10 @@
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import android.content.Context;
+
import com.android.launcher3.InvariantDeviceProfile;
-import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.GridBackupTable;
import com.android.launcher3.provider.LauncherDbUtils;
@@ -29,29 +31,24 @@
* A helper class to manage migration revert restoration for hybrid hotseat
*/
public class HotseatRestoreHelper {
- private final Launcher mLauncher;
-
- HotseatRestoreHelper(Launcher context) {
- mLauncher = context;
- }
/**
* Creates a snapshot backup of Favorite table for future restoration use.
*/
- public void createBackup() {
+ public static void createBackup(Context context) {
MODEL_EXECUTOR.execute(() -> {
try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
LauncherSettings.Settings.call(
- mLauncher.getContentResolver(),
+ context.getContentResolver(),
LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
.getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
- InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
- GridBackupTable backupTable = new GridBackupTable(mLauncher,
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
+ GridBackupTable backupTable = new GridBackupTable(context,
transaction.getDb(), idp.numHotseatIcons, idp.numColumns,
idp.numRows);
backupTable.createCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE);
transaction.commit();
- LauncherSettings.Settings.call(mLauncher.getContentResolver(),
+ LauncherSettings.Settings.call(context.getContentResolver(),
LauncherSettings.Settings.METHOD_REFRESH_HOTSEAT_RESTORE_TABLE);
}
});
@@ -60,23 +57,23 @@
/**
* Finds and restores a previously saved snapshow of Favorites table
*/
- public void restoreBackup() {
+ public static void restoreBackup(Context context) {
MODEL_EXECUTOR.execute(() -> {
try (LauncherDbUtils.SQLiteTransaction transaction = (LauncherDbUtils.SQLiteTransaction)
LauncherSettings.Settings.call(
- mLauncher.getContentResolver(),
+ context.getContentResolver(),
LauncherSettings.Settings.METHOD_NEW_TRANSACTION)
.getBinder(LauncherSettings.Settings.EXTRA_VALUE)) {
if (!tableExists(transaction.getDb(), HYBRID_HOTSEAT_BACKUP_TABLE)) {
return;
}
- InvariantDeviceProfile idp = mLauncher.getDeviceProfile().inv;
- GridBackupTable backupTable = new GridBackupTable(mLauncher,
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
+ GridBackupTable backupTable = new GridBackupTable(context,
transaction.getDb(), idp.numHotseatIcons, idp.numColumns,
idp.numRows);
backupTable.restoreFromCustomBackupTable(HYBRID_HOTSEAT_BACKUP_TABLE, true);
transaction.commit();
- mLauncher.getModel().forceReload();
+ LauncherAppState.getInstance(context).getModel().forceReload();
}
});
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/model/AppEventProducer.java b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
similarity index 63%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/model/AppEventProducer.java
rename to quickstep/src/com/android/launcher3/model/AppEventProducer.java
index 8e4c43f..364a321 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/model/AppEventProducer.java
+++ b/quickstep/src/com/android/launcher3/model/AppEventProducer.java
@@ -15,8 +15,21 @@
*/
package com.android.launcher3.model;
+import static android.app.prediction.AppTargetEvent.ACTION_DISMISS;
+import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH;
+import static android.app.prediction.AppTargetEvent.ACTION_PIN;
+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;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
+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;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST;
+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;
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;
@@ -47,11 +60,12 @@
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.model.data.ItemInfo;
import com.android.launcher3.pm.UserCache;
import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer;
import java.util.Locale;
-import java.util.function.Consumer;
+import java.util.function.ObjIntConsumer;
import java.util.function.Predicate;
/**
@@ -64,9 +78,11 @@
private final Context mContext;
private final Handler mMessageHandler;
- private final Consumer<AppTargetEvent> mCallback;
+ private final ObjIntConsumer<AppTargetEvent> mCallback;
- public AppEventProducer(Context context, Consumer<AppTargetEvent> callback) {
+ private LauncherAtom.ItemInfo mLastDragItem;
+
+ public AppEventProducer(Context context, ObjIntConsumer<AppTargetEvent> callback) {
mContext = context;
mMessageHandler = new Handler(MODEL_EXECUTOR.getLooper(), this::handleMessage);
mCallback = callback;
@@ -76,7 +92,7 @@
private boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_LAUNCH: {
- mCallback.accept((AppTargetEvent) msg.obj);
+ mCallback.accept((AppTargetEvent) msg.obj, msg.arg1);
return true;
}
}
@@ -84,13 +100,18 @@
}
@AnyThread
- private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId) {
- AppTarget target = toAppTarget(atomInfo);
+ 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) {
if (target != null) {
AppTargetEvent event = new AppTargetEvent.Builder(target, eventId)
- .setLaunchLocation(getContainer(atomInfo))
+ .setLaunchLocation(getContainer(locationInfo))
.build();
- Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget();
+ mMessageHandler.obtainMessage(MSG_LAUNCH, targetPredictor, 0, event).sendToTarget();
}
}
@@ -101,9 +122,42 @@
|| event == LAUNCHER_TASK_LAUNCH_TAP
|| event == LAUNCHER_QUICKSWITCH_RIGHT
|| event == LAUNCHER_QUICKSWITCH_LEFT) {
- sendEvent(atomInfo, AppTargetEvent.ACTION_LAUNCH);
+ sendEvent(atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
} else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) {
- sendEvent(atomInfo, AppTargetEvent.ACTION_DISMISS);
+ 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(atomInfo)) {
+ sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
+ }
+ if (isTrackedForHotseatPrediction(mLastDragItem)) {
+ sendEvent(mLastDragItem, ACTION_UNPIN, CONTAINER_HOTSEAT_PREDICTION);
+ }
+ 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);
+ }
+ } else if (event == LAUNCHER_HOTSEAT_PREDICTION_PINNED) {
+ if (isTrackedForHotseatPrediction(atomInfo)) {
+ sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
+ }
}
}
@@ -152,10 +206,8 @@
}
break;
}
- case FOLDER_ICON: {
- id = "folder:" + SystemClock.uptimeMillis();
- cn = new ComponentName(mContext.getPackageName(), "#folder");
- }
+ case FOLDER_ICON:
+ return createTempFolderTarget();
}
if (id != null && cn != null) {
return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle)
@@ -165,6 +217,12 @@
return null;
}
+ private AppTarget createTempFolderTarget() {
+ return new AppTarget.Builder(new AppTargetId("folder:" + SystemClock.uptimeMillis()),
+ mContext.getPackageName(), Process.myUserHandle())
+ .build();
+ }
+
private String getContainer(LauncherAtom.ItemInfo info) {
ContainerInfo ci = info.getContainerInfo();
switch (ci.getContainerCase()) {
@@ -212,11 +270,26 @@
}
private static String getHotseatContainerString(HotseatContainer hc) {
- return String.format(Locale.ENGLISH, "hotseat/%d", hc.getIndex());
+ return String.format(Locale.ENGLISH, "hotseat/%1$d/[%1$d,0]/[1,1]", hc.getIndex());
}
private static ComponentName parseNullable(String componentNameString) {
return TextUtils.isEmpty(componentNameString)
? null : ComponentName.unflattenFromString(componentNameString);
}
+
+ /**
+ * Helper method to determine if {@link ItemInfo} should be tracked and reported to predictors
+ */
+ private static boolean isTrackedForHotseatPrediction(LauncherAtom.ItemInfo info) {
+ ContainerInfo ci = info.getContainerInfo();
+ switch (ci.getContainerCase()) {
+ case HOTSEAT:
+ return true;
+ case WORKSPACE:
+ return ci.getWorkspace().getPageIndex() == 0;
+ default:
+ return false;
+ }
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/model/PredictionUpdateTask.java
rename to quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
similarity index 80%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/model/QuickstepModelDelegate.java
rename to quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 166cb6c..be57dec 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -16,9 +16,11 @@
package com.android.launcher3.model;
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
+import static com.android.launcher3.hybridhotseat.HotseatPredictionModel.convertDataModelToAppTargetBundle;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionManager;
@@ -62,6 +64,8 @@
private final PredictorState mAllAppsState =
new PredictorState(CONTAINER_PREDICTION, "all_apps_predictions");
+ private final PredictorState mHotseatState =
+ new PredictorState(CONTAINER_HOTSEAT_PREDICTION, "hotseat_predictions");
private final InvariantDeviceProfile mIDP;
private final AppEventProducer mAppEventProducer;
@@ -81,13 +85,23 @@
// TODO: Implement caching and preloading
super.loadItems(ums, pinnedShortcuts);
- WorkspaceItemFactory factory =
+ WorkspaceItemFactory allAppsFactory =
new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, mIDP.numAllAppsColumns);
mAllAppsState.items.setItems(
- mAllAppsState.storage.read(mApp.getContext(), factory, ums.allUsers::get));
+ mAllAppsState.storage.read(mApp.getContext(), allAppsFactory, ums.allUsers::get));
mDataModel.extraItems.put(CONTAINER_PREDICTION, mAllAppsState.items);
+ WorkspaceItemFactory hotseatFactory =
+ new WorkspaceItemFactory(mApp, ums, pinnedShortcuts, mIDP.numHotseatIcons);
+ mHotseatState.items.setItems(
+ mHotseatState.storage.read(mApp.getContext(), hotseatFactory, ums.allUsers::get));
+ mDataModel.extraItems.put(CONTAINER_HOTSEAT_PREDICTION, mHotseatState.items);
mActive = true;
+ }
+
+ @Override
+ public void workspaceLoadComplete() {
+ super.workspaceLoadComplete();
recreatePredictors();
}
@@ -111,6 +125,7 @@
private void destroyPredictors() {
mAllAppsState.destroyPredictor();
+ mHotseatState.destroyPredictor();
}
@WorkerThread
@@ -125,18 +140,28 @@
return;
}
- int count = mIDP.numAllAppsColumns;
-
- mAllAppsState.predictor = apm.createAppPredictionSession(
+ registerPredictor(mAllAppsState, apm.createAppPredictionSession(
new AppPredictionContext.Builder(context)
.setUiSurface("home")
- .setPredictedTargetCount(count)
- .build());
- mAllAppsState.predictor.registerPredictionUpdates(
- Executors.MODEL_EXECUTOR, t -> handleUpdate(mAllAppsState, t));
- mAllAppsState.predictor.requestPredictionUpdate();
+ .setPredictedTargetCount(mIDP.numAllAppsColumns)
+ .build()));
+
+ // TODO: get bundle
+ registerPredictor(mHotseatState, apm.createAppPredictionSession(
+ new AppPredictionContext.Builder(context)
+ .setUiSurface("hotseat")
+ .setPredictedTargetCount(mIDP.numHotseatIcons)
+ .setExtras(convertDataModelToAppTargetBundle(context, mDataModel))
+ .build()));
+
}
+ private void registerPredictor(PredictorState state, AppPredictor predictor) {
+ state.predictor = predictor;
+ state.predictor.registerPredictionUpdates(
+ Executors.MODEL_EXECUTOR, t -> handleUpdate(state, t));
+ state.predictor.requestPredictionUpdate();
+ }
private void handleUpdate(PredictorState state, List<AppTarget> targets) {
if (state.setTargets(targets)) {
@@ -154,9 +179,10 @@
}
}
- private void onAppTargetEvent(AppTargetEvent event) {
- if (mAllAppsState.predictor != null) {
- mAllAppsState.predictor.notifyAppTargetEvent(event);
+ private void onAppTargetEvent(AppTargetEvent event, int client) {
+ PredictorState state = client == CONTAINER_PREDICTION ? mAllAppsState : mHotseatState;
+ if (state.predictor != null) {
+ state.predictor.notifyAppTargetEvent(event);
}
}
diff --git a/quickstep/src/com/android/launcher3/model/WellbeingModel.java b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
index cc7b712..810f4e3 100644
--- a/quickstep/src/com/android/launcher3/model/WellbeingModel.java
+++ b/quickstep/src/com/android/launcher3/model/WellbeingModel.java
@@ -43,9 +43,13 @@
import android.util.Log;
import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherProvider;
+import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
@@ -74,6 +78,9 @@
private static final int MSG_PACKAGE_REMOVED = 2;
private static final int MSG_FULL_REFRESH = 3;
+ private static final int UNKNOWN_MINIMAL_DEVICE_STATE = 0;
+ private static final int IN_MINIMAL_DEVICE = 2;
+
// Welbeing contract
private static final String PATH_ACTIONS = "actions";
private static final String PATH_MINIMAL_DEVICE = "minimal_device";
@@ -84,6 +91,8 @@
private static final String EXTRA_MAX_NUM_ACTIONS_SHOWN = "max_num_actions_shown";
private static final String EXTRA_PACKAGES = "packages";
private static final String EXTRA_SUCCESS = "success";
+ private static final String EXTRA_MINIMAL_DEVICE_STATE = "minimal_device_state";
+ private static final String DB_NAME_MINIMAL_DEVICE = "minimal.db";
public static final MainThreadInitializedObject<WellbeingModel> INSTANCE =
new MainThreadInitializedObject<>(WellbeingModel::new);
@@ -121,11 +130,12 @@
updateWellbeingData();
} else if (uri.getPath().contains(PATH_MINIMAL_DEVICE)) {
// Wellbeing reports that minimal device state or config is changed.
- updateLauncherModel();
+ updateLauncherModel(context);
}
}
};
- FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, this::updateLauncherModel);
+ FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, () ->
+ updateLauncherModel(context));
if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
context.registerReceiver(
@@ -170,7 +180,6 @@
Log.e(TAG, "Failed to register content observer for " + actionsUri + ": " + e);
if (mIsInTest) throw new RuntimeException(e);
}
-
updateWellbeingData();
}
@@ -208,10 +217,34 @@
mWorkerHandler.sendEmptyMessage(MSG_FULL_REFRESH);
}
- private void updateLauncherModel() {
- if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) return;
+ private void updateLauncherModel(@NonNull final Context context) {
+ if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
+ reloadLauncherInNormalMode(context);
+ return;
+ }
+ runWithMinimalDeviceConfigs((bundle) -> {
+ if (bundle.getInt(EXTRA_MINIMAL_DEVICE_STATE, UNKNOWN_MINIMAL_DEVICE_STATE)
+ == IN_MINIMAL_DEVICE) {
+ reloadLauncherInMinimalMode(context);
+ } else {
+ reloadLauncherInNormalMode(context);
+ }
+ });
+ }
- // TODO: init Launcher in minimal device / normal mode
+ private void reloadLauncherInNormalMode(@NonNull final Context context) {
+ LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_SWITCH_DATABASE,
+ InvariantDeviceProfile.INSTANCE.get(context).dbFile);
+ }
+
+ private void reloadLauncherInMinimalMode(@NonNull final Context context) {
+ final Bundle extras = new Bundle();
+ extras.putString(LauncherProvider.KEY_LAYOUT_PROVIDER_AUTHORITY,
+ mWellbeingProviderPkg + ".api");
+ LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_SWITCH_DATABASE,
+ DB_NAME_MINIMAL_DEVICE, extras);
}
private Uri.Builder apiBuilder() {
@@ -225,6 +258,9 @@
*/
@WorkerThread
private void runWithMinimalDeviceConfigs(Consumer<Bundle> consumer) {
+ if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) {
+ return;
+ }
if (DEBUG || mIsInTest) {
Log.d(TAG, "runWithMinimalDeviceConfigs() called");
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 1b8e244..aad7e17 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.graphics.OverviewScrim.SCRIM_MULTIPLIER;
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
@@ -70,6 +71,7 @@
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
SCRIM_PROGRESS.set(scrim, state.getOverviewScrimAlpha(mLauncher));
+ SCRIM_MULTIPLIER.set(scrim, 1f);
getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness());
}
@@ -108,6 +110,8 @@
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher),
config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
+ setter.setFloat(scrim, SCRIM_MULTIPLIER, 1f,
+ config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR));
setter.setFloat(
mRecentsView, getTaskModalnessProperty(),
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
rename to quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
rename to quickstep/src/com/android/launcher3/uioverrides/PredictedAppIconInflater.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
similarity index 88%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
rename to quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 4107698..e808f8c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -33,8 +33,8 @@
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Configuration;
-import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -48,19 +48,15 @@
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.folder.Folder;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory;
-import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.NoButtonNavbarToOverviewTouchController;
@@ -71,21 +67,21 @@
import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TaskViewTouchController;
import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchTouchController;
-import com.android.launcher3.util.IntArray;
+import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.SystemUiProxy;
+import com.android.quickstep.util.QuickstepOnboardingPrefs;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
-
import com.android.systemui.shared.system.ActivityManagerWrapper;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.List;
import java.util.Objects;
import java.util.stream.Stream;
@@ -99,14 +95,7 @@
SystemUiProxy.INSTANCE.get(context).setShelfHeight(arg1 != 0, arg2);
private FixedContainerItems mAllAppsPredictions;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (mHotseatPredictionController != null) {
- mHotseatPredictionController.createPredictor();
- }
- }
+ private HotseatPredictionController mHotseatPredictionController;
@Override
protected void setupViews() {
@@ -144,6 +133,18 @@
}
}
+ /**
+ * Returns Prediction controller for hybrid hotseat
+ */
+ public HotseatPredictionController getHotseatPredictionController() {
+ return mHotseatPredictionController;
+ }
+
+ @Override
+ protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs) {
+ return new QuickstepOnboardingPrefs(this, sharedPrefs);
+ }
+
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
@@ -180,22 +181,6 @@
}
@Override
- public void folderCreatedFromItem(Folder folder, WorkspaceItemInfo itemInfo) {
- super.folderCreatedFromItem(folder, itemInfo);
- if (mHotseatPredictionController != null) {
- mHotseatPredictionController.folderCreatedFromWorkspaceItem(itemInfo, folder.getInfo());
- }
- }
-
- @Override
- public void folderConvertedToItem(Folder folder, WorkspaceItemInfo itemInfo) {
- super.folderConvertedToItem(folder, itemInfo);
- if (mHotseatPredictionController != null) {
- mHotseatPredictionController.folderConvertedToWorkspaceItem(itemInfo, folder.getInfo());
- }
- }
-
- @Override
public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
if (mHotseatPredictionController != null) {
return Stream.concat(super.getSupportedShortcuts(),
@@ -223,19 +208,14 @@
}
@Override
- public void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks) {
- super.bindPredictedItems(appInfos, ranks);
- if (mHotseatPredictionController != null) {
- mHotseatPredictionController.showCachedItems(appInfos, ranks);
- }
- }
-
- @Override
public void bindExtraContainerItems(FixedContainerItems item) {
if (item.containerId == Favorites.CONTAINER_PREDICTION) {
mAllAppsPredictions = item;
getAppsView().getFloatingHeaderView().findFixedRowByType(PredictionRowView.class)
.setPredictedApps(item.items);
+ } else if (item.containerId == Favorites.CONTAINER_HOTSEAT_PREDICTION
+ && mHotseatPredictionController != null) {
+ mHotseatPredictionController.setPredictedItems(item);
}
}
@@ -306,14 +286,7 @@
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.2");
}
- if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
- if (TestProtocol.sDebugTracing) {
- Log.d(TestProtocol.PAUSE_NOT_DETECTED, "createTouchControllers.3");
- }
- list.add(new NoButtonNavbarToOverviewTouchController(this));
- } else {
- list.add(new FlingAndHoldTouchController(this));
- }
+ list.add(new NoButtonNavbarToOverviewTouchController(this));
} else {
if (getDeviceProfile().isVerticalBarLayout()) {
list.add(new OverviewToAllAppsTouchController(this));
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
rename to quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index e7cd393..bce73cd 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -16,8 +16,7 @@
package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
+import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.Context;
@@ -25,7 +24,6 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.quickstep.SysUINavigationMode;
/**
* Definition for AllApps state
@@ -65,13 +63,7 @@
public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW
.getWorkspaceScaleAndTranslation(launcher);
- if (SysUINavigationMode.getMode(launcher) == NO_BUTTON && !ENABLE_OVERVIEW_ACTIONS.get()) {
- float normalScale = 1;
- // Scale down halfway to where we'd be in overview, to prepare for a potential pause.
- scaleAndTranslation.scale = (scaleAndTranslation.scale + normalScale) / 2;
- } else {
- scaleAndTranslation.scale = 1;
- }
+ scaleAndTranslation.scale = 1;
return scaleAndTranslation;
}
@@ -92,7 +84,8 @@
@Override
public float[] getOverviewScaleAndOffset(Launcher launcher) {
- return new float[] {0.9f, 0};
+ float offset = removeShelfFromOverview(launcher) ? 1 : 0;
+ return new float[] {0.9f, offset};
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java b/quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
rename to quickstep/src/com/android/launcher3/uioverrides/states/BackgroundAppState.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
rename to quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
similarity index 90%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
rename to quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index d174bfd..bbe7821 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -16,8 +16,6 @@
package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
@@ -31,7 +29,6 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Workspace;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.util.LayoutUtils;
@@ -65,7 +62,7 @@
public int getTransitionDuration(Context context) {
// In no-button mode, overview comes in all the way from the left, so give it more time.
boolean isNoButtonMode = SysUINavigationMode.INSTANCE.get(context).getMode() == NO_BUTTON;
- return isNoButtonMode && ENABLE_OVERVIEW_ACTIONS.get() ? 380 : 250;
+ return isNoButtonMode ? 380 : 250;
}
@Override
@@ -108,8 +105,7 @@
@Override
public ScaleAndTranslation getQsbScaleAndTranslation(Launcher launcher) {
- if (this == OVERVIEW && ENABLE_OVERVIEW_ACTIONS.get()
- && removeShelfFromOverview(launcher)) {
+ if (this == OVERVIEW && removeShelfFromOverview(launcher)) {
// Treat the QSB as part of the hotseat so they move together.
return getHotseatScaleAndTranslation(launcher);
}
@@ -129,7 +125,7 @@
@Override
public int getVisibleElements(Launcher launcher) {
RecentsView recentsView = launcher.getOverviewPanel();
- if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher) ||
+ if (removeShelfFromOverview(launcher) ||
hideShelfInTwoButtonLandscape(launcher, recentsView.getPagedOrientationHandler())) {
return OVERVIEW_BUTTONS;
} else if (launcher.getDeviceProfile().isVerticalBarLayout()) {
@@ -179,8 +175,6 @@
public void onBackPressed(Launcher launcher) {
TaskView taskView = launcher.<RecentsView>getOverviewPanel().getRunningTaskView();
if (taskView != null) {
- launcher.getUserEventDispatcher().logActionCommand(Action.Command.BACK,
- newContainerTarget(ContainerType.OVERVIEW));
taskView.launchTask(true);
} else {
super.onBackPressed(launcher);
@@ -191,10 +185,6 @@
return new BackgroundAppState(id);
}
- public static OverviewState newPeekState(int id) {
- return new OverviewPeekState(id);
- }
-
public static OverviewState newSwitchState(int id) {
return new QuickSwitchState(id);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
rename to quickstep/src/com/android/launcher3/uioverrides/states/QuickSwitchState.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
similarity index 88%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
rename to quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index daa1aad..94af134 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -22,28 +22,24 @@
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
-import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
@@ -190,23 +186,14 @@
if (!isHotseatVisible) {
hotseat.setScaleX(0.92f);
hotseat.setScaleY(0.92f);
- if (ENABLE_OVERVIEW_ACTIONS.get()) {
- AllAppsContainerView qsbContainer = mActivity.getAppsView();
- View qsb = qsbContainer.getSearchView();
- boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
- if (!qsbVisible) {
- qsbContainer.setScaleX(0.92f);
- qsbContainer.setScaleY(0.92f);
- }
+ AllAppsContainerView qsbContainer = mActivity.getAppsView();
+ View qsb = qsbContainer.getSearchView();
+ boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
+ if (!qsbVisible) {
+ qsbContainer.setScaleX(0.92f);
+ qsbContainer.setScaleY(0.92f);
}
}
- } else if (toState == NORMAL && fromState == OVERVIEW_PEEK) {
- // Keep fully visible until the very end (when overview is offscreen) to make invisible.
- config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
- } else if (toState == OVERVIEW_PEEK && fromState == NORMAL) {
- config.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT);
- config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
- config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
} else if ((fromState == NORMAL || fromState == HINT_STATE) && toState == OVERVIEW) {
if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
config.setInterpolator(ANIM_WORKSPACE_SCALE,
@@ -227,8 +214,7 @@
config.setInterpolator(ANIM_ALL_APPS_FADE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
config.setInterpolator(ANIM_DEPTH, OVERSHOOT_1_2);
- Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
- && removeShelfFromOverview(mActivity)
+ Interpolator translationInterpolator = removeShelfFromOverview(mActivity)
? OVERSHOOT_1_2
: OVERSHOOT_1_7;
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
similarity index 94%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
index 57fd11a..d574294 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java
@@ -19,7 +19,6 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL_APPS_EDU;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
-import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.config.FeatureFlags.ENABLE_ALL_APPS_EDU;
@@ -66,8 +65,8 @@
SingleAxisSwipeDetector.Listener {
private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3;
- // How much of the overview scrim we can remove during the transition.
- private static final float OVERVIEW_TO_HOME_SCRIM_PROGRESS = 0.5f;
+ // The min amount of overview scrim we keep during the transition.
+ private static final float OVERVIEW_TO_HOME_SCRIM_MULTIPLIER = 0.5f;
private final Launcher mLauncher;
private final SingleAxisSwipeDetector mSwipeDetector;
@@ -163,11 +162,11 @@
RecentsView recentsView = mLauncher.getOverviewPanel();
AnimatorControllerWithResistance.createRecentsResistanceFromOverviewAnim(mLauncher,
builder);
- float endScrimAlpha = Utilities.mapRange(OVERVIEW_TO_HOME_SCRIM_PROGRESS,
- mStartState.getOverviewScrimAlpha(mLauncher),
- mEndState.getOverviewScrimAlpha(mLauncher));
+
builder.setFloat(mLauncher.getDragLayer().getOverviewScrim(),
- OverviewScrim.SCRIM_PROGRESS, endScrimAlpha, PULLBACK_INTERPOLATOR);
+ OverviewScrim.SCRIM_MULTIPLIER, OVERVIEW_TO_HOME_SCRIM_MULTIPLIER,
+ PULLBACK_INTERPOLATOR);
+
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
builder.addOnFrameCallback(recentsView::redrawLiveTile);
}
@@ -221,7 +220,7 @@
recentsView.switchToScreenshot(null,
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
}
- if (mStartState == OVERVIEW) {
+ if (mStartState.overviewUi) {
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState))
.animateWithVelocity(velocity);
} else {
@@ -229,12 +228,12 @@
() -> onSwipeInteractionCompleted(mEndState));
}
if (mStartState != mEndState) {
- logStateChange(mStartState.containerType, logAction);
+ // TODO: add to WW log
}
AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(mLauncher);
if (topOpenView != null) {
AbstractFloatingView.closeAllOpenViews(mLauncher);
- logStateChange(topOpenView.getLogContainerType(), logAction);
+ // TODO: add to WW log
}
ActivityManagerWrapper.getInstance()
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
similarity index 64%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
index dbff20a..591d3ca 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java
@@ -16,30 +16,44 @@
package com.android.launcher3.uioverrides.touchcontrollers;
+import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
+import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.PointF;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
+import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.OverviewScrim;
-import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.VibratorWrapper;
+import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.util.AnimatorControllerWithResistance;
+import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
@@ -48,7 +62,7 @@
* the nav bar falls back to go to All Apps. Swiping from the nav bar without holding goes to the
* first home screen instead of to Overview.
*/
-public class NoButtonNavbarToOverviewTouchController extends FlingAndHoldTouchController {
+public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouchController {
// How much of the movement to use for translating overview after swipe and hold.
@@ -57,6 +71,8 @@
private static final float TRANSLATION_ANIM_VELOCITY_DP_PER_MS = 0.8f;
private final RecentsView mRecentsView;
+ private final MotionPauseDetector mMotionPauseDetector;
+ private final float mMotionPauseMinDisplacement;
private boolean mDidTouchStartInNavBar;
private boolean mReachedOverview;
@@ -69,21 +85,16 @@
private ObjectAnimator mNormalToHintOverviewScrimAnimator;
public NoButtonNavbarToOverviewTouchController(Launcher l) {
- super(l);
+ super(l, false /* allowDragToOverview */);
mRecentsView = l.getOverviewPanel();
+ mMotionPauseDetector = new MotionPauseDetector(l);
+ mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NoButtonNavbarToOverviewTouchController.ctor");
}
}
@Override
- protected float getMotionPauseMaxDisplacement() {
- // No need to disallow pause when swiping up all the way up the screen (unlike
- // FlingAndHoldTouchController where user is probably intending to go to all apps).
- return Float.MAX_VALUE;
- }
-
- @Override
protected boolean canInterceptTouch(MotionEvent ev) {
mDidTouchStartInNavBar = (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0;
return super.canInterceptTouch(ev);
@@ -113,6 +124,13 @@
@Override
public void onDragStart(boolean start, float startDisplacement) {
super.onDragStart(start, startDisplacement);
+
+ mMotionPauseDetector.clear();
+
+ if (handlingOverviewAnim()) {
+ mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
+ }
+
if (mFromState == NORMAL && mToState == HINT_STATE) {
mNormalToHintOverviewScrimAnimator = ObjectAnimator.ofFloat(
mLauncher.getDragLayer().getOverviewScrim(),
@@ -134,8 +152,24 @@
@Override
public void onDragEnd(float velocity) {
- super.onDragEnd(velocity);
+ if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
+ goToOverviewOrHomeOnDragEnd(velocity);
+ } else {
+ super.onDragEnd(velocity);
+ }
+
+ View searchView = mLauncher.getAppsView().getSearchView();
+ if (searchView instanceof FeedbackHandler) {
+ ((FeedbackHandler) searchView).resetFeedback();
+ }
+
+ mMotionPauseDetector.clear();
mNormalToHintOverviewScrimAnimator = null;
+ if (mLauncher.isInState(OVERVIEW)) {
+ // Normally we would cleanup the state based on mCurrentAnimation, but since we stop
+ // using that when we pause to go to Overview, we need to clean up ourselves.
+ clearState();
+ }
}
@Override
@@ -151,8 +185,7 @@
}
}
- @Override
- protected void onMotionPauseChanged(boolean isPaused) {
+ private void onMotionPauseChanged(boolean isPaused) {
if (mCurrentAnimation == null) {
return;
}
@@ -175,9 +208,10 @@
}
}
- @Override
- protected boolean handlingOverviewAnim() {
- return mDidTouchStartInNavBar && super.handlingOverviewAnim();
+ private boolean handlingOverviewAnim() {
+ int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
+ return mDidTouchStartInNavBar && mStartState == NORMAL
+ && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
}
@Override
@@ -203,14 +237,18 @@
// Stay in Overview.
return true;
}
+
+ float upDisplacement = -yDisplacement;
+ mMotionPauseDetector.setDisallowPause(!handlingOverviewAnim()
+ || upDisplacement < mMotionPauseMinDisplacement);
+ mMotionPauseDetector.addPosition(event);
+
return super.onDrag(yDisplacement, xDisplacement, event);
}
- @Override
- protected void goToOverviewOnDragEnd(float velocity) {
+ private void goToOverviewOrHomeOnDragEnd(float velocity) {
float velocityDp = dpiFromPx(velocity);
boolean isFling = Math.abs(velocityDp) > 1;
- StateManager<LauncherState> stateManager = mLauncher.getStateManager();
boolean goToHomeInsteadOfOverview = isFling;
if (goToHomeInsteadOfOverview) {
new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
@@ -243,4 +281,54 @@
private float dpiFromPx(float pixels) {
return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics());
}
+
+ @Override
+ protected StateAnimationConfig getConfigForStates(
+ LauncherState fromState, LauncherState toState) {
+ if (fromState == NORMAL && toState == ALL_APPS) {
+ StateAnimationConfig builder = new StateAnimationConfig();
+ // Fade in prediction icons quickly, then rest of all apps after reaching overview.
+ float progressToReachOverview = NORMAL.getVerticalProgress(mLauncher)
+ - OVERVIEW.getVerticalProgress(mLauncher);
+ builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
+ ACCEL,
+ 0,
+ ALL_APPS_CONTENT_FADE_THRESHOLD));
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
+ ACCEL,
+ progressToReachOverview,
+ progressToReachOverview + ALL_APPS_CONTENT_FADE_THRESHOLD));
+
+ // Get workspace out of the way quickly, to prepare for potential pause.
+ builder.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL_3);
+ builder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, DEACCEL_3);
+ builder.setInterpolator(ANIM_WORKSPACE_FADE, DEACCEL_3);
+ return builder;
+ } else if (fromState == ALL_APPS && toState == NORMAL) {
+ StateAnimationConfig builder = new StateAnimationConfig();
+ // Keep all apps/predictions opaque until the very end of the transition.
+ float progressToReachOverview = OVERVIEW.getVerticalProgress(mLauncher);
+ builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(
+ DEACCEL,
+ progressToReachOverview - ALL_APPS_CONTENT_FADE_THRESHOLD,
+ progressToReachOverview));
+ builder.setInterpolator(ANIM_ALL_APPS_HEADER_FADE, Interpolators.clampToProgress(
+ DEACCEL,
+ 1 - ALL_APPS_CONTENT_FADE_THRESHOLD,
+ 1));
+ return builder;
+ }
+ return super.getConfigForStates(fromState, toState);
+ }
+
+ /**
+ * Interface for views with feedback animation requiring reset
+ */
+ public interface FeedbackHandler {
+
+ /**
+ * reset searchWidget feedback
+ */
+ void resetFeedback();
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
similarity index 91%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
index 3867c35..4b0642f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonQuickSwitchTouchController.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.uioverrides.touchcontrollers;
-import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
@@ -25,7 +24,6 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
-import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
@@ -40,9 +38,6 @@
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_PAUSE_TO_OVERVIEW_ANIM;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
-import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL;
-import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
-import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
@@ -60,10 +55,8 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.OverviewScrim;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
@@ -79,8 +72,6 @@
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.MotionPauseDetector;
-import com.android.quickstep.util.ShelfPeekAnim;
-import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.LauncherRecentsView;
@@ -99,7 +90,6 @@
private final BaseQuickstepLauncher mLauncher;
private final BothAxesSwipeDetector mSwipeDetector;
- private final ShelfPeekAnim mShelfPeekAnim;
private final float mXRange;
private final float mYRange;
private final float mMaxYProgress;
@@ -121,7 +111,6 @@
public NoButtonQuickSwitchTouchController(BaseQuickstepLauncher launcher) {
mLauncher = launcher;
mSwipeDetector = new BothAxesSwipeDetector(mLauncher, this);
- mShelfPeekAnim = mLauncher.getShelfPeekAnim();
mRecentsView = mLauncher.getOverviewPanel();
mXRange = mLauncher.getDeviceProfile().widthPx / 2f;
mYRange = LayoutUtils.getShelfTrackingDistance(
@@ -191,25 +180,6 @@
@Override
public void onMotionPauseChanged(boolean isPaused) {
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
-
- if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
- return;
- }
-
- ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
- if (shelfState == PEEK) {
- // Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
- AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
- allAppsController.setAlphas(
- NORMAL, new StateAnimationConfig(), NO_ANIM_PROPERTY_SETTER);
-
- if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
- // Hotseat was hidden, but we need it visible when peeking.
- mLauncher.getHotseat().setAlpha(1);
- }
- }
- mShelfPeekAnim.setShelfState(shelfState, ShelfPeekAnim.INTERPOLATOR,
- ShelfPeekAnim.DURATION);
}
private void setupAnimators() {
@@ -301,10 +271,6 @@
mIsHomeScreenVisible = FADE_OUT_INTERPOLATOR.getInterpolation(xProgress)
<= 1 - ALPHA_CUTOFF_THRESHOLD;
- if (wasHomeScreenVisible && !mIsHomeScreenVisible) {
- // Get the shelf all the way offscreen so it pops up when we decide to peek it.
- mShelfPeekAnim.setShelfState(HIDE, LINEAR, 0);
- }
// Only allow motion pause if the home screen is invisible, since some
// home screen elements will appear in the shelf on motion pause.
@@ -312,11 +278,6 @@
|| -displacement.y < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(ev);
- if (mIsHomeScreenVisible) {
- // Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
- mShelfPeekAnim.setShelfState(CANCEL, LINEAR, 0);
- }
-
if (mXOverviewAnim != null) {
mXOverviewAnim.setPlayFraction(xProgress);
}
@@ -474,7 +435,6 @@
if (mYOverviewAnim != null) {
mYOverviewAnim.cancelAnimation();
}
- mShelfPeekAnim.setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
mMotionPauseDetector.clear();
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/OverviewToAllAppsTouchController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitOverviewStateTouchHelper.java
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 20ee61d..1208c6c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -24,7 +24,6 @@
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
@@ -142,6 +141,10 @@
Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
"PortraitStatesTouchController.getTargetState 1");
}
+ if (removeShelfFromOverview(mLauncher)) {
+ // Don't allow swiping down to overview.
+ return NORMAL;
+ }
return TouchInteractionService.isConnected() ?
mLauncher.getStateManager().getLastState() : NORMAL;
} else if (fromState == OVERVIEW) {
@@ -150,7 +153,7 @@
"PortraitStatesTouchController.getTargetState 2");
}
LauncherState positiveDragTarget = ALL_APPS;
- if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(mLauncher)) {
+ if (removeShelfFromOverview(mLauncher)) {
// Don't allow swiping up to all apps.
positiveDragTarget = OVERVIEW;
}
@@ -245,7 +248,7 @@
final StateAnimationConfig config = totalShift == 0 ? new StateAnimationConfig()
: getConfigForStates(mFromState, mToState);
- config.animFlags = updateAnimComponentsOnReinit(animFlags);
+ config.animFlags = animFlags;
config.duration = maxAccuracy;
cancelPendingAnim();
@@ -279,14 +282,6 @@
return 1 / totalShift;
}
- /**
- * Give subclasses the chance to update the animation when we re-initialize towards a new state.
- */
- @AnimationFlags
- protected int updateAnimComponentsOnReinit(@AnimationFlags int animComponents) {
- return animComponents;
- }
-
private void cancelPendingAnim() {
if (mPendingAnimation != null) {
mPendingAnimation.finish(false, Touch.SWIPE);
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
index 3586b4f..df6194d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java
@@ -82,7 +82,15 @@
mDetector = new SingleAxisSwipeDetector(activity, this, dir);
}
- private boolean canInterceptTouch() {
+ private boolean canInterceptTouch(MotionEvent ev) {
+ if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) != 0) {
+ // Don't intercept swipes on the nav bar, as user might be trying to go home
+ // during a task dismiss animation.
+ if (mCurrentAnimation != null) {
+ mCurrentAnimation.getAnimationPlayer().end();
+ }
+ return false;
+ }
if (mCurrentAnimation != null) {
mCurrentAnimation.forceFinishIfCloseToEnd();
}
@@ -118,7 +126,7 @@
clearState();
}
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mNoIntercept = !canInterceptTouch();
+ mNoIntercept = !canInterceptTouch(ev);
if (mNoIntercept) {
return false;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
rename to quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/TransposedQuickSwitchTouchController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
similarity index 97%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
rename to quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 2ca07ec..aaa2720 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -20,7 +20,6 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
-import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
@@ -41,8 +40,6 @@
import static com.android.quickstep.GestureState.STATE_END_TARGET_SET;
import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHED;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
-import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
-import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
@@ -93,8 +90,6 @@
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.RectFSpringAnim;
-import com.android.quickstep.util.ShelfPeekAnim;
-import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TransformParams;
import com.android.quickstep.views.LiveTileOverlay;
@@ -205,7 +200,7 @@
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
- private boolean mIsShelfPeeking;
+ private boolean mIsMotionPaused;
private boolean mContinuingLastGesture;
@@ -491,7 +486,9 @@
* Called when motion pause is detected
*/
public void onMotionPauseChanged(boolean isPaused) {
- setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION);
+ mIsMotionPaused = isPaused;
+ maybeUpdateRecentsAttachedState();
+ performHapticFeedback();
}
public void maybeUpdateRecentsAttachedState() {
@@ -522,7 +519,7 @@
// The window is going away so make sure recents is always visible in this case.
recentsAttachedToAppWindow = true;
} else {
- recentsAttachedToAppWindow = mIsShelfPeeking || mIsLikelyToStartNewTask;
+ recentsAttachedToAppWindow = mIsMotionPaused || mIsLikelyToStartNewTask;
}
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
@@ -552,19 +549,6 @@
}
}
- @UiThread
- public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
- mAnimationFactory.setShelfState(shelfState, interpolator, duration);
- boolean wasShelfPeeking = mIsShelfPeeking;
- mIsShelfPeeking = shelfState == PEEK;
- if (mIsShelfPeeking != wasShelfPeeking) {
- maybeUpdateRecentsAttachedState();
- }
- if (shelfState.shouldPreformHaptic) {
- performHapticFeedback();
- }
- }
-
private void buildAnimationController() {
if (!canCreateNewOrUpdateExistingLauncherTransitionController()) {
return;
@@ -852,7 +836,7 @@
if (isCancel) {
endTarget = LAST_TASK;
} else if (mDeviceState.isFullyGesturalNavMode()) {
- if (mIsShelfPeeking) {
+ if (mIsMotionPaused) {
endTarget = RECENTS;
} else if (goingToNewTask) {
endTarget = NEW_TASK;
@@ -874,7 +858,7 @@
if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
endTarget = HOME;
- } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsShelfPeeking) {
+ } else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsMotionPaused) {
// If swiping at a diagonal, base end target on the faster velocity.
endTarget = NEW_TASK;
} else if (isSwipeUp) {
@@ -942,7 +926,6 @@
mInputConsumerProxy.enable();
}
if (endTarget == HOME) {
- setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
} else if (endTarget == RECENTS) {
LiveTileOverlay.INSTANCE.startIconAnimation();
@@ -958,9 +941,6 @@
}
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
}
- if (mDeviceState.isFullyGesturalNavMode()) {
- setShelfState(ShelfAnimState.OVERVIEW, interpolator, duration);
- }
}
// Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
@@ -1267,7 +1247,6 @@
}
private void endLauncherTransitionController() {
- setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
if (mLauncherTransitionController != null) {
// End the animation, but stay at the same visual progress.
mLauncherTransitionController.getNormalController().dispatchSetInterpolator(
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java
rename to quickstep/src/com/android/quickstep/AppToOverviewAnimationProvider.java
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 1a4620b..8b108ac 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.quickstep.AbsSwipeUpHandler.RECENTS_ATTACH_DURATION;
import static com.android.quickstep.SysUINavigationMode.getMode;
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
@@ -37,7 +36,6 @@
import android.graphics.Rect;
import android.os.Build;
import android.view.MotionEvent;
-import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -54,7 +52,6 @@
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
-import com.android.quickstep.util.ShelfPeekAnim;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
@@ -299,9 +296,6 @@
default void onTransitionCancelled() { }
- default void setShelfState(ShelfPeekAnim.ShelfAnimState animState,
- Interpolator interpolator, long duration) { }
-
/**
* @param attached Whether to show RecentsView alongside the app window. If false, recents
* will be hidden by some property we can animate, e.g. alpha.
@@ -409,6 +403,6 @@
}
protected static boolean showOverviewActions(Context context) {
- return ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context);
+ return removeShelfFromOverview(context);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java
rename to quickstep/src/com/android/quickstep/FallbackActivityInterface.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java
rename to quickstep/src/com/android/quickstep/FallbackSwipeHandler.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java b/quickstep/src/com/android/quickstep/ImageActionsApi.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
rename to quickstep/src/com/android/quickstep/ImageActionsApi.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
rename to quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index 4e38f49..036d473 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -27,7 +27,6 @@
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.Log;
-import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -50,7 +49,6 @@
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.LayoutUtils;
-import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.plugins.shared.LauncherOverlayManager;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -122,12 +120,6 @@
notifyRecentsOfOrientation(deviceState.getRotationTouchHelper());
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
@Override
- public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
- long duration) {
- mActivity.getShelfPeekAnim().setShelfState(shelfState, interpolator, duration);
- }
-
- @Override
protected void createBackgroundToOverviewAnim(BaseQuickstepLauncher activity,
PendingAnimation pa) {
super.createBackgroundToOverviewAnim(activity, pa);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java
rename to quickstep/src/com/android/quickstep/LauncherSwipeHandlerV2.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java b/quickstep/src/com/android/quickstep/OverscrollPluginFactory.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/OverscrollPluginFactory.java
rename to quickstep/src/com/android/quickstep/OverscrollPluginFactory.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
similarity index 97%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
rename to quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index dca3378..365cff5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -29,7 +29,6 @@
import androidx.annotation.BinderThread;
-import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.util.ActivityInitListener;
@@ -87,12 +86,6 @@
MAIN_EXECUTOR.execute(new HideRecentsCommand());
}
- @BinderThread
- public void onTip(int actionType, int viewType) {
- MAIN_EXECUTOR.execute(() ->
- UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
- }
-
private class ShowRecentsCommand extends RecentsActivityCommand {
private final boolean mTriggeredFromAltTab;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
similarity index 92%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
rename to quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
index 5026f36..e4b8ce2 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/QuickstepTestInformationHandler.java
+++ b/quickstep/src/com/android/quickstep/QuickstepTestInformationHandler.java
@@ -53,12 +53,6 @@
Bundle::putInt, PortraitStatesTouchController::getHotseatTop);
}
- case TestProtocol.REQUEST_OVERVIEW_ACTIONS_ENABLED: {
- response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
- FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get());
- return response;
- }
-
case TestProtocol.REQUEST_OVERVIEW_SHARE_ENABLED: {
response.putBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD,
FeatureFlags.ENABLE_OVERVIEW_SHARE.get());
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
rename to quickstep/src/com/android/quickstep/RecentsActivity.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java
rename to quickstep/src/com/android/quickstep/SwipeUpAnimationLogic.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
similarity index 90%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
rename to quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 36579ec..3a47024 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -18,6 +18,7 @@
import static android.view.Surface.ROTATION_0;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL;
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
@@ -41,6 +42,7 @@
import com.android.launcher3.util.ResourceBasedOverride;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.views.OverviewActionsView;
+import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -155,6 +157,7 @@
getActionsView().setCallbacks(new OverlayUICallbacks() {
@Override
public void onShare() {
+ endLiveTileMode(isAllowedByPolicy);
if (isAllowedByPolicy) {
mImageApi.startShareActivity();
} else {
@@ -165,6 +168,7 @@
@SuppressLint("NewApi")
@Override
public void onScreenshot() {
+ endLiveTileMode(isAllowedByPolicy);
saveScreenshot(task);
}
});
@@ -172,6 +176,23 @@
}
/**
+ * End rendering live tile in Overview.
+ *
+ * @param showScreenshot if it's true, we take a screenshot and switch to it.
+ */
+ public void endLiveTileMode(boolean showScreenshot) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
+ RecentsView recentsView = mThumbnailView.getTaskView().getRecentsView();
+ if (showScreenshot) {
+ recentsView.switchToScreenshot(
+ () -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
+ } else {
+ recentsView.finishRecentsAnimation(true /* toRecents */, null);
+ }
+ }
+ }
+
+ /**
* Called to save screenshot of the task thumbnail.
*/
@SuppressLint("NewApi")
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
rename to quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index ff051b6..3b245b3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -18,7 +18,6 @@
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SELECTIONS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP;
@@ -310,16 +309,11 @@
TaskShortcutFactory WELLBEING = (activity, view) ->
WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, view.getItemInfo());
- TaskShortcutFactory SCREENSHOT = (activity, tv) -> {
- if (ENABLE_OVERVIEW_ACTIONS.get()) {
- return tv.getThumbnail().getTaskOverlay()
- .getScreenshotShortcut(activity, tv.getItemInfo());
- }
- return null;
- };
+ TaskShortcutFactory SCREENSHOT = (activity, tv) -> tv.getThumbnail().getTaskOverlay()
+ .getScreenshotShortcut(activity, tv.getItemInfo());
TaskShortcutFactory MODAL = (activity, tv) -> {
- if (ENABLE_OVERVIEW_ACTIONS.get() && ENABLE_OVERVIEW_SELECTIONS.get()) {
+ if (ENABLE_OVERVIEW_SELECTIONS.get()) {
return tv.getThumbnail().getTaskOverlay().getModalStateSystemShortcut(tv.getItemInfo());
}
return null;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/TaskViewUtils.java
rename to quickstep/src/com/android/quickstep/TaskViewUtils.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
similarity index 97%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
rename to quickstep/src/com/android/quickstep/TouchInteractionService.java
index 5ec6377..5b4a239 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -22,7 +22,6 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
-import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
@@ -61,7 +60,6 @@
import com.android.launcher3.ResourceUtils;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.testing.TestLogging;
@@ -141,7 +139,6 @@
}
@BinderThread
- @Override
public void onOverviewToggle() {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onOverviewToggle");
mOverviewCommandHelper.onOverviewToggle();
@@ -165,7 +162,7 @@
@BinderThread
@Override
public void onTip(int actionType, int viewType) {
- mOverviewCommandHelper.onTip(actionType, viewType);
+ // Please delete this method from the interface
}
@BinderThread
@@ -189,18 +186,7 @@
@BinderThread
public void onBackAction(boolean completed, int downX, int downY, boolean isButton,
boolean gestureSwipeLeft) {
- if (mOverviewComponentObserver == null) {
- return;
- }
-
- final BaseActivityInterface activityInterface =
- mOverviewComponentObserver.getActivityInterface();
- UserEventDispatcher.newInstance(getBaseContext()).logActionBack(completed, downX, downY,
- isButton, gestureSwipeLeft, activityInterface.getContainerType());
-
- if (completed && !isButton && shouldNotifyBackGesture()) {
- UI_HELPER_EXECUTOR.execute(TouchInteractionService.this::tryNotifyBackGesture);
- }
+ // Remove this method from the interface
}
@BinderThread
@@ -263,10 +249,10 @@
mMainChoreographer = Choreographer.getInstance();
mAM = ActivityManagerWrapper.getInstance();
mDeviceState = new RecentsAnimationDeviceState(this);
+ mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
mDeviceState.addOneHandedModeChangedCallback(this::onOneHandedModeOverlayChanged);
mDeviceState.runOnUserUnlocked(this::onUserUnlocked);
- mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
ProtoTracer.INSTANCE.get(this).add(this);
sConnected = true;
@@ -659,17 +645,17 @@
runningComponent != null && runningComponent.equals(homeComponent);
}
- if (gestureState.getRunningTask() == null) {
+ if (ENABLE_QUICKSTEP_LIVE_TILE.get()
+ && gestureState.getActivityInterface().isInLiveTileMode()) {
+ return createOverviewInputConsumer(
+ previousGestureState, gestureState, event, forceOverviewInputConsumer);
+ } else if (gestureState.getRunningTask() == null) {
return mResetGestureInputConsumer;
} else if (previousGestureState.isRunningAnimationToLauncher()
|| gestureState.getActivityInterface().isResumed()
|| forceOverviewInputConsumer) {
return createOverviewInputConsumer(
previousGestureState, gestureState, event, forceOverviewInputConsumer);
- } else if (ENABLE_QUICKSTEP_LIVE_TILE.get()
- && gestureState.getActivityInterface().isInLiveTileMode()) {
- return createOverviewInputConsumer(
- previousGestureState, gestureState, event, forceOverviewInputConsumer);
} else if (mDeviceState.isGestureBlockedActivity(gestureState.getRunningTask())) {
return mResetGestureInputConsumer;
} else {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/ViewUtils.java b/quickstep/src/com/android/quickstep/ViewUtils.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/ViewUtils.java
rename to quickstep/src/com/android/quickstep/ViewUtils.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java b/quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
rename to quickstep/src/com/android/quickstep/fallback/FallbackNavBarTouchController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
rename to quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
rename to quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsDragLayer.java b/quickstep/src/com/android/quickstep/fallback/RecentsDragLayer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsDragLayer.java
rename to quickstep/src/com/android/quickstep/fallback/RecentsDragLayer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsState.java
rename to quickstep/src/com/android/quickstep/fallback/RecentsState.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java
rename to quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/AssistantInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/DelegateInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/OverscrollInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/OverviewInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/OverviewWithoutFocusInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/ScreenPinnedInputConsumer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
rename to quickstep/src/com/android/quickstep/inputconsumers/SysUiOverlayInputConsumer.java
diff --git a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
deleted file mode 100644
index 9ca7f23..0000000
--- a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2018 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.
- */
-package com.android.quickstep.logging;
-
-import android.content.Context;
-import android.util.Log;
-
-import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET;
-import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP;
-import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP;
-import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE;
-
-import com.android.launcher3.logging.UserEventDispatcher;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.systemui.shared.system.MetricsLoggerCompat;
-
-/**
- * This class handles AOSP MetricsLogger function calls and logging around
- * quickstep interactions.
- */
-@SuppressWarnings("unused")
-public class UserEventDispatcherExtension extends UserEventDispatcher {
-
- public static final int ALL_APPS_PREDICTION_TIPS = 2;
-
- private static final String TAG = "UserEventDispatcher";
-
- public UserEventDispatcherExtension(Context context) { }
-
- public void logStateChangeAction(int action, int dir, int downX, int downY,
- int srcChildTargetType, int srcParentContainerType,
- int dstContainerType, int pageIndex) {
- new MetricsLoggerCompat().visibility(MetricsLoggerCompat.OVERVIEW_ACTIVITY,
- dstContainerType == LauncherLogProto.ContainerType.TASKSWITCHER);
- super.logStateChangeAction(action, dir, downX, downY, srcChildTargetType,
- srcParentContainerType, dstContainerType, pageIndex);
- }
-
- public void logActionTip(int actionType, int viewType) {
- LauncherLogProto.Action action = new LauncherLogProto.Action();
- LauncherLogProto.Target target = new LauncherLogProto.Target();
- switch(actionType) {
- case VISIBLE:
- action.type = LauncherLogProto.Action.Type.TIP;
- target.type = LauncherLogProto.Target.Type.CONTAINER;
- target.containerType = LauncherLogProto.ContainerType.TIP;
- break;
- case DISMISS:
- action.type = LauncherLogProto.Action.Type.TOUCH;
- action.touch = LauncherLogProto.Action.Touch.TAP;
- target.type = LauncherLogProto.Target.Type.CONTROL;
- target.controlType = CANCEL_TARGET;
- break;
- default:
- Log.e(TAG, "Unexpected action type = " + actionType);
- }
-
- switch(viewType) {
- case RECENTS_QUICK_SCRUB_ONBOARDING_TIP:
- target.tipType = LauncherLogProto.TipType.QUICK_SCRUB_TEXT;
- break;
- case RECENTS_SWIPE_UP_ONBOARDING_TIP:
- target.tipType = LauncherLogProto.TipType.SWIPE_UP_TEXT;
- break;
- default:
- Log.e(TAG, "Unexpected viewType = " + viewType);
- }
- LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
- dispatchUserEvent(event, null);
- }
-}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ActiveGestureLog.java b/quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/ActiveGestureLog.java
rename to quickstep/src/com/android/quickstep/util/ActiveGestureLog.java
diff --git a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
index a19a67c..deb70e0 100644
--- a/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
+++ b/quickstep/src/com/android/quickstep/util/AnimatorControllerWithResistance.java
@@ -31,11 +31,12 @@
import androidx.annotation.Nullable;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.views.RecentsView;
@@ -54,11 +55,12 @@
*/
public static final float TWO_BUTTON_EXTRA_DRAG_FACTOR = 0.25f;
- private enum RecentsParams {
+ private enum RecentsResistanceParams {
FROM_APP(0.75f, 0.5f, 1f),
FROM_OVERVIEW(1f, 0.75f, 0.5f);
- RecentsParams(float scaleStartResist, float scaleMaxResist, float translationFactor) {
+ RecentsResistanceParams(float scaleStartResist, float scaleMaxResist,
+ float translationFactor) {
this.scaleStartResist = scaleStartResist;
this.scaleMaxResist = scaleMaxResist;
this.translationFactor = translationFactor;
@@ -139,9 +141,9 @@
FloatProperty<SCALE> scaleProperty, TRANSLATION translationTarget,
FloatProperty<TRANSLATION> translationProperty) {
- PendingAnimation resistAnim = createRecentsResistanceAnim(null, context,
- recentsOrientedState, dp, scaleTarget, scaleProperty, translationTarget,
- translationProperty, RecentsParams.FROM_APP);
+ RecentsParams params = new RecentsParams(context, recentsOrientedState, dp, scaleTarget,
+ scaleProperty, translationTarget, translationProperty);
+ PendingAnimation resistAnim = createRecentsResistanceAnim(params);
AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController();
return new AnimatorControllerWithResistance(normalController, resistanceController);
@@ -152,31 +154,30 @@
* when starting from recents, i.e. {@link #createRecentsResistanceFromOverviewAnim}.
*/
public static <SCALE, TRANSLATION> PendingAnimation createRecentsResistanceAnim(
- @Nullable PendingAnimation resistAnim, Context context,
- RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget,
- FloatProperty<SCALE> scaleProperty, TRANSLATION translationTarget,
- FloatProperty<TRANSLATION> translationProperty, RecentsParams params) {
+ RecentsParams<SCALE, TRANSLATION> params) {
Rect startRect = new Rect();
- LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect,
- recentsOrientedState.getOrientationHandler());
+ PagedOrientationHandler orientationHandler = params.recentsOrientedState
+ .getOrientationHandler();
+ LauncherActivityInterface.INSTANCE.calculateTaskSize(params.context, params.dp, startRect,
+ orientationHandler);
long distanceToCover = startRect.bottom;
- boolean isTwoButtonMode = SysUINavigationMode.getMode(context) == TWO_BUTTONS;
+ boolean isTwoButtonMode = SysUINavigationMode.getMode(params.context) == TWO_BUTTONS;
if (isTwoButtonMode) {
// We can only drag a small distance past overview, not to the top of the screen.
distanceToCover = (long)
- ((dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR);
+ ((params.dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR);
}
- if (resistAnim == null) {
- resistAnim = new PendingAnimation(distanceToCover * 2);
- }
+ PendingAnimation resistAnim = params.resistAnim != null
+ ? params.resistAnim
+ : new PendingAnimation(distanceToCover * 2);
PointF pivot = new PointF();
- float fullscreenScale = recentsOrientedState.getFullScreenScaleAndPivot(
- startRect, dp, pivot);
- float startScale = 1;
- float prevScaleRate = (fullscreenScale - startScale) / (dp.heightPx - startRect.bottom);
+ float fullscreenScale = params.recentsOrientedState.getFullScreenScaleAndPivot(
+ startRect, params.dp, pivot);
+ float prevScaleRate = (fullscreenScale - params.startScale)
+ / (params.dp.heightPx - startRect.bottom);
// This is what the scale would be at the end of the drag if we didn't apply resistance.
- float endScale = startScale - prevScaleRate * distanceToCover;
+ float endScale = params.startScale - prevScaleRate * distanceToCover;
final TimeInterpolator scaleInterpolator;
if (isTwoButtonMode) {
// We are bounded by the distance of the drag, so we don't need to apply resistance.
@@ -184,9 +185,10 @@
} else {
// Create an interpolator that resists the scale so the scale doesn't get smaller than
// RECENTS_SCALE_MAX_RESIST.
- float startResist = Utilities.getProgress(params.scaleStartResist , startScale,
- endScale);
- float maxResist = Utilities.getProgress(params.scaleMaxResist, startScale, endScale);
+ float startResist = Utilities.getProgress(params.resistanceParams.scaleStartResist,
+ params.startScale, endScale);
+ float maxResist = Utilities.getProgress(params.resistanceParams.scaleMaxResist,
+ params.startScale, endScale);
scaleInterpolator = t -> {
if (t < startResist) {
return t;
@@ -196,20 +198,22 @@
return startResist + resistProgress * (maxResist - startResist);
};
}
- resistAnim.addFloat(scaleTarget, scaleProperty, startScale, endScale,
+ resistAnim.addFloat(params.scaleTarget, params.scaleProperty, params.startScale, endScale,
scaleInterpolator);
if (!isTwoButtonMode) {
// Compute where the task view would be based on the end scale, if we didn't translate.
RectF endRectF = new RectF(startRect);
Matrix temp = new Matrix();
- temp.setScale(params.scaleMaxResist, params.scaleMaxResist, pivot.x, pivot.y);
+ temp.setScale(params.resistanceParams.scaleMaxResist,
+ params.resistanceParams.scaleMaxResist, pivot.x, pivot.y);
temp.mapRect(endRectF);
// Translate such that the task view touches the top of the screen when drag does.
- float endTranslation = endRectF.top * recentsOrientedState.getOrientationHandler()
- .getSecondaryTranslationDirectionFactor() * params.translationFactor;
- resistAnim.addFloat(translationTarget, translationProperty, 0, endTranslation,
- RECENTS_TRANSLATE_RESIST_INTERPOLATOR);
+ float endTranslation = endRectF.top
+ * orientationHandler.getSecondaryTranslationDirectionFactor()
+ * params.resistanceParams.translationFactor;
+ resistAnim.addFloat(params.translationTarget, params.translationProperty,
+ params.startTranslation, endTranslation, RECENTS_TRANSLATE_RESIST_INTERPOLATOR);
}
return resistAnim;
@@ -220,11 +224,66 @@
* a RecentsView interaction that started from the overview state.
*/
public static PendingAnimation createRecentsResistanceFromOverviewAnim(
- BaseDraggingActivity activity, @Nullable PendingAnimation resistanceAnim) {
- RecentsView recentsView = activity.getOverviewPanel();
- return createRecentsResistanceAnim(resistanceAnim, activity,
- recentsView.getPagedViewOrientedState(), activity.getDeviceProfile(),
- recentsView, RECENTS_SCALE_PROPERTY, recentsView, TASK_SECONDARY_TRANSLATION,
- RecentsParams.FROM_OVERVIEW);
+ Launcher launcher, @Nullable PendingAnimation resistanceAnim) {
+ RecentsView recentsView = launcher.getOverviewPanel();
+ RecentsParams params = new RecentsParams(launcher, recentsView.getPagedViewOrientedState(),
+ launcher.getDeviceProfile(), recentsView, RECENTS_SCALE_PROPERTY, recentsView,
+ TASK_SECONDARY_TRANSLATION)
+ .setResistAnim(resistanceAnim)
+ .setResistanceParams(RecentsResistanceParams.FROM_OVERVIEW)
+ .setStartScale(recentsView.getScaleX());
+ return createRecentsResistanceAnim(params);
+ }
+
+ /**
+ * Params to compute resistance when scaling/translating recents.
+ */
+ private static class RecentsParams<SCALE, TRANSLATION> {
+ // These are all required and can't have default values, hence are final.
+ public final Context context;
+ public final RecentsOrientedState recentsOrientedState;
+ public final DeviceProfile dp;
+ public final SCALE scaleTarget;
+ public final FloatProperty<SCALE> scaleProperty;
+ public final TRANSLATION translationTarget;
+ public final FloatProperty<TRANSLATION> translationProperty;
+
+ // These are not required, or can have a default value that is generally correct.
+ @Nullable public PendingAnimation resistAnim = null;
+ public RecentsResistanceParams resistanceParams = RecentsResistanceParams.FROM_APP;
+ public float startScale = 1f;
+ public float startTranslation = 0f;
+
+ private RecentsParams(Context context, RecentsOrientedState recentsOrientedState,
+ DeviceProfile dp, SCALE scaleTarget, FloatProperty<SCALE> scaleProperty,
+ TRANSLATION translationTarget, FloatProperty<TRANSLATION> translationProperty) {
+ this.context = context;
+ this.recentsOrientedState = recentsOrientedState;
+ this.dp = dp;
+ this.scaleTarget = scaleTarget;
+ this.scaleProperty = scaleProperty;
+ this.translationTarget = translationTarget;
+ this.translationProperty = translationProperty;
+ }
+
+ private RecentsParams setResistAnim(PendingAnimation resistAnim) {
+ this.resistAnim = resistAnim;
+ return this;
+ }
+
+ private RecentsParams setResistanceParams(RecentsResistanceParams resistanceParams) {
+ this.resistanceParams = resistanceParams;
+ return this;
+ }
+
+ private RecentsParams setStartScale(float startScale) {
+ this.startScale = startScale;
+ return this;
+ }
+
+ private RecentsParams setStartTranslation(float startTranslation) {
+ this.startTranslation = startTranslation;
+ return this;
+ }
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AssistantUtilities.java b/quickstep/src/com/android/quickstep/util/AssistantUtilities.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/AssistantUtilities.java
rename to quickstep/src/com/android/quickstep/util/AssistantUtilities.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/InputConsumerProxy.java
rename to quickstep/src/com/android/quickstep/util/InputConsumerProxy.java
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index f7bd1e2..b88a195 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -15,7 +15,6 @@
*/
package com.android.quickstep.util;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.Context;
@@ -45,7 +44,7 @@
public static int getShelfTrackingDistance(Context context, DeviceProfile dp,
PagedOrientationHandler orientationHandler) {
// Track the bottom of the window.
- if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context)) {
+ if (removeShelfFromOverview(context)) {
Rect taskSize = new Rect();
LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, taskSize,
orientationHandler);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
similarity index 88%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
rename to quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
index d2e1ded..4a298d3 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/OverviewToHomeAnim.java
+++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
@@ -76,6 +77,7 @@
if (startState != OVERVIEW) {
Log.e(TAG, "animateFromOverviewToHome: unexpected start state " + startState);
}
+ AnimatorSet anim = new AnimatorSet();
boolean playStaggeredWorkspaceAnim = velocity < 0;
if (playStaggeredWorkspaceAnim) {
@@ -87,7 +89,8 @@
mIsHomeStaggeredAnimFinished = true;
maybeOverviewToHomeAnimComplete();
}
- }).start();
+ });
+ anim.play(staggeredWorkspaceAnim.getAnimators());
} else {
mIsHomeStaggeredAnimFinished = true;
}
@@ -104,20 +107,27 @@
// StaggeredWorkspaceAnim doesn't animate overview, so we handle it here.
? PLAY_ATOMIC_OVERVIEW_PEEK
: ANIM_ALL_COMPONENTS;
- config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, DEACCEL);
+ boolean isLayoutNaturalToLauncher = recentsView.getPagedOrientationHandler()
+ .isLayoutNaturalToLauncher();
+ config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, isLayoutNaturalToLauncher
+ ? DEACCEL : FINAL_FRAME);
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, INSTANT);
- AnimatorSet anim = stateManager.createAtomicAnimation(
+ if (!isLayoutNaturalToLauncher) {
+ config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL);
+ }
+ AnimatorSet stateAnim = stateManager.createAtomicAnimation(
startState, NORMAL, config);
- anim.addListener(new AnimationSuccessListener() {
+ stateAnim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationSuccess(Animator animator) {
mIsOverviewHidden = true;
maybeOverviewToHomeAnimComplete();
}
});
- stateManager.cancelAnimation();
+ anim.play(stateAnim);
+ stateManager.setCurrentAnimation(anim, NORMAL);
anim.start();
recentsView.snapToPage(DEFAULT_PAGE, duration);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ProtoTracer.java b/quickstep/src/com/android/quickstep/util/ProtoTracer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/ProtoTracer.java
rename to quickstep/src/com/android/quickstep/util/ProtoTracer.java
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index c2e67c1..b10adb4 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -21,19 +21,18 @@
import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.SharedPreferences;
-import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateListener;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.views.AllAppsEduView;
@@ -41,9 +40,9 @@
/**
* Extends {@link OnboardingPrefs} for quickstep-specific onboarding data.
*/
-public class QuickstepOnboardingPrefs extends OnboardingPrefs<BaseQuickstepLauncher> {
+public class QuickstepOnboardingPrefs extends OnboardingPrefs<QuickstepLauncher> {
- public QuickstepOnboardingPrefs(BaseQuickstepLauncher launcher, SharedPreferences sharedPrefs) {
+ public QuickstepOnboardingPrefs(QuickstepLauncher launcher, SharedPreferences sharedPrefs) {
super(launcher, sharedPrefs);
StateManager<LauncherState> stateManager = launcher.getStateManager();
@@ -66,8 +65,7 @@
}
boolean shelfBounceSeen = getBoolean(SHELF_BOUNCE_SEEN);
- if (!shelfBounceSeen && ENABLE_OVERVIEW_ACTIONS.get()
- && removeShelfFromOverview(launcher)) {
+ if (!shelfBounceSeen && removeShelfFromOverview(launcher)) {
// There's no shelf in overview, so don't bounce it (can't get to all apps anyway).
shelfBounceSeen = true;
mSharedPrefs.edit().putBoolean(SHELF_BOUNCE_SEEN, shelfBounceSeen).apply();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java b/quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
rename to quickstep/src/com/android/quickstep/util/RecentsAtomicAnimationFactory.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java
rename to quickstep/src/com/android/quickstep/util/RectFSpringAnim.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
rename to quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SurfaceTransactionApplier.java b/quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/SurfaceTransactionApplier.java
rename to quickstep/src/com/android/quickstep/util/SurfaceTransactionApplier.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskCornerRadius.java b/quickstep/src/com/android/quickstep/util/TaskCornerRadius.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskCornerRadius.java
rename to quickstep/src/com/android/quickstep/util/TaskCornerRadius.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java
rename to quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java
rename to quickstep/src/com/android/quickstep/util/TransformParams.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java b/quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
rename to quickstep/src/com/android/quickstep/util/TriggerSwipeUpTouchTracker.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
similarity index 98%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java
rename to quickstep/src/com/android/quickstep/views/AllAppsEduView.java
index c06dd9c..97a239c 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java
+++ b/quickstep/src/com/android/quickstep/views/AllAppsEduView.java
@@ -105,11 +105,6 @@
}
@Override
- public void logActionCommand(int command) {
- // TODO
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_ALL_APPS_EDU) != 0;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/ClearAllButton.java
rename to quickstep/src/com/android/quickstep/views/ClearAllButton.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/DigitalWellBeingToast.java
rename to quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/IconView.java
rename to quickstep/src/com/android/quickstep/views/IconView.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
rename to quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index f31bc19..b338bd0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -43,6 +43,7 @@
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.quickstep.LauncherActivityInterface;
import com.android.quickstep.SysUINavigationMode;
+import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.RecentsExtraCard;
@@ -93,12 +94,14 @@
@Override
public void startHome() {
+ Runnable onReachedHome = () -> mActivity.getStateManager().goToState(NORMAL, false);
+ OverviewToHomeAnim overviewToHomeAnim = new OverviewToHomeAnim(mActivity, onReachedHome);
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
switchToScreenshot(null,
() -> finishRecentsAnimation(true /* toRecents */,
- () -> mActivity.getStateManager().goToState(NORMAL)));
+ () -> overviewToHomeAnim.animateWithVelocity(0)));
} else {
- mActivity.getStateManager().goToState(NORMAL);
+ overviewToHomeAnim.animateWithVelocity(0);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java b/quickstep/src/com/android/quickstep/views/LiveTileOverlay.java
similarity index 92%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
rename to quickstep/src/com/android/quickstep/views/LiveTileOverlay.java
index 30c9f77..c6c2d7e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LiveTileOverlay.java
+++ b/quickstep/src/com/android/quickstep/views/LiveTileOverlay.java
@@ -40,14 +40,13 @@
public static final LiveTileOverlay INSTANCE = new LiveTileOverlay();
private final Paint mPaint = new Paint();
+ private final RectF mCurrentRect = new RectF();
private final Rect mBoundsRect = new Rect();
- private RectF mCurrentRect;
private float mCornerRadius;
private Drawable mIcon;
private Animator mIconAnimator;
- private boolean mDrawEnabled = true;
private float mIconAnimationProgress = 0f;
private boolean mIsAttached;
@@ -58,7 +57,7 @@
public void update(RectF currentRect, float cornerRadius) {
invalidateSelf();
- mCurrentRect = currentRect;
+ mCurrentRect.set(currentRect);
mCornerRadius = cornerRadius;
mCurrentRect.roundOut(mBoundsRect);
@@ -93,16 +92,9 @@
return mIconAnimationProgress;
}
- public void setDrawEnabled(boolean drawEnabled) {
- if (mDrawEnabled != drawEnabled) {
- mDrawEnabled = drawEnabled;
- invalidateSelf();
- }
- }
-
@Override
public void draw(Canvas canvas) {
- if (mCurrentRect != null && mDrawEnabled) {
+ if (mCurrentRect != null) {
canvas.drawRoundRect(mCurrentRect, mCornerRadius, mCornerRadius, mPaint);
if (mIcon != null && mIconAnimationProgress > 0f) {
canvas.save();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
similarity index 93%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
rename to quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 1bf2fbf..8f60991 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -16,7 +16,6 @@
package com.android.quickstep.views;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SHARE;
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
@@ -53,7 +52,6 @@
@IntDef(flag = true, value = {
HIDDEN_UNSUPPORTED_NAVIGATION,
- HIDDEN_DISABLED_FEATURE,
HIDDEN_NON_ZERO_ROTATION,
HIDDEN_NO_TASKS,
HIDDEN_GESTURE_RUNNING,
@@ -62,11 +60,10 @@
public @interface ActionsHiddenFlags { }
public static final int HIDDEN_UNSUPPORTED_NAVIGATION = 1 << 0;
- public static final int HIDDEN_DISABLED_FEATURE = 1 << 1;
- public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 2;
- public static final int HIDDEN_NO_TASKS = 1 << 3;
- public static final int HIDDEN_GESTURE_RUNNING = 1 << 4;
- public static final int HIDDEN_NO_RECENTS = 1 << 5;
+ public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 1;
+ public static final int HIDDEN_NO_TASKS = 1 << 2;
+ public static final int HIDDEN_GESTURE_RUNNING = 1 << 3;
+ public static final int HIDDEN_NO_RECENTS = 1 << 4;
@IntDef(flag = true, value = {
DISABLED_SCROLLING,
@@ -145,7 +142,6 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- updateHiddenFlags(HIDDEN_DISABLED_FEATURE, !ENABLE_OVERVIEW_ACTIONS.get());
updateHiddenFlags(HIDDEN_UNSUPPORTED_NAVIGATION, !removeShelfFromOverview(getContext()));
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsExtraViewContainer.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsExtraViewContainer.java
rename to quickstep/src/com/android/quickstep/views/RecentsExtraViewContainer.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
similarity index 98%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
rename to quickstep/src/com/android/quickstep/views/RecentsView.java
index 5267760..6ae91b6 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -79,7 +79,6 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.TouchDelegate;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
@@ -110,8 +109,6 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.DynamicResource;
@@ -142,7 +139,6 @@
import com.android.systemui.shared.recents.model.Task.TaskKey;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.LauncherEventUtil;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -673,9 +669,6 @@
public void onDigitalWellbeingToastShown() {
if (!mDwbToastShown) {
mDwbToastShown = true;
- mActivity.getUserEventDispatcher().logActionTip(
- LauncherEventUtil.VISIBLE,
- LauncherLogProto.TipType.DWB_TOAST);
}
}
@@ -712,12 +705,9 @@
super.onTouchEvent(ev);
TaskView taskView = getCurrentPageTaskView();
- if (taskView != null) {
- TouchDelegate mChildTouchDelegate = taskView.getIconTouchDelegate(ev);
- if (mChildTouchDelegate != null && mChildTouchDelegate.onTouchEvent(ev)) {
- // Keep consuming events to pass to delegate
- return true;
- }
+ if (taskView != null && taskView.offerTouchToChildren(ev)) {
+ // Keep consuming events to pass to delegate
+ return true;
}
final int x = (int) ev.getX();
@@ -1461,8 +1451,6 @@
if (taskView.getTask() != null) {
ActivityManagerWrapper.getInstance().removeTask(taskView.getTask().key.id);
ComponentKey compKey = TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key);
- mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- endState.logAction, Direction.UP, index, compKey);
mActivity.getStatsLogManager().logger().withItemInfo(taskView.getItemInfo())
.log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
}
@@ -2174,9 +2162,6 @@
tv.launchTask(false, onLaunchResult, getHandler());
Task task = tv.getTask();
if (task != null) {
- mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- endState.logAction, Direction.DOWN, indexOfChild(tv),
- TaskUtils.getLaunchComponentKeyForTask(task.key));
mActivity.getStatsLogManager().logger().withItemInfo(tv.getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_SWIPE_DOWN);
}
@@ -2294,13 +2279,13 @@
mRecentsAnimationController.finish(toRecents, () -> {
if (onFinishComplete != null) {
onFinishComplete.run();
- // After we finish the recents animation, the current task id should be correctly
- // reset so that when the task is launched from Overview later, it goes through the
- // flow of starting a new task instead of finishing recents animation to app. A
- // typical example of this is (1) user swipes up from app to Overview (2) user
- // taps on QSB (3) user goes back to Overview and launch the most recent task.
- setCurrentTask(-1);
}
+ // After we finish the recents animation, the current task id should be correctly
+ // reset so that when the task is launched from Overview later, it goes through the
+ // flow of starting a new task instead of finishing recents animation to app. A
+ // typical example of this is (1) user swipes up from app to Overview (2) user
+ // taps on QSB (3) user goes back to Overview and launch the most recent task.
+ setCurrentTask(-1);
});
}
@@ -2428,7 +2413,19 @@
}
}
- /** If it's in the live tile mode, switch the running task into screenshot mode. */
+ /**
+ * Switch the current running task view to static snapshot mode,
+ * capturing the snapshot at the same time.
+ */
+ public void switchToScreenshot(Runnable onFinishRunnable) {
+ switchToScreenshot(mRunningTaskId == -1 ? null
+ : mRecentsAnimationController.screenshotTask(mRunningTaskId), onFinishRunnable);
+ }
+
+ /**
+ * Switch the current running task view to static snapshot mode, using the
+ * provided thumbnail data as the snapshot.
+ */
public void switchToScreenshot(ThumbnailData thumbnailData, Runnable onFinishRunnable) {
TaskView taskView = getRunningTaskView();
if (taskView != null) {
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index f1ac6a5..e6613eb 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -16,9 +16,7 @@
package com.android.quickstep.views;
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
-import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.QUICK_SWITCH;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -38,11 +36,9 @@
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
-import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ScrimView;
@@ -155,8 +151,7 @@
Context context = getContext();
if ((OVERVIEW.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) == 0) {
- if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()
- && SysUINavigationMode.removeShelfFromOverview(context)) {
+ if (SysUINavigationMode.removeShelfFromOverview(context)) {
// Fade in all apps background quickly to distinguish from swiping from nav bar.
mMidAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha);
mMidProgress = OverviewState.getDefaultVerticalProgress(mLauncher);
@@ -198,13 +193,6 @@
if (mProgress >= 1) {
mRemainingScreenColor = 0;
mShelfColor = 0;
- LauncherState state = mLauncher.getStateManager().getState();
- if (mSysUINavigationMode == Mode.NO_BUTTON
- && (state == BACKGROUND_APP || state == QUICK_SWITCH)
- && mLauncher.getShelfPeekAnim().isPeeking()) {
- // Show the shelf background when peeking during swipe up.
- mShelfColor = setColorAlphaBound(mEndScrim, mMidAlpha);
- }
} else if (mProgress >= mMidProgress) {
mRemainingScreenColor = 0;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
similarity index 98%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
rename to quickstep/src/com/android/quickstep/views/TaskMenuView.java
index 8b49f2c..656d59e 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -133,11 +133,6 @@
}
@Override
- public void logActionCommand(int command) {
- // TODO
- }
-
- @Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
similarity index 100%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java
rename to quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
similarity index 96%
rename from quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
rename to quickstep/src/com/android/quickstep/views/TaskView.java
index 3a359f0..321821b 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -135,6 +135,7 @@
* delegated bounds only to be updated.
*/
private TransformingTouchDelegate mIconTouchDelegate;
+ private TransformingTouchDelegate mChipTouchDelegate;
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
@@ -200,6 +201,7 @@
private View mContextualChipWrapper;
private View mContextualChip;
private final float[] mIconCenterCoords = new float[2];
+ private final float[] mChipCenterCoords = new float[2];
public TaskView(Context context) {
this(context, null);
@@ -225,10 +227,6 @@
} else {
launchTask(true /* animate */);
}
-
- mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
- Touch.TAP, Direction.NONE, getRecentsView().indexOfChild(this),
- TaskUtils.getLaunchComponentKeyForTask(getTask().key));
mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
.log(LAUNCHER_TASK_LAUNCH_TAP);
});
@@ -263,11 +261,22 @@
mIconTouchDelegate = new TransformingTouchDelegate(mIconView);
}
- public TouchDelegate getIconTouchDelegate(MotionEvent event) {
+ /**
+ * Whether the taskview should take the touch event from parent. Events passed to children
+ * that might require special handling.
+ */
+ public boolean offerTouchToChildren(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
computeAndSetIconTouchDelegate();
+ computeAndSetChipTouchDelegate();
}
- return mIconTouchDelegate;
+ if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
+ return true;
+ }
+ if (mChipTouchDelegate != null && mChipTouchDelegate.onTouchEvent(event)) {
+ return true;
+ }
+ return false;
}
private void computeAndSetIconTouchDelegate() {
@@ -282,6 +291,23 @@
(int) (mIconCenterCoords[1] + iconHalfSize));
}
+ private void computeAndSetChipTouchDelegate() {
+ if (mContextualChipWrapper != null) {
+ float chipHalfWidth = mContextualChipWrapper.getWidth() / 2f;
+ float chipHalfHeight = mContextualChipWrapper.getHeight() / 2f;
+ mChipCenterCoords[0] = chipHalfWidth;
+ mChipCenterCoords[1] = chipHalfHeight;
+ getDescendantCoordRelativeToAncestor(mContextualChipWrapper, mActivity.getDragLayer(),
+ mChipCenterCoords,
+ false);
+ mChipTouchDelegate.setBounds(
+ (int) (mChipCenterCoords[0] - chipHalfWidth),
+ (int) (mChipCenterCoords[1] - chipHalfHeight),
+ (int) (mChipCenterCoords[0] + chipHalfWidth),
+ (int) (mChipCenterCoords[1] + chipHalfHeight));
+ }
+ }
+
/**
* The modalness of this view is how it should be displayed when it is shown on its own in the
* modal state of overview.
@@ -716,6 +742,7 @@
mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(50);
}
if (mContextualChipWrapper != null) {
+ mChipTouchDelegate = new TransformingTouchDelegate(mContextualChipWrapper);
mContextualChipWrapper.animate().alpha(1f).setDuration(50);
}
}
@@ -737,6 +764,7 @@
View oldContextualChipWrapper = mContextualChipWrapper;
mContextualChipWrapper = null;
mContextualChip = null;
+ mChipTouchDelegate = null;
return oldContextualChipWrapper;
}
diff --git a/res/layout/search_result_play_item.xml b/res/layout/search_result_play_item.xml
new file mode 100644
index 0000000..4e82eaf
--- /dev/null
+++ b/res/layout/search_result_play_item.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<com.android.launcher3.views.SearchResultPlayItem xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dp"
+ android:orientation="horizontal">
+ <View
+ android:id="@+id/icon"
+ android:layout_width="@dimen/deep_shortcut_icon_size"
+ android:layout_height="@dimen/deep_shortcut_icon_size"
+ android:layout_gravity="start|center_vertical"
+ android:background="@drawable/ic_deepshortcut_placeholder" />
+
+ <LinearLayout
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:padding="8dp">
+
+ <TextView
+ android:id="@+id/title_view"
+ style="@style/TextHeadline"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAlignment="viewStart"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="16sp" />
+
+ <TextView
+ android:id="@+id/detail_0"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView
+ android:id="@+id/detail_1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorPrimary"
+ android:visibility="gone" />
+
+ <TextView
+ android:id="@+id/detail_2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="?android:attr/textColorPrimary"
+ android:visibility="gone" />
+ </LinearLayout>
+ <Button
+ android:id="@+id/try_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|center_vertical"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/search_action_try_now">
+ </Button>
+
+
+</com.android.launcher3.views.SearchResultPlayItem>
diff --git a/res/layout/search_result_settings_row.xml b/res/layout/search_result_settings_row.xml
new file mode 100644
index 0000000..19daf34
--- /dev/null
+++ b/res/layout/search_result_settings_row.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2020 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.
+-->
+<com.android.launcher3.views.SearchSettingsRowView xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/TextHeadline"
+ android:id="@+id/section_title"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:padding="4dp"
+ android:minHeight="48dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="14sp">
+
+ <TextView
+ android:id="@+id/title"
+ style="@style/TextTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="4dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="16sp" />
+
+ <TextView
+ android:id="@+id/description"
+ style="@style/TextTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="14sp" />
+
+ <TextView
+ android:id="@+id/breadcrumbs"
+ style="@style/TextTitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:alpha=".7"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="14sp" />
+
+
+</com.android.launcher3.views.SearchSettingsRowView>
\ No newline at end of file
diff --git a/quickstep/recents_ui_overrides/res/values/config.xml b/res/layout/search_result_slice.xml
similarity index 69%
rename from quickstep/recents_ui_overrides/res/values/config.xml
rename to res/layout/search_result_slice.xml
index 120e034..ea1d49a 100644
--- a/quickstep/recents_ui_overrides/res/values/config.xml
+++ b/res/layout/search_result_slice.xml
@@ -5,7 +5,7 @@
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
+ 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,
@@ -13,6 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
- <integer name="max_depth_blur_radius">150</integer>
-</resources>
\ No newline at end of file
+<androidx.slice.widget.SliceView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingHorizontal="4dp" />
\ No newline at end of file
diff --git a/res/layout/search_section_title.xml b/res/layout/search_section_title.xml
index c39a641..9419015 100644
--- a/res/layout/search_section_title.xml
+++ b/res/layout/search_section_title.xml
@@ -13,11 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/section_title"
- android:textSize="14sp"
- android:fontFamily="@style/TextHeadline"
- android:layout_width="wrap_content"
- android:textColor="?android:attr/textColorPrimary"
- android:padding="4dp"
- android:layout_height="wrap_content"/>
\ No newline at end of file
+<com.android.launcher3.views.SearchSectionHeaderView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/section_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:fontFamily="@style/TextHeadline"
+ android:padding="4dp"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="14sp" />
\ No newline at end of file
diff --git a/res/values/colors.xml b/res/values/colors.xml
index fe9717c..f56fbaa 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -35,9 +35,6 @@
<color name="icon_background">#E0E0E0</color> <!-- Gray 300 -->
- <color name="all_apps_section_fill">#32c0c0c0</color>
- <color name="all_apps_section_focused_item">#40c0c0c0</color>
-
<color name="gesture_tutorial_ripple_color">#A0C2F9</color> <!-- Light Blue -->
<color name="gesture_tutorial_fake_task_view_color">#6DA1FF</color> <!-- Light Blue -->
<color name="gesture_tutorial_action_button_label_color">#FFFFFFFF</color>
diff --git a/res/values/config.xml b/res/values/config.xml
index dc8bdff..fc0a5e1 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -69,7 +69,6 @@
<string name="app_launch_tracker_class" translatable="false"></string>
<string name="test_information_handler_class" translatable="false"></string>
<string name="launcher_activity_logic_class" translatable="false"></string>
- <string name="prediction_model_class" translatable="false"></string>
<string name="model_delegate_class" translatable="false"></string>
<!-- View ID to use for QSB widget -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ef47eef..ad3e2b7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -70,6 +70,8 @@
<!--All apps Search-->
<!-- Section title for apps [CHAR_LIMIT=50] -->
<string name="search_corpus_apps">Apps</string>
+ <!-- try instant app action for play search result [CHAR_LIMIT=50 -->
+ <string name="search_action_try_now">Try Now</string>
<!-- Popup items -->
<!-- Text to display as the header above notifications. [CHAR_LIMIT=30] -->
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 3455cb8..7e72208 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -44,12 +44,6 @@
android:defaultValue="@bool/allow_rotation"
android:persistent="true" />
- <SwitchPreference
- android:key="pref_grid_options"
- android:title="Enable grid options"
- android:defaultValue="false"
- android:persistent="true" />
-
<androidx.preference.PreferenceScreen
android:key="pref_developer_options"
android:persistent="false"
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 3bfe379..3c34444 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -36,8 +36,6 @@
import androidx.annotation.IntDef;
import com.android.launcher3.anim.PendingAnimation;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -129,8 +127,7 @@
public final void close(boolean animate) {
animate &= areAnimatorsEnabled();
if (mIsOpen) {
- BaseActivity.fromContext(getContext()).getUserEventDispatcher()
- .resetElapsedContainerMillis("container closed");
+ // Add to WW logging
}
handleClose(animate);
mIsOpen = false;
@@ -145,12 +142,6 @@
public void addHintCloseAnim(
float distanceToMove, Interpolator interpolator, PendingAnimation target) { }
- public abstract void logActionCommand(int command);
-
- public int getLogContainerType() {
- return ContainerType.DEFAULT_CONTAINERTYPE;
- }
-
public final boolean isOpen() {
return mIsOpen;
}
@@ -159,7 +150,6 @@
/** @return Whether the back is consumed. If false, Launcher will handle the back as well. */
public boolean onBackPressed() {
- logActionCommand(Action.Command.BACK);
close(true);
return true;
}
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index 6f7b684..168d9c4 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -537,11 +537,6 @@
}
@Override
- public void logActionCommand(int command) {
- // TODO: Log this case.
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_WIDGET_RESIZE_FRAME) != 0;
}
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index cbc3abc..0d90602 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -193,7 +193,6 @@
getSystemService(LauncherApps.class).startMainActivity(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
}
- getUserEventDispatcher().logAppLaunch(v, intent, user);
if (item != null) {
InstanceId instanceId = new InstanceIdSequence().newInstanceId();
logAppLaunch(item, instanceId);
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 55d5de7..06bb263 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -79,7 +79,7 @@
private static final int DISPLAY_FOLDER = 2;
private static final int DISPLAY_HERO_APP = 5;
- private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed};
+ private static final int[] STATE_PRESSED = new int[]{android.R.attr.state_pressed};
private final PointF mTranslationForReorderBounce = new PointF(0, 0);
private final PointF mTranslationForReorderPreview = new PointF(0, 0);
@@ -280,7 +280,10 @@
applyDotState(info, false /* animate */);
}
- public void applyFromPackageItemInfo(PackageItemInfo info) {
+ /**
+ * Apply label and tag using a generic {@link ItemInfoWithIcon}
+ */
+ public void applyFromItemInfoWithIcon(ItemInfoWithIcon info) {
applyIconAndLabel(info);
// We don't need to check the info since it's not a WorkspaceItemInfo
super.setTag(info);
@@ -407,12 +410,14 @@
/**
* Draws the notification dot in the top right corner of the icon bounds.
+ *
* @param canvas The canvas to draw to.
*/
protected void drawDotIfNecessary(Canvas canvas) {
if (!mForceHideDot && (hasDot() || mDotParams.scale > 0)) {
getIconBounds(mDotParams.iconBounds);
- Utilities.scaleRectAboutCenter(mDotParams.iconBounds, IconShape.getNormalizationScale());
+ Utilities.scaleRectAboutCenter(mDotParams.iconBounds,
+ IconShape.getNormalizationScale());
final int scrollX = getScrollX();
final int scrollY = getScrollY();
canvas.translate(scrollX, scrollY);
@@ -507,6 +512,7 @@
/**
* Creates an animator to fade the text in or out.
+ *
* @param fadeIn Whether the text should fade in or fade out.
*/
public ObjectAnimator createTextAlphaAnimator(boolean fadeIn) {
@@ -663,7 +669,7 @@
applyFromWorkspaceItem((WorkspaceItemInfo) info);
mActivity.invalidateParent(info);
} else if (info instanceof PackageItemInfo) {
- applyFromPackageItemInfo((PackageItemInfo) info);
+ applyFromItemInfoWithIcon((PackageItemInfo) info);
}
mDisableRelayout = false;
@@ -761,7 +767,8 @@
public SafeCloseable prepareDrawDragView() {
resetIconScale();
setForceHideDot(true);
- return () -> { };
+ return () -> {
+ };
}
private void resetIconScale() {
diff --git a/src/com/android/launcher3/DragSource.java b/src/com/android/launcher3/DragSource.java
index d4d7b99..ba227d4 100644
--- a/src/com/android/launcher3/DragSource.java
+++ b/src/com/android/launcher3/DragSource.java
@@ -19,12 +19,11 @@
import android.view.View;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
/**
* Interface defining an object that can originate a drag.
*/
-public interface DragSource extends LogContainerProvider {
+public interface DragSource {
/**
* A callback made back to the source after an item from this source has been dropped on a
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index b27abc4..fd4c30c 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -113,18 +113,6 @@
return res;
}
-
-
- /**
- * This is used to determine if an object is dropped at a different location than it was
- * dragged from
- */
- public boolean isMoved() {
- return dragInfo.cellX != originalDragInfo.cellX
- || dragInfo.cellY != originalDragInfo.cellY
- || dragInfo.screenId != originalDragInfo.screenId
- || dragInfo.container != originalDragInfo.container;
- }
}
/**
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index d64967b..02c6162 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -24,6 +24,7 @@
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.UiThreadHelper;
@@ -130,6 +131,10 @@
public void reset() {
if (!TextUtils.isEmpty(getText())) {
setText("");
+ } else {
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ return;
+ }
}
if (isFocused()) {
View nextFocus = focusSearch(View.FOCUS_DOWN);
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
deleted file mode 100644
index d2b05c5..0000000
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-package com.android.launcher3;
-
-import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
-
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
-import static com.android.launcher3.LauncherSettings.Favorites.PROFILE_ID;
-import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent;
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.pm.LauncherActivityInfo;
-import android.content.pm.LauncherApps;
-import android.content.pm.ShortcutInfo;
-import android.os.Process;
-import android.os.UserHandle;
-import android.util.Log;
-import android.util.Pair;
-
-import androidx.annotation.Nullable;
-import androidx.annotation.WorkerThread;
-
-import com.android.launcher3.LauncherSettings.Favorites;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.shortcuts.ShortcutKey;
-import com.android.launcher3.shortcuts.ShortcutRequest;
-import com.android.launcher3.util.Preconditions;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.json.JSONStringer;
-
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-public class InstallShortcutReceiver {
-
- public static final int FLAG_ACTIVITY_PAUSED = 1;
- public static final int FLAG_LOADER_RUNNING = 2;
- public static final int FLAG_DRAG_AND_DROP = 4;
-
- // Determines whether to defer installing shortcuts immediately until
- // processAllPendingInstalls() is called.
- private static int sInstallQueueDisabledFlags = 0;
-
- private static final String TAG = "InstallShortcutReceiver";
- private static final boolean DBG = false;
-
- // The set of shortcuts that are pending install
- private static final String APPS_PENDING_INSTALL = "apps_to_install";
-
- public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
- public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
-
- @WorkerThread
- private static void addToQueue(Context context, PendingInstallShortcutInfo info) {
- String encoded = info.encodeToString(context);
- SharedPreferences prefs = Utilities.getPrefs(context);
- Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
- strings = (strings != null) ? new HashSet<>(strings) : new HashSet<>(1);
- strings.add(encoded);
- prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
- }
-
- @WorkerThread
- private static void flushQueueInBackground(Context context) {
- if (Launcher.ACTIVITY_TRACKER.getCreatedActivity() == null) {
- // Launcher not loaded
- return;
- }
-
- ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
- SharedPreferences prefs = Utilities.getPrefs(context);
- Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
- if (strings == null) {
- return;
- }
-
- for (String encoded : strings) {
- PendingInstallShortcutInfo info = decode(encoded, context);
- if (info == null) {
- continue;
- }
-
- // Generate a shortcut info to add into the model
- installQueue.add(info.getItemInfo(context));
- }
- prefs.edit().remove(APPS_PENDING_INSTALL).apply();
- if (!installQueue.isEmpty()) {
- LauncherAppState.getInstance(context).getModel()
- .addAndBindAddedWorkspaceItems(installQueue);
- }
- }
-
- public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
- UserHandle user) {
- if (packageNames.isEmpty()) {
- return;
- }
- Preconditions.assertWorkerThread();
-
- SharedPreferences sp = Utilities.getPrefs(context);
- Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) {
- Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
- + ", removing packages: " + packageNames);
- }
- if (strings == null || ((Collection) strings).isEmpty()) {
- return;
- }
- Set<String> newStrings = new HashSet<>(strings);
- Iterator<String> newStringsIter = newStrings.iterator();
- while (newStringsIter.hasNext()) {
- String encoded = newStringsIter.next();
- try {
- Decoder decoder = new Decoder(encoded, context);
- if (packageNames.contains(getIntentPackage(decoder.intent))
- && user.equals(decoder.user)) {
- newStringsIter.remove();
- }
- } catch (JSONException | URISyntaxException e) {
- Log.d(TAG, "Exception reading shortcut to add: " + e);
- newStringsIter.remove();
- }
- }
- sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
- }
-
- public static void queueShortcut(ShortcutInfo info, Context context) {
- queuePendingShortcutInfo(new PendingInstallShortcutInfo(info), context);
- }
-
- public static void queueWidget(AppWidgetProviderInfo info, int widgetId, Context context) {
- queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, widgetId), context);
- }
-
- public static void queueApplication(
- String packageName, UserHandle userHandle, Context context) {
- queuePendingShortcutInfo(new PendingInstallShortcutInfo(packageName, userHandle), context);
- }
-
- public static HashSet<ShortcutKey> getPendingShortcuts(Context context) {
- HashSet<ShortcutKey> result = new HashSet<>();
-
- Set<String> strings = Utilities.getPrefs(context).getStringSet(APPS_PENDING_INSTALL, null);
- if (strings == null || ((Collection) strings).isEmpty()) {
- return result;
- }
-
- for (String encoded : strings) {
- try {
- Decoder decoder = new Decoder(encoded, context);
- if (decoder.optInt(Favorites.ITEM_TYPE, -1) == ITEM_TYPE_DEEP_SHORTCUT) {
- result.add(ShortcutKey.fromIntent(decoder.intent, decoder.user));
- }
- } catch (JSONException | URISyntaxException e) {
- Log.d(TAG, "Exception reading shortcut to add: " + e);
- }
- }
- return result;
- }
-
- private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
- // Queue the item up for adding if launcher has not loaded properly yet
- MODEL_EXECUTOR.post(() -> addToQueue(context, info));
- flushInstallQueue(context);
- }
-
- public static void enableInstallQueue(int flag) {
- sInstallQueueDisabledFlags |= flag;
- }
- public static void disableAndFlushInstallQueue(int flag, Context context) {
- sInstallQueueDisabledFlags &= ~flag;
- flushInstallQueue(context);
- }
-
- static void flushInstallQueue(Context context) {
- if (sInstallQueueDisabledFlags != 0) {
- return;
- }
- MODEL_EXECUTOR.post(() -> flushQueueInBackground(context));
- }
-
-
- private static class PendingInstallShortcutInfo extends ItemInfo {
-
- final Intent intent;
-
- @Nullable ShortcutInfo shortcutInfo;
- @Nullable AppWidgetProviderInfo providerInfo;
-
- /**
- * Initializes a PendingInstallShortcutInfo to represent a pending launcher target.
- */
- public PendingInstallShortcutInfo(String packageName, UserHandle userHandle) {
- itemType = Favorites.ITEM_TYPE_APPLICATION;
- intent = new Intent().setPackage(packageName);
- user = userHandle;
- }
-
- /**
- * Initializes a PendingInstallShortcutInfo to represent a deep shortcut.
- */
- public PendingInstallShortcutInfo(ShortcutInfo info) {
- itemType = Favorites.ITEM_TYPE_DEEP_SHORTCUT;
- intent = ShortcutKey.makeIntent(info);
- user = info.getUserHandle();
-
- shortcutInfo = info;
- }
-
- /**
- * Initializes a PendingInstallShortcutInfo to represent an app widget.
- */
- public PendingInstallShortcutInfo(AppWidgetProviderInfo info, int widgetId) {
- itemType = Favorites.ITEM_TYPE_APPWIDGET;
- intent = new Intent()
- .setComponent(info.provider)
- .putExtra(EXTRA_APPWIDGET_ID, widgetId);
- user = info.getProfile();
-
- providerInfo = info;
- }
-
- public String encodeToString(Context context) {
- try {
- return new JSONStringer()
- .object()
- .key(Favorites.ITEM_TYPE).value(itemType)
- .key(Favorites.INTENT).value(intent.toUri(0))
- .key(PROFILE_ID).value(
- UserCache.INSTANCE.get(context).getSerialNumberForUser(user))
- .endObject().toString();
- } catch (JSONException e) {
- Log.d(TAG, "Exception when adding shortcut: " + e);
- return null;
- }
- }
-
- public Pair<ItemInfo, Object> getItemInfo(Context context) {
- switch (itemType) {
- case ITEM_TYPE_APPLICATION: {
- String packageName = intent.getPackage();
- List<LauncherActivityInfo> laiList =
- context.getSystemService(LauncherApps.class)
- .getActivityList(packageName, user);
-
- final WorkspaceItemInfo si = new WorkspaceItemInfo();
- si.user = user;
- si.itemType = ITEM_TYPE_APPLICATION;
-
- LauncherActivityInfo lai;
- boolean usePackageIcon = laiList.isEmpty();
- if (usePackageIcon) {
- lai = null;
- si.intent = makeLaunchIntent(new ComponentName(packageName, ""))
- .setPackage(packageName);
- si.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
- } else {
- lai = laiList.get(0);
- si.intent = makeLaunchIntent(lai);
- }
- LauncherAppState.getInstance(context).getIconCache()
- .getTitleAndIcon(si, () -> lai, usePackageIcon, false);
- return Pair.create(si, null);
- }
- case ITEM_TYPE_DEEP_SHORTCUT: {
- WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, context);
- LauncherAppState.getInstance(context).getIconCache()
- .getShortcutIcon(itemInfo, shortcutInfo);
- return Pair.create(itemInfo, shortcutInfo);
- }
- case ITEM_TYPE_APPWIDGET: {
- LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
- .fromProviderInfo(context, providerInfo);
- LauncherAppWidgetInfo widgetInfo = new LauncherAppWidgetInfo(
- intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0),
- info.provider);
- InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
- widgetInfo.minSpanX = info.minSpanX;
- widgetInfo.minSpanY = info.minSpanY;
- widgetInfo.spanX = Math.min(info.spanX, idp.numColumns);
- widgetInfo.spanY = Math.min(info.spanY, idp.numRows);
- widgetInfo.user = user;
- return Pair.create(widgetInfo, providerInfo);
- }
- }
- return null;
- }
- }
-
- private static String getIntentPackage(Intent intent) {
- return intent.getComponent() == null
- ? intent.getPackage() : intent.getComponent().getPackageName();
- }
-
- private static PendingInstallShortcutInfo decode(String encoded, Context context) {
- try {
- Decoder decoder = new Decoder(encoded, context);
- switch (decoder.optInt(Favorites.ITEM_TYPE, -1)) {
- case Favorites.ITEM_TYPE_APPLICATION:
- return new PendingInstallShortcutInfo(
- decoder.intent.getPackage(), decoder.user);
- case Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
- List<ShortcutInfo> si = ShortcutKey.fromIntent(decoder.intent, decoder.user)
- .buildRequest(context)
- .query(ShortcutRequest.ALL);
- if (si.isEmpty()) {
- return null;
- } else {
- return new PendingInstallShortcutInfo(si.get(0));
- }
- }
- case Favorites.ITEM_TYPE_APPWIDGET: {
- int widgetId = decoder.intent.getIntExtra(EXTRA_APPWIDGET_ID, 0);
- AppWidgetProviderInfo info =
- AppWidgetManager.getInstance(context).getAppWidgetInfo(widgetId);
- if (info == null || !info.provider.equals(decoder.intent.getComponent())
- || !info.getProfile().equals(decoder.user)) {
- return null;
- }
- return new PendingInstallShortcutInfo(info, widgetId);
- }
- default:
- Log.e(TAG, "Unknown item type");
- }
- } catch (JSONException | URISyntaxException e) {
- Log.d(TAG, "Exception reading shortcut to add: " + e);
- }
- return null;
- }
-
- private static class Decoder extends JSONObject {
- public final Intent intent;
- public final UserHandle user;
-
- private Decoder(String encoded, Context context) throws JSONException, URISyntaxException {
- super(encoded);
- intent = Intent.parseUri(getString(Favorites.INTENT), 0);
- user = has(PROFILE_ID)
- ? UserCache.INSTANCE.get(context).getUserForSerialNumber(getLong(PROFILE_ID))
- : Process.myUserHandle();
- if (user == null || intent == null) {
- throw new JSONException("Invalid data");
- }
- }
- }
-}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3f64df3..cacd3fb 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -24,7 +24,6 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ICON_SURFACE;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
import static com.android.launcher3.AbstractFloatingView.TYPE_SNACKBAR;
-import static com.android.launcher3.InstallShortcutReceiver.FLAG_DRAG_AND_DROP;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.FLAG_CLOSE_POPUPS;
@@ -34,7 +33,6 @@
import static com.android.launcher3.LauncherState.NO_OFFSET;
import static com.android.launcher3.LauncherState.NO_SCALE;
import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOAD;
@@ -43,6 +41,9 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONRESUME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ONSTOP;
import static com.android.launcher3.logging.StatsLogManager.containerTypeToAtomState;
+import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
+import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
+import static com.android.launcher3.model.ItemInstallQueue.FLAG_LOADER_RUNNING;
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
import static com.android.launcher3.popup.SystemShortcut.INSTALL;
import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
@@ -109,7 +110,6 @@
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
-import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderGridOrganizer;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.icons.IconCache;
@@ -120,6 +120,7 @@
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.ModelUtils;
import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.model.data.AppInfo;
@@ -451,7 +452,7 @@
float alpha = 1f - mCurrentAssistantVisibility;
if (finalState == NORMAL) {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
- } else if (finalState == OVERVIEW || finalState == OVERVIEW_PEEK) {
+ } else if (finalState == OVERVIEW) {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
mScrimView.setAlpha(alpha);
} else {
@@ -551,7 +552,7 @@
LauncherState state = mStateManager.getState();
if (state == NORMAL) {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
- } else if (state == OVERVIEW || state == OVERVIEW_PEEK) {
+ } else if (state == OVERVIEW) {
mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha);
mScrimView.setAlpha(alpha);
}
@@ -909,11 +910,10 @@
@CallSuper
protected void onDeferredResumed() {
logStopAndResume(Action.Command.RESUME);
- getUserEventDispatcher().startSession();
// Process any items that were added while Launcher was away.
- InstallShortcutReceiver.disableAndFlushInstallQueue(
- InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED, this);
+ ItemInstallQueue.INSTANCE.get(this)
+ .resumeModelPush(FLAG_ACTIVITY_PAUSED);
// Refresh shortcuts if the permission changed.
mModel.validateModelDataOnResume();
@@ -927,6 +927,7 @@
protected void handlePendingActivityRequest() { }
private void logStopAndResume(int command) {
+ if (mPendingExecutor != null) return;
int pageIndex = mWorkspace.isOverlayShown() ? -1 : mWorkspace.getCurrentPage();
int containerType = mStateManager.getState().containerType;
@@ -1007,7 +1008,7 @@
if (state == SPRING_LOADED) {
// Prevent any Un/InstallShortcutReceivers from updating the db while we are
// not on homescreen
- InstallShortcutReceiver.enableInstallQueue(FLAG_DRAG_AND_DROP);
+ ItemInstallQueue.INSTANCE.get(this).pauseModelPush(FLAG_DRAG_AND_DROP);
getRotationHelper().setCurrentStateRequest(REQUEST_LOCK);
mWorkspace.showPageIndicatorAtCurrentScroll();
@@ -1032,7 +1033,8 @@
if (state == NORMAL) {
// Re-enable any Un/InstallShortcutReceiver and now process any queued items
- InstallShortcutReceiver.disableAndFlushInstallQueue(FLAG_DRAG_AND_DROP, this);
+ ItemInstallQueue.INSTANCE.get(this)
+ .resumeModelPush(FLAG_DRAG_AND_DROP);
// Clear any rotation locks when going to normal state
getRotationHelper().setCurrentStateRequest(REQUEST_NONE);
@@ -1066,7 +1068,7 @@
@Override
protected void onPause() {
// Ensure that items added to Launcher are queued until Launcher returns
- InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED);
+ ItemInstallQueue.INSTANCE.get(this).pauseModelPush(FLAG_ACTIVITY_PAUSED);
super.onPause();
mDragController.cancelDrag();
@@ -1744,16 +1746,6 @@
}
/**
- * Called when a workspace item is converted into a folder
- */
- public void folderCreatedFromItem(Folder folder, WorkspaceItemInfo itemInfo){}
-
- /**
- * Called when a folder is converted into a workspace item
- */
- public void folderConvertedToItem(Folder folder, WorkspaceItemInfo itemInfo) {}
-
- /**
* Unbinds the view for the specified item, and removes the item and all its children.
*
* @param v the view being removed.
@@ -2190,9 +2182,6 @@
workspace.requestLayout();
}
- @Override
- public void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks) { }
-
/**
* Add the views for a widget to the workspace.
*/
@@ -2421,8 +2410,8 @@
mPendingActivityResult = null;
}
- InstallShortcutReceiver.disableAndFlushInstallQueue(
- InstallShortcutReceiver.FLAG_LOADER_RUNNING, this);
+ ItemInstallQueue.INSTANCE.get(this)
+ .resumeModelPush(FLAG_LOADER_RUNNING);
// When undoing the removal of the last item on a page, return to that page.
// Since we are just resetting the current page without user interaction,
@@ -2449,8 +2438,8 @@
private ValueAnimator createNewAppBounceAnimation(View v, int i) {
ValueAnimator bounceAnim = new PropertyListBuilder().alpha(1).scale(1).build(v)
- .setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
- bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
+ .setDuration(ItemInstallQueue.NEW_SHORTCUT_BOUNCE_DURATION);
+ bounceAnim.setStartDelay(i * ItemInstallQueue.NEW_SHORTCUT_STAGGER_DELAY);
bounceAnim.setInterpolator(new OvershootInterpolator(BOUNCE_ANIMATION_TENSION));
return bounceAnim;
}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 782a869..b278e81 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -33,7 +33,6 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.LauncherIcons;
-import com.android.launcher3.model.PredictionModel;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.InstallSessionTracker;
@@ -58,7 +57,6 @@
private final IconCache mIconCache;
private final WidgetPreviewLoader mWidgetCache;
private final InvariantDeviceProfile mInvariantDeviceProfile;
- private final PredictionModel mPredictionModel;
private SecureSettingsObserver mNotificationDotsObserver;
private InstallSessionTracker mInstallSessionTracker;
@@ -125,7 +123,6 @@
mIconCache = new IconCache(mContext, mInvariantDeviceProfile, iconCacheFileName);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
mModel = new LauncherModel(context, this, mIconCache, AppFilter.newInstance(mContext));
- mPredictionModel = PredictionModel.newInstance(mContext);
}
protected void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
@@ -182,10 +179,6 @@
return mModel;
}
- public PredictionModel getPredictionModel() {
- return mPredictionModel;
- }
-
public WidgetPreviewLoader getWidgetCache() {
return mWidgetCache;
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index e2568d5..8458152 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -43,6 +43,7 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.model.CacheDataUpdatedTask;
+import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.LoaderResults;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.model.ModelDelegate;
@@ -60,7 +61,6 @@
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
@@ -85,7 +85,6 @@
private final LauncherAppState mApp;
private final Object mLock = new Object();
- private final LooperExecutor mMainExecutor = MAIN_EXECUTOR;
private LoaderTask mLoaderTask;
private boolean mIsLoaderTaskRunning;
@@ -220,6 +219,13 @@
}
/**
+ * Called when the workspace items have drastically changed
+ */
+ public void onWorkspaceUiChanged() {
+ MODEL_EXECUTOR.execute(mModelDelegate::workspaceLoadComplete);
+ }
+
+ /**
* Called when the model is destroyed
*/
public void destroy() {
@@ -330,20 +336,21 @@
*/
public boolean startLoader() {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
- InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
+ ItemInstallQueue.INSTANCE.get(mApp.getContext())
+ .pauseModelPush(ItemInstallQueue.FLAG_LOADER_RUNNING);
synchronized (mLock) {
// Don't bother to start the thread if we know it's not going to do anything
final Callbacks[] callbacksList = getCallbacks();
if (callbacksList.length > 0) {
// Clear any pending bind-runnables from the synchronized load process.
for (Callbacks cb : callbacksList) {
- mMainExecutor.execute(cb::clearPendingBinds);
+ MAIN_EXECUTOR.execute(cb::clearPendingBinds);
}
// If there is already one running, tell it to stop.
stopLoader();
LoaderResults loaderResults = new LoaderResults(
- mApp, mBgDataModel, mBgAllAppsList, callbacksList, mMainExecutor);
+ mApp, mBgDataModel, mBgAllAppsList, callbacksList);
if (mModelLoaded && !mIsLoaderTaskRunning) {
// Divide the set of loaded items into those that we are binding synchronously,
// and everything else that is to be bound normally (asynchronously).
@@ -530,7 +537,7 @@
}
public void enqueueModelUpdateTask(ModelUpdateTask task) {
- task.init(mApp, this, mBgDataModel, mBgAllAppsList, mMainExecutor);
+ task.init(mApp, this, mBgDataModel, mBgAllAppsList, MAIN_EXECUTOR);
MODEL_EXECUTOR.execute(task);
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index fdbbf4e..2973cf7 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -100,10 +100,12 @@
public static final int SCHEMA_VERSION = 28;
public static final String AUTHORITY = BuildConfig.APPLICATION_ID + ".settings";
+ public static final String KEY_LAYOUT_PROVIDER_AUTHORITY = "KEY_LAYOUT_PROVIDER_AUTHORITY";
static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
protected DatabaseHelper mOpenHelper;
+ protected String mProviderAuthority;
private long mLastRestoreTimestamp = 0L;
@@ -367,7 +369,8 @@
case LauncherSettings.Settings.METHOD_WAS_EMPTY_DB_CREATED : {
Bundle result = new Bundle();
result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
- Utilities.getPrefs(getContext()).getBoolean(EMPTY_DATABASE_CREATED, false));
+ Utilities.getPrefs(getContext()).getBoolean(
+ mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false));
return result;
}
case LauncherSettings.Settings.METHOD_DELETE_EMPTY_FOLDERS: {
@@ -437,6 +440,7 @@
getContext(), true /* forMigration */)));
return result;
}
+ return null;
}
case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: {
if (MULTI_DB_GRID_MIRATION_ALGO.get()) {
@@ -450,6 +454,23 @@
() -> mOpenHelper));
return result;
}
+ return null;
+ }
+ case LauncherSettings.Settings.METHOD_SWITCH_DATABASE: {
+ if (TextUtils.equals(arg, mOpenHelper.getDatabaseName())) return null;
+ final DatabaseHelper helper = mOpenHelper;
+ if (extras == null || !extras.containsKey(KEY_LAYOUT_PROVIDER_AUTHORITY)) {
+ mProviderAuthority = null;
+ } else {
+ mProviderAuthority = extras.getString(KEY_LAYOUT_PROVIDER_AUTHORITY);
+ }
+ mOpenHelper = DatabaseHelper.createDatabaseHelper(
+ getContext(), arg, false /* forMigration */);
+ helper.close();
+ LauncherAppState app = LauncherAppState.getInstanceNoCreate();
+ if (app == null) return null;
+ app.getModel().forceReload();
+ return null;
}
}
return null;
@@ -492,7 +513,8 @@
}
private void clearFlagEmptyDbCreated() {
- Utilities.getPrefs(getContext()).edit().remove(EMPTY_DATABASE_CREATED).commit();
+ Utilities.getPrefs(getContext()).edit()
+ .remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit();
}
/**
@@ -505,7 +527,7 @@
synchronized private void loadDefaultFavoritesIfNecessary() {
SharedPreferences sp = Utilities.getPrefs(getContext());
- if (sp.getBoolean(EMPTY_DATABASE_CREATED, false)) {
+ if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
Log.d(TAG, "loading default workspace");
AppWidgetHost widgetHost = mOpenHelper.newLauncherWidgetHost();
@@ -553,8 +575,13 @@
*/
private AutoInstallsLayout createWorkspaceLoaderFromAppRestriction(AppWidgetHost widgetHost) {
Context ctx = getContext();
- String authority = Settings.Secure.getString(ctx.getContentResolver(),
- "launcher3.layout.provider");
+ final String authority;
+ if (!TextUtils.isEmpty(mProviderAuthority)) {
+ authority = mProviderAuthority;
+ } else {
+ authority = Settings.Secure.getString(ctx.getContentResolver(),
+ "launcher3.layout.provider");
+ }
if (TextUtils.isEmpty(authority)) {
return null;
}
@@ -694,11 +721,25 @@
}
/**
+ * Re-composite given key in respect to database. If the current db is
+ * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
+ * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
+ * string will be "EMPTY_DATABASE_CREATED@minimal.db".
+ */
+ String getKey(final String key) {
+ if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
+ return key;
+ }
+ return key + "@" + getDatabaseName();
+ }
+
+ /**
* Overriden in tests.
*/
protected void onEmptyDbCreated() {
// Set the flag for empty DB
- Utilities.getPrefs(mContext).edit().putBoolean(EMPTY_DATABASE_CREATED, true).commit();
+ Utilities.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
+ .commit();
}
public long getSerialNumberForUser(UserHandle user) {
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 5512654..58a418e 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -354,14 +354,20 @@
public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview";
+ public static final String METHOD_SWITCH_DATABASE = "switch_database";
+
public static final String EXTRA_VALUE = "value";
public static Bundle call(ContentResolver cr, String method) {
- return call(cr, method, null);
+ return call(cr, method, null /* arg */);
}
public static Bundle call(ContentResolver cr, String method, String arg) {
- return cr.call(CONTENT_URI, method, arg, null);
+ return call(cr, method, arg, null /* extras */);
+ }
+
+ public static Bundle call(ContentResolver cr, String method, String arg, Bundle extras) {
+ return cr.call(CONTENT_URI, method, arg, extras);
}
}
}
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index 39b0f2f..b6bc500 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -21,7 +21,6 @@
import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_MODAL_TASK_STATE_ORDINAL;
-import static com.android.launcher3.testing.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL;
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
@@ -117,8 +116,6 @@
public static final LauncherState HINT_STATE = new HintState(HINT_STATE_ORDINAL);
public static final LauncherState OVERVIEW = new OverviewState(OVERVIEW_STATE_ORDINAL);
- public static final LauncherState OVERVIEW_PEEK =
- OverviewState.newPeekState(OVERVIEW_PEEK_STATE_ORDINAL);
public static final LauncherState OVERVIEW_MODAL_TASK = OverviewState.newModalTaskState(
OVERVIEW_MODAL_TASK_STATE_ORDINAL);
public static final LauncherState QUICK_SWITCH =
diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java
index 56875bb..2df7f5a 100644
--- a/src/com/android/launcher3/SecondaryDropTarget.java
+++ b/src/com/android/launcher3/SecondaryDropTarget.java
@@ -49,7 +49,6 @@
import com.android.launcher3.util.Themes;
import java.net.URISyntaxException;
-import java.util.ArrayList;
/**
* Drop target which provides a secondary option for an item.
@@ -340,12 +339,6 @@
}
@Override
- public void fillInLogContainerData(ItemInfo childInfo, Target child,
- ArrayList<Target> parents) {
- mOriginal.fillInLogContainerData(childInfo, child, parents);
- }
-
- @Override
public void onLauncherResume() {
// We use MATCH_UNINSTALLED_PACKAGES as the app can be on SD card as well.
if (new PackageManagerHelper(mContext).getApplicationInfo(mPackageName,
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index e48ffb9..007e5f5 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -25,6 +25,7 @@
import android.os.UserHandle;
import android.text.TextUtils;
+import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.pm.InstallSessionHelper;
/**
@@ -59,7 +60,8 @@
return;
}
- InstallShortcutReceiver.queueApplication(info.getAppPackageName(), user, context);
+ ItemInstallQueue.INSTANCE.get(context)
+ .queueItem(info.getAppPackageName(), user);
}
public static boolean isEnabled(Context context) {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 3ef4bf6..45aaa1b 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -22,12 +22,12 @@
import static com.android.launcher3.LauncherState.FLAG_MULTI_PAGE;
import static com.android.launcher3.LauncherState.FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED;
import static com.android.launcher3.LauncherState.FLAG_WORKSPACE_INACCESSIBLE;
+import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;
-import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPELEFT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPERIGHT;
@@ -99,7 +99,6 @@
import com.android.launcher3.touch.WorkspaceTouchListener;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.Executors;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSparseArrayMap;
@@ -941,7 +940,10 @@
super.onScrollChanged(l, t, oldl, oldt);
// Update the page indicator progress.
- boolean isTransitioning = mIsSwitchingState
+ // Unlike from other states, we show the page indicator when transitioning from HINT_STATE.
+ boolean isSwitchingState = mIsSwitchingState
+ && mLauncher.getStateManager().getCurrentStableState() != HINT_STATE;
+ boolean isTransitioning = isSwitchingState
|| (getLayoutTransition() != null && getLayoutTransition().isRunning());
if (!isTransitioning) {
showPageIndicatorAtCurrentScroll();
@@ -1500,7 +1502,6 @@
.showForIcon((BubbleTextView) child);
if (popupContainer != null) {
dragOptions.preDragCondition = popupContainer.createPreDragCondition();
- mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("dragging started");
}
}
@@ -1700,7 +1701,6 @@
fi.addItem(destInfo);
fi.addItem(sourceInfo);
}
- mLauncher.folderCreatedFromItem(fi.getFolder(), destInfo);
return true;
}
return false;
@@ -1717,7 +1717,7 @@
if (dropOverView instanceof FolderIcon) {
FolderIcon fi = (FolderIcon) dropOverView;
if (fi.acceptDrop(d.dragInfo)) {
- mStatsLogManager.logger().withItemInfo(fi.mInfo).withInstanceId(d.logInstanceId)
+ mStatsLogManager.logger().withItemInfo(d.dragInfo).withInstanceId(d.logInstanceId)
.log(LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED);
fi.onDrop(d, false /* itemReturnedOnFailedDrop */);
@@ -3278,24 +3278,6 @@
return getContext().getString(R.string.workspace_scroll_format, page + 1, nScreens);
}
- @Override
- public void fillInLogContainerData(ItemInfo childInfo, Target child,
- ArrayList<Target> parents) {
- if (childInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
- || childInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION) {
- getHotseat().fillInLogContainerData(childInfo, child, parents);
- return;
- } else if (childInfo.container >= 0) {
- FolderIcon icon = (FolderIcon) getHomescreenIconByItemId(childInfo.container);
- icon.getFolder().fillInLogContainerData(childInfo, child, parents);
- return;
- }
- child.gridX = childInfo.cellX;
- child.gridY = childInfo.cellY;
- child.pageIndex = getCurrentPage();
- parents.add(newContainerTarget(ContainerType.WORKSPACE));
- }
-
/**
* 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 af3722a..1f51566 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -15,7 +15,8 @@
*/
package com.android.launcher3.allapps;
-import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
+import static com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
+import static com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
@@ -42,6 +43,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
+import androidx.core.os.BuildCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
@@ -59,8 +61,6 @@
import com.android.launcher3.keyboard.FocusedItemDecorator;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
@@ -68,8 +68,6 @@
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.SpringRelativeLayout;
-import java.util.ArrayList;
-
/**
* The all apps view container.
*/
@@ -108,7 +106,7 @@
private final MultiValueAlpha mMultiValueAlpha;
- Rect mInsets = new Rect();
+ private Rect mInsets = new Rect();
public AllAppsContainerView(Context context) {
this(context, null);
@@ -204,6 +202,17 @@
mAH[AdapterHolder.WORK].applyPadding();
}
+ private void hideInput() {
+ if (!BuildCompat.isAtLeastR() || !FeatureFlags.ENABLE_DEVICE_SEARCH.get()) return;
+
+ WindowInsets insets = getRootWindowInsets();
+ if (insets == null) return;
+
+ if (insets.isVisible(WindowInsets.Type.ime())) {
+ getWindowInsetsController().hide(WindowInsets.Type.ime());
+ }
+ }
+
/**
* Returns whether the view itself will handle the touch event or not.
*/
@@ -219,9 +228,14 @@
}
if (rv.getScrollbar().getThumbOffsetY() >= 0 &&
mLauncher.getDragLayer().isEventOverView(rv.getScrollbar(), ev)) {
+ hideInput();
return false;
}
- return rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
+ boolean shouldScroll = rv.shouldContainerScroll(ev, mLauncher.getDragLayer());
+ if (shouldScroll) {
+ hideInput();
+ }
+ return shouldScroll;
}
@Override
@@ -336,13 +350,6 @@
}
@Override
- public void fillInLogContainerData(ItemInfo childInfo, Target child,
- ArrayList<Target> parents) {
- parents.add(newContainerTarget(
- getApps().hasFilter() ? ContainerType.SEARCHRESULT : ContainerType.ALLAPPS));
- }
-
- @Override
public void setInsets(Rect insets) {
mInsets.set(insets);
DeviceProfile grid = mLauncher.getDeviceProfile();
@@ -528,6 +535,25 @@
}
/**
+ * Handles selection on focused view and returns success
+ */
+ public boolean selectFocusedView(View v) {
+ ItemInfo itemInfo = getHighlightedItemInfo();
+ if (itemInfo != null) {
+ return mLauncher.startActivitySafely(v, itemInfo.getIntent(), itemInfo);
+ }
+ AdapterItem focusedItem = getActiveRecyclerView().getApps().getFocusedChild();
+ if (focusedItem instanceof AdapterItemWithPayload) {
+ Runnable onSelection = ((AdapterItemWithPayload) focusedItem).getSelectionHandler();
+ if (onSelection != null) {
+ onSelection.run();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Returns the ItemInfo of a view that is in focus, ready to be launched by an IME.
*/
public ItemInfo getHighlightedItemInfo() {
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 2cec797..da161ac 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -20,6 +20,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.net.Uri;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -30,27 +31,38 @@
import android.view.accessibility.AccessibilityEvent;
import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.accessibility.AccessibilityEventCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityRecordCompat;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LifecycleRegistry;
+import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import androidx.slice.Slice;
+import androidx.slice.widget.SliceLiveData;
+import androidx.slice.widget.SliceView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController.PayloadResultHandler;
+import com.android.launcher3.allapps.search.SearchSectionInfo;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.util.PackageManagerHelper;
-import com.android.launcher3.views.HeroSearchResultView;
import java.util.List;
/**
* The grid view adapter of all the apps.
*/
-public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> {
+public class AllAppsGridAdapter extends
+ RecyclerView.Adapter<AllAppsGridAdapter.ViewHolder> implements
+ LifecycleOwner {
public static final String TAG = "AppsGridAdapter";
@@ -71,10 +83,18 @@
public static final int VIEW_TYPE_SEARCH_HERO_APP = 1 << 6;
+ public static final int VIEW_TYPE_SEARCH_ROW_WITH_BUTTON = 1 << 7;
+
+ public static final int VIEW_TYPE_SEARCH_ROW = 1 << 8;
+
+ public static final int VIEW_TYPE_SEARCH_SLICE = 1 << 9;
+
// Common view type masks
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
+ private final LifecycleRegistry mLifecycleRegistry;
+
/**
* ViewHolder for each icon.
*/
@@ -86,6 +106,111 @@
}
/**
+ * Info about a particular adapter item (can be either section or app)
+ */
+ public static class AdapterItem {
+ /** Common properties */
+ // The index of this adapter item in the list
+ public int position;
+ // The type of this item
+ public int viewType;
+
+ /** App-only properties */
+ // The section name of this app. Note that there can be multiple items with different
+ // sectionNames in the same section
+ public String sectionName = null;
+ // The row that this item shows up on
+ public int rowIndex;
+ // The index of this app in the row
+ public int rowAppIndex;
+ // The associated AppInfo for the app
+ public AppInfo appInfo = null;
+ // The index of this app not including sections
+ public int appIndex = -1;
+ // Search section associated to result
+ public SearchSectionInfo searchSectionInfo = null;
+
+ /**
+ * Factory method for AppIcon AdapterItem
+ */
+ public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo,
+ int appIndex) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = VIEW_TYPE_ICON;
+ item.position = pos;
+ item.sectionName = sectionName;
+ item.appInfo = appInfo;
+ item.appIndex = appIndex;
+ return item;
+ }
+
+ /**
+ * Factory method for empty search results view
+ */
+ public static AdapterItem asEmptySearch(int pos) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = VIEW_TYPE_EMPTY_SEARCH;
+ item.position = pos;
+ return item;
+ }
+
+ /**
+ * Factory method for a dividerView in AllAppsSearch
+ */
+ public static AdapterItem asAllAppsDivider(int pos) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = VIEW_TYPE_ALL_APPS_DIVIDER;
+ item.position = pos;
+ return item;
+ }
+
+ /**
+ * Factory method for a market search button
+ */
+ public static AdapterItem asMarketSearch(int pos) {
+ AdapterItem item = new AdapterItem();
+ item.viewType = VIEW_TYPE_SEARCH_MARKET;
+ item.position = pos;
+ return item;
+ }
+
+ boolean isCountedForAccessibility() {
+ return viewType == VIEW_TYPE_ICON
+ || viewType == VIEW_TYPE_SEARCH_HERO_APP
+ || viewType == VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
+ || viewType == VIEW_TYPE_SEARCH_SLICE
+ || viewType == VIEW_TYPE_SEARCH_ROW;
+ }
+ }
+
+ /**
+ * Extension of AdapterItem that contains an extra payload specific to item
+ *
+ * @param <T> Play load Type
+ */
+ public static class AdapterItemWithPayload<T> extends AdapterItem {
+ private T mPayload;
+ private Runnable mSelectionHandler;
+
+ public AdapterItemWithPayload(T payload, int type) {
+ mPayload = payload;
+ viewType = type;
+ }
+
+ public void setSelectionHandler(Runnable runnable) {
+ mSelectionHandler = runnable;
+ }
+
+ public Runnable getSelectionHandler() {
+ return mSelectionHandler;
+ }
+
+ public T getPayload() {
+ return mPayload;
+ }
+ }
+
+ /**
* A subclass of GridLayoutManager that overrides accessibility values during app search.
*/
public class AppsGridLayoutManager extends GridLayoutManager {
@@ -206,6 +331,12 @@
mOnIconClickListener = launcher.getItemOnClickListener();
setAppsPerRow(mLauncher.getDeviceProfile().inv.numAllAppsColumns);
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ mLifecycleRegistry = new LifecycleRegistry(this);
+ mLifecycleRegistry.setCurrentState(Lifecycle.State.STARTED);
+ } else {
+ mLifecycleRegistry = null;
+ }
}
public void setAppsPerRow(int appsPerRow) {
@@ -286,6 +417,15 @@
case VIEW_TYPE_SEARCH_HERO_APP:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.search_result_hero_app, parent, false));
+ case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.search_result_play_item, parent, false));
+ case VIEW_TYPE_SEARCH_ROW:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.search_result_settings_row, parent, false));
+ case VIEW_TYPE_SEARCH_SLICE:
+ return new ViewHolder(mLayoutInflater.inflate(
+ R.layout.search_result_slice, parent, false));
default:
throw new RuntimeException("Unexpected view type");
}
@@ -314,16 +454,23 @@
searchView.setVisibility(View.GONE);
}
break;
- case VIEW_TYPE_SEARCH_CORPUS_TITLE:
- TextView titleView = (TextView) holder.itemView;
- titleView.setText(mApps.getAdapterItems().get(position).searchSectionInfo.getTitle(
- titleView.getContext()));
+ case VIEW_TYPE_SEARCH_SLICE:
+ SliceView sliceView = (SliceView) holder.itemView;
+ Uri uri = ((AdapterItemWithPayload<Uri>) mApps.getAdapterItems().get(position))
+ .getPayload();
+ try {
+ LiveData<Slice> liveData = SliceLiveData.fromUri(mLauncher, uri);
+ liveData.observe(this::getLifecycle, sliceView);
+ } catch (Exception ignored) {
+ }
break;
+ case VIEW_TYPE_SEARCH_CORPUS_TITLE:
+ case VIEW_TYPE_SEARCH_ROW_WITH_BUTTON:
case VIEW_TYPE_SEARCH_HERO_APP:
- HeroSearchResultView heroView = (HeroSearchResultView) holder.itemView;
- heroView.prepareUsingAdapterItem(
- (AlphabeticalAppsList.HeroAppAdapterItem) mApps.getAdapterItems().get(
- position));
+ case VIEW_TYPE_SEARCH_ROW:
+ PayloadResultHandler payloadResultView = (PayloadResultHandler) holder.itemView;
+ payloadResultView.applyAdapterInfo(
+ (AdapterItemWithPayload) mApps.getAdapterItems().get(position));
break;
case VIEW_TYPE_ALL_APPS_DIVIDER:
// nothing to do
@@ -344,8 +491,13 @@
@Override
public int getItemViewType(int position) {
- AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(position);
+ AdapterItem item = mApps.getAdapterItems().get(position);
return item.viewType;
}
+ @NonNull
+ @Override
+ public Lifecycle getLifecycle() {
+ return mLifecycleRegistry;
+ }
}
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 640ef01..13a93ff 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -278,7 +278,7 @@
if (mApps == null) {
return;
}
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems();
// Skip early if there are no items or we haven't been measured
if (items.isEmpty() || mNumAppsPerRow == 0) {
@@ -352,7 +352,7 @@
@Override
public int getCurrentScrollY() {
// Return early if there are no items or we haven't been measured
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems();
if (items.isEmpty() || mNumAppsPerRow == 0 || getChildCount() == 0) {
return -1;
}
@@ -368,14 +368,14 @@
}
public int getCurrentScrollY(int position, int offset) {
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
- AlphabeticalAppsList.AdapterItem posItem = position < items.size() ?
- items.get(position) : null;
+ List<AllAppsGridAdapter.AdapterItem> items = mApps.getAdapterItems();
+ AllAppsGridAdapter.AdapterItem posItem = position < items.size()
+ ? items.get(position) : null;
int y = mCachedScrollPositions.get(position, -1);
if (y < 0) {
y = 0;
for (int i = 0; i < position; i++) {
- AlphabeticalAppsList.AdapterItem item = items.get(i);
+ AllAppsGridAdapter.AdapterItem item = items.get(i);
if (AllAppsGridAdapter.isIconViewType(item.viewType)) {
// Break once we reach the desired row
if (posItem != null && posItem.viewType == item.viewType &&
diff --git a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
index a168c06..0214c35 100644
--- a/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
+++ b/src/com/android/launcher3/allapps/AllAppsSectionDecorator.java
@@ -22,6 +22,7 @@
import android.view.View;
import androidx.annotation.Nullable;
+import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.R;
@@ -47,13 +48,13 @@
// Since views in the same section will follow each other, we can skip to a last view in
// a section to get the bounds of the section without having to iterate on every item.
int itemCount = parent.getChildCount();
- List<AlphabeticalAppsList.AdapterItem> adapterItems = mAppsView.getApps().getAdapterItems();
+ List<AllAppsGridAdapter.AdapterItem> adapterItems = mAppsView.getApps().getAdapterItems();
SectionDecorationHandler lastDecorationHandler = null;
int i = 0;
while (i < itemCount) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
- AlphabeticalAppsList.AdapterItem adapterItem = adapterItems.get(position);
+ AllAppsGridAdapter.AdapterItem adapterItem = adapterItems.get(position);
if (adapterItem.searchSectionInfo != null) {
SearchSectionInfo sectionInfo = adapterItem.searchSectionInfo;
int endIndex = Math.min(i + sectionInfo.getPosEnd() - position, itemCount - 1);
@@ -100,19 +101,23 @@
* Handles grouping and drawing of items in the same all apps sections.
*/
public static class SectionDecorationHandler {
+ private static final int FILL_ALPHA = (int) (.3f * 255);
+ private static final int FOCUS_ALPHA = (int) (.8f * 255);
+
protected RectF mBounds = new RectF();
private final boolean mIsFullWidth;
private final float mRadius;
- private final int mFocusColor;
- private final int mFillcolor;
+ protected int mFocusColor;
+ protected int mFillcolor;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public SectionDecorationHandler(Context context, boolean isFullWidth) {
mIsFullWidth = isFullWidth;
- mFillcolor = context.getColor(R.color.all_apps_section_fill);
- mFocusColor = context.getColor(R.color.all_apps_section_focused_item);
+ int endScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
+ mFillcolor = ColorUtils.setAlphaComponent(endScrim, FILL_ALPHA);
+ mFocusColor = ColorUtils.setAlphaComponent(endScrim, FOCUS_ALPHA);
mRadius = Themes.getDialogCornerRadius(context);
}
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 7379dbed..8c059d5 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -19,10 +19,10 @@
import android.content.Context;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
import com.android.launcher3.allapps.search.SearchSectionInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LabelComparator;
@@ -62,101 +62,6 @@
}
}
- /**
- * Info about a particular adapter item (can be either section or app)
- */
- public static class AdapterItem {
- /** Common properties */
- // The index of this adapter item in the list
- public int position;
- // The type of this item
- public int viewType;
-
- /** App-only properties */
- // The section name of this app. Note that there can be multiple items with different
- // sectionNames in the same section
- public String sectionName = null;
- // The row that this item shows up on
- public int rowIndex;
- // The index of this app in the row
- public int rowAppIndex;
- // The associated AppInfo for the app
- public AppInfo appInfo = null;
- // The index of this app not including sections
- public int appIndex = -1;
- // Search section associated to result
- public SearchSectionInfo searchSectionInfo = null;
-
- public static AdapterItem asApp(int pos, String sectionName, AppInfo appInfo,
- int appIndex) {
- AdapterItem item = new AdapterItem();
- item.viewType = AllAppsGridAdapter.VIEW_TYPE_ICON;
- item.position = pos;
- item.sectionName = sectionName;
- item.appInfo = appInfo;
- item.appIndex = appIndex;
- return item;
- }
-
- public static AdapterItem asEmptySearch(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = AllAppsGridAdapter.VIEW_TYPE_EMPTY_SEARCH;
- item.position = pos;
- return item;
- }
-
- public static AdapterItem asAllAppsDivider(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = AllAppsGridAdapter.VIEW_TYPE_ALL_APPS_DIVIDER;
- item.position = pos;
- return item;
- }
-
- public static AdapterItem asMarketSearch(int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = AllAppsGridAdapter.VIEW_TYPE_SEARCH_MARKET;
- item.position = pos;
- return item;
- }
-
- /**
- * Factory method for search section title AdapterItem
- */
- public static AdapterItem asSearchTitle(SearchSectionInfo sectionInfo, int pos) {
- AdapterItem item = new AdapterItem();
- item.viewType = AllAppsGridAdapter.VIEW_TYPE_SEARCH_CORPUS_TITLE;
- item.position = pos;
- item.searchSectionInfo = sectionInfo;
- return item;
- }
-
- boolean isCountedForAccessibility() {
- return viewType == AllAppsGridAdapter.VIEW_TYPE_ICON
- || viewType == AllAppsGridAdapter.VIEW_TYPE_SEARCH_HERO_APP;
- }
- }
-
- /**
- * Extension of AdapterItem that contains shortcut workspace items
- */
- public static class HeroAppAdapterItem extends AdapterItem {
- private ArrayList<WorkspaceItemInfo> mShortcutInfos;
-
- public HeroAppAdapterItem(AppInfo info, ArrayList<WorkspaceItemInfo> shortcutInfos) {
- viewType = AllAppsGridAdapter.VIEW_TYPE_SEARCH_HERO_APP;
- mShortcutInfos = shortcutInfos;
- appInfo = info;
- }
-
- /**
- * Returns list of shortcuts for appInfo
- */
- public ArrayList<WorkspaceItemInfo> getShortcutInfos() {
- return mShortcutInfos;
- }
-
- }
-
private final BaseDraggingActivity mLauncher;
@@ -396,7 +301,9 @@
adapterItem.position = i;
mAdapterItems.add(adapterItem);
if (adapterItem.searchSectionInfo != lastSection) {
- adapterItem.searchSectionInfo.setPosStart(i);
+ if (adapterItem.searchSectionInfo != null) {
+ adapterItem.searchSectionInfo.setPosStart(i);
+ }
if (lastSection != null) {
lastSection.setPosEnd(i - 1);
}
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index b4ff5ea..14595ca 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -116,11 +116,6 @@
}
@Override
- public void logActionCommand(int command) {
- // Since this is on-boarding popup, it is not a user controlled action.
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_DISCOVERY_BOUNCE) != 0;
}
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 06faaac..2e5ed3e 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.allapps.search;
+import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
@@ -29,12 +30,15 @@
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
-import com.android.launcher3.allapps.AlphabeticalAppsList;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.systemui.plugins.AllAppsSearchPlugin;
import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
/**
* An interface to a search box that AllApps can command.
@@ -59,7 +63,7 @@
*/
public final void initialize(
SearchAlgorithm searchAlgorithm, ExtendedEditText input,
- BaseDraggingActivity launcher, Callbacks cb) {
+ BaseDraggingActivity launcher, Callbacks cb, Consumer<List<Bundle>> secondaryCb) {
mCb = cb;
mLauncher = launcher;
@@ -72,8 +76,11 @@
}
@Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // Do nothing
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
+ if (mSearchAlgorithm instanceof PluginWrapper) {
+ ((PluginWrapper) mSearchAlgorithm).runOnPluginIfConnected(
+ AllAppsSearchPlugin::startedTyping);
+ }
}
@Override
@@ -106,10 +113,8 @@
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
- ItemInfo info = Launcher.getLauncher(mLauncher).getAppsView()
- .getHighlightedItemInfo();
- if (info != null) {
- return mLauncher.startActivitySafely(v, info.getIntent(), info);
+ if (Launcher.getLauncher(mLauncher).getAppsView().selectFocusedView(v)) {
+ return true;
}
}
}
@@ -171,16 +176,26 @@
}
/**
+ * A wrapper setup for running essential calls to plugin from search controller
+ */
+ public interface PluginWrapper {
+ /**
+ * executes call if plugin is connected
+ */
+ void runOnPluginIfConnected(Consumer<AllAppsSearchPlugin> plugin);
+ }
+
+ /**
* Callback for getting search results.
*/
public interface Callbacks {
/**
- * Called when the search is complete.
+ * Called when the search from primary source is complete.
*
* @param items sorted list of search result adapter items.
*/
- void onSearchResult(String query, ArrayList<AlphabeticalAppsList.AdapterItem> items);
+ void onSearchResult(String query, ArrayList<AllAppsGridAdapter.AdapterItem> items);
/**
* Called when the search results should be cleared.
@@ -188,4 +203,15 @@
void clearSearchResult();
}
+ /**
+ * An interface for supporting dynamic search results
+ *
+ * @param <T> Type of payload
+ */
+ public interface PayloadResultHandler<T> {
+ /**
+ * Updates View using Adapter's payload
+ */
+ void applyAdapterInfo(AdapterItemWithPayload<T> adapterItemWithPayload);
+ }
}
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 16a1efd..7518521 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.graphics.Rect;
+import android.os.Bundle;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.method.TextKeyListener;
@@ -41,19 +42,22 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsContainerView;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.allapps.AlphabeticalAppsList;
import com.android.launcher3.allapps.SearchUiManager;
import com.android.launcher3.anim.PropertySetter;
import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
/**
* Layout to contain the All-apps search UI.
*/
public class AppsSearchContainerLayout extends ExtendedEditText
implements SearchUiManager, AllAppsSearchBarController.Callbacks,
- AllAppsStore.OnUpdateListener, Insettable {
+ AllAppsStore.OnUpdateListener, Insettable, Consumer<List<Bundle>> {
private final BaseDraggingActivity mLauncher;
private final AllAppsSearchBarController mSearchBarController;
@@ -135,8 +139,8 @@
mApps = appsView.getApps();
mAppsView = appsView;
mSearchBarController.initialize(
- new DefaultAppSearchAlgorithm(LauncherAppState.getInstance(mLauncher)), this,
- mLauncher, this);
+ new DefaultAppSearchAlgorithm(mLauncher, LauncherAppState.getInstance(mLauncher)),
+ this, mLauncher, this, this);
}
@Override
@@ -169,7 +173,7 @@
}
@Override
- public void onSearchResult(String query, ArrayList<AlphabeticalAppsList.AdapterItem> items) {
+ public void onSearchResult(String query, ArrayList<AllAppsGridAdapter.AdapterItem> items) {
if (items != null) {
mApps.setSearchResults(items);
notifyResultChanged();
@@ -220,4 +224,9 @@
public EditText getEditText() {
return this;
}
+
+ @Override
+ public void accept(List<Bundle> bundles) {
+ // TODO: Render the result on mAppsView object
+ }
}
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
index e67e897..dc9c155 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchPipeline.java
@@ -15,25 +15,15 @@
*/
package com.android.launcher3.allapps.search;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
-
import android.content.Context;
-import android.content.pm.ShortcutInfo;
-
-import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItem;
import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHandler;
-import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
-import com.android.launcher3.allapps.AlphabeticalAppsList.HeroAppAdapterItem;
-import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BaseModelUpdateTask;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.popup.PopupPopulator;
-import com.android.launcher3.shortcuts.ShortcutRequest;
import java.util.ArrayList;
import java.util.List;
@@ -45,64 +35,29 @@
public class AppsSearchPipeline implements SearchPipeline {
private static final int MAX_RESULTS_COUNT = 5;
- private static final int MAX_HERO_SECTION_COUNT = 2;
- private static final int MAX_SHORTCUTS_COUNT = 2;
private final SearchSectionInfo mSearchSectionInfo;
private final LauncherAppState mLauncherAppState;
- private final boolean mHeroSectionSupported;
- public AppsSearchPipeline(LauncherAppState launcherAppState) {
- this(launcherAppState, true);
- }
-
- public AppsSearchPipeline(LauncherAppState launcherAppState, boolean supportsHeroView) {
+ public AppsSearchPipeline(Context context, LauncherAppState launcherAppState) {
mLauncherAppState = launcherAppState;
mSearchSectionInfo = new SearchSectionInfo();
mSearchSectionInfo.setDecorationHandler(
- new SectionDecorationHandler(launcherAppState.getContext(), true));
- mHeroSectionSupported = supportsHeroView;
+ new SectionDecorationHandler(context, true));
}
@Override
- @WorkerThread
public void performSearch(String query, Consumer<ArrayList<AdapterItem>> callback) {
mLauncherAppState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
List<AppInfo> matchingResults = getTitleMatchResult(apps.data, query);
- if (mHeroSectionSupported && matchingResults.size() <= MAX_HERO_SECTION_COUNT) {
- callback.accept(getHeroAdapterItems(app.getContext(), matchingResults));
- } else {
- callback.accept(getAdapterItems(matchingResults));
- }
+ callback.accept(getAdapterItems(matchingResults));
}
});
}
/**
- * Returns MAX_SHORTCUTS_COUNT shortcuts from local cache
- * TODO: Shortcuts should be ranked based on relevancy
- */
- private ArrayList<WorkspaceItemInfo> getShortcutInfos(Context context, AppInfo appInfo) {
- List<ShortcutInfo> shortcuts = new ShortcutRequest(context, appInfo.user)
- .withContainer(appInfo.getTargetComponent())
- .query(ShortcutRequest.PUBLISHED);
- shortcuts = PopupPopulator.sortAndFilterShortcuts(shortcuts, null);
- IconCache cache = LauncherAppState.getInstance(context).getIconCache();
- ArrayList<WorkspaceItemInfo> shortcutItems = new ArrayList<>();
- for (int i = 0; i < shortcuts.size() && i < MAX_SHORTCUTS_COUNT; i++) {
- final ShortcutInfo shortcut = shortcuts.get(i);
- final WorkspaceItemInfo si = new WorkspaceItemInfo(shortcut, context);
- cache.getUnbadgedShortcutIcon(si, shortcut);
- si.rank = i;
- si.container = CONTAINER_SHORTCUTS;
- shortcutItems.add(si);
- }
- return shortcutItems;
- }
-
- /**
* Filters {@link AppInfo}s matching specified query
*/
public static ArrayList<AppInfo> getTitleMatchResult(List<AppInfo> apps, String query) {
@@ -120,19 +75,6 @@
return result;
}
- private ArrayList<AdapterItem> getHeroAdapterItems(Context context, List<AppInfo> apps) {
- ArrayList<AdapterItem> adapterItems = new ArrayList<>();
- for (int i = 0; i < apps.size(); i++) {
- //hero app
- AppInfo appInfo = apps.get(i);
- ArrayList<WorkspaceItemInfo> shortcuts = getShortcutInfos(context, appInfo);
- AdapterItem adapterItem = new HeroAppAdapterItem(appInfo, shortcuts);
- adapterItem.searchSectionInfo = mSearchSectionInfo;
- adapterItems.add(adapterItem);
- }
- return adapterItems;
- }
-
private ArrayList<AdapterItem> getAdapterItems(List<AppInfo> matchingApps) {
ArrayList<AdapterItem> items = new ArrayList<>();
for (int i = 0; i < matchingApps.size() && i < MAX_RESULTS_COUNT; i++) {
diff --git a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
index 470191c..5ed7de5 100644
--- a/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
+++ b/src/com/android/launcher3/allapps/search/DefaultAppSearchAlgorithm.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.allapps.search;
+import android.content.Context;
import android.os.Handler;
import com.android.launcher3.LauncherAppState;
@@ -30,9 +31,9 @@
protected final Handler mResultHandler;
private final AppsSearchPipeline mAppsSearchPipeline;
- public DefaultAppSearchAlgorithm(LauncherAppState launcherAppState) {
+ public DefaultAppSearchAlgorithm(Context context, LauncherAppState launcherAppState) {
mResultHandler = new Handler();
- mAppsSearchPipeline = new AppsSearchPipeline(launcherAppState, false);
+ mAppsSearchPipeline = new AppsSearchPipeline(context, launcherAppState);
}
@Override
diff --git a/src/com/android/launcher3/allapps/search/SearchPipeline.java b/src/com/android/launcher3/allapps/search/SearchPipeline.java
index 3216740..545f0e3 100644
--- a/src/com/android/launcher3/allapps/search/SearchPipeline.java
+++ b/src/com/android/launcher3/allapps/search/SearchPipeline.java
@@ -15,7 +15,7 @@
*/
package com.android.launcher3.allapps.search;
-import com.android.launcher3.allapps.AlphabeticalAppsList;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
import java.util.ArrayList;
import java.util.function.Consumer;
@@ -28,5 +28,5 @@
/**
* Perform query
*/
- void performSearch(String query, Consumer<ArrayList<AlphabeticalAppsList.AdapterItem>> cb);
+ void performSearch(String query, Consumer<ArrayList<AllAppsGridAdapter.AdapterItem>> cb);
}
diff --git a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
index dee0ffd..e026e84 100644
--- a/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
+++ b/src/com/android/launcher3/allapps/search/SearchSectionInfo.java
@@ -15,8 +15,6 @@
*/
package com.android.launcher3.allapps.search;
-import android.content.Context;
-
import com.android.launcher3.allapps.AllAppsSectionDecorator.SectionDecorationHandler;
/**
@@ -24,7 +22,7 @@
*/
public class SearchSectionInfo {
- private final int mTitleResId;
+ private String mTitle;
private SectionDecorationHandler mDecorationHandler;
public int getPosStart() {
@@ -47,11 +45,11 @@
private int mPosEnd;
public SearchSectionInfo() {
- this(-1);
+ this(null);
}
- public SearchSectionInfo(int titleResId) {
- mTitleResId = titleResId;
+ public SearchSectionInfo(String title) {
+ mTitle = title;
}
public void setDecorationHandler(SectionDecorationHandler sectionDecorationHandler) {
@@ -66,10 +64,7 @@
/**
* Returns the section's title
*/
- public String getTitle(Context context) {
- if (mTitleResId == -1) {
- return "";
- }
- return context.getString(mTitleResId);
+ public String getTitle() {
+ return mTitle == null ? "" : mTitle;
}
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index e624dd3..d8fca1d 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -142,10 +142,6 @@
public static final BooleanFlag ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER = getDebugFlag(
"ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", true, "Show launcher preview in grid picker");
- public static final BooleanFlag ENABLE_OVERVIEW_ACTIONS = getDebugFlag(
- "ENABLE_OVERVIEW_ACTIONS", true, "Show app actions instead of the shelf in Overview."
- + " As part of this decoupling, also distinguish swipe up from nav bar vs above it.");
-
// Keep as DeviceFlag for remote disable in emergency.
public static final BooleanFlag ENABLE_OVERVIEW_SELECTIONS = new DeviceFlag(
"ENABLE_OVERVIEW_SELECTIONS", true, "Show Select Mode button in Overview Actions");
@@ -178,9 +174,6 @@
"SEPARATE_RECENTS_ACTIVITY", false,
"Uses a separate recents activity instead of using the integrated recents+Launcher UI");
- public static final BooleanFlag USER_EVENT_DISPATCHER = new DeviceFlag(
- "USER_EVENT_DISPATCHER", true, "User event dispatcher collects logs.");
-
public static final BooleanFlag ENABLE_MINIMAL_DEVICE = new DeviceFlag(
"ENABLE_MINIMAL_DEVICE", false,
"Allow user to toggle minimal device mode in launcher.");
diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java
index 0df6713..2d625c5 100644
--- a/src/com/android/launcher3/dragndrop/AddItemActivity.java
+++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java
@@ -43,13 +43,13 @@
import android.view.View.OnTouchListener;
import com.android.launcher3.BaseActivity;
-import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetHost;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
+import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.pm.PinRequestHelper;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@@ -249,7 +249,7 @@
*/
public void onPlaceAutomaticallyClick(View v) {
if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
- InstallShortcutReceiver.queueShortcut(mRequest.getShortcutInfo(), this);
+ ItemInstallQueue.INSTANCE.get(this).queueItem(mRequest.getShortcutInfo());
logCommand(Action.Command.CONFIRM);
mRequest.accept();
finish();
@@ -270,7 +270,8 @@
}
private void acceptWidget(int widgetId) {
- InstallShortcutReceiver.queueWidget(mRequest.getAppWidgetProviderInfo(this), widgetId, this);
+ ItemInstallQueue.INSTANCE.get(this)
+ .queueItem(mRequest.getAppWidgetProviderInfo(this), widgetId);
mWidgetOptions.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
mRequest.accept(mWidgetOptions);
logCommand(Action.Command.CONFIRM);
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index bf3aa7f..6104d80 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -16,7 +16,6 @@
package com.android.launcher3.dragndrop;
-import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import android.annotation.TargetApi;
import android.appwidget.AppWidgetManager;
@@ -33,15 +32,11 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.PendingAddItemInfo;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.PendingItemDragHelper;
import com.android.launcher3.widget.WidgetAddFlowHandler;
-import java.util.ArrayList;
-
/**
* {@link DragSource} for handling drop from a different window. This object is initialized
* in the source window and is passed on to the Launcher activity as an Intent extra.
@@ -107,12 +102,6 @@
}
@Override
- public void fillInLogContainerData(ItemInfo childInfo, LauncherLogProto.Target child,
- ArrayList<LauncherLogProto.Target> parents) {
- parents.add(newContainerTarget(LauncherLogProto.ContainerType.PINITEM));
- }
-
- @Override
protected void postCleanup() {
super.postCleanup();
mCancelSignal.cancel();
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index b91d1c3..f1606ea 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -19,11 +19,11 @@
import static android.text.TextUtils.isEmpty;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTIMIZATION_FOR_FOLDER_ANIMATIONS;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_CONVERTED_TO_ICON;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED;
@@ -1183,7 +1183,8 @@
newIcon.requestFocus();
}
if (finalItem != null) {
- mLauncher.folderConvertedToItem(mFolderIcon.getFolder(), finalItem);
+ mStatsLogManager.logger().withItemInfo(finalItem)
+ .log(LAUNCHER_FOLDER_CONVERTED_TO_ICON);
}
}
}
@@ -1481,27 +1482,6 @@
outRect.right += mScrollAreaOffset;
}
- @Override
- public void fillInLogContainerData(ItemInfo childInfo, LauncherLogProto.Target child,
- ArrayList<LauncherLogProto.Target> targets) {
- child.gridX = childInfo.cellX;
- child.gridY = childInfo.cellY;
- child.pageIndex = mContent.getCurrentPage();
-
- LauncherLogProto.Target target = newContainerTarget(LauncherLogProto.ContainerType.FOLDER);
- target.pageIndex = mInfo.screenId;
- target.gridX = mInfo.cellX;
- target.gridY = mInfo.cellY;
- targets.add(target);
-
- // continue to parent
- if (mInfo.container == CONTAINER_HOTSEAT) {
- mLauncher.getHotseat().fillInLogContainerData(mInfo, target, targets);
- } else {
- mLauncher.getWorkspace().fillInLogContainerData(mInfo, target, targets);
- }
- }
-
private class OnScrollHintListener implements OnAlarmListener {
private final DragObject mDragObject;
@@ -1589,17 +1569,6 @@
return getOpenView(launcher, TYPE_FOLDER);
}
- @Override
- public void logActionCommand(int command) {
- mLauncher.getUserEventDispatcher().logActionCommand(
- command, getFolderIcon(), getLogContainerType());
- }
-
- @Override
- public int getLogContainerType() {
- return LauncherLogProto.ContainerType.FOLDER;
- }
-
/**
* Navigation bar back key or hardware input back key has been issued.
*/
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index cca9836..0f1432a 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -19,6 +19,7 @@
import static android.view.View.MeasureSpec.makeMeasureSpec;
import static android.view.View.VISIBLE;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
@@ -72,12 +73,12 @@
import com.android.launcher3.model.AllAppsList;
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.model.BgDataModel.FixedContainerItems;
import com.android.launcher3.model.LoaderResults;
import com.android.launcher3.model.LoaderTask;
import com.android.launcher3.model.ModelDelegate;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.WidgetsModel;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -95,6 +96,7 @@
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -467,12 +469,14 @@
}
IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems,
mIdp.numHotseatIcons);
- int count = Math.min(ranks.size(), workspaceResult.mCachedPredictedItems.size());
+ List<ItemInfo> predictions = workspaceResult.mHotseatPredictions == null
+ ? Collections.emptyList() : workspaceResult.mHotseatPredictions.items;
+ int count = Math.min(ranks.size(), predictions.size());
for (int i = 0; i < count; i++) {
- AppInfo appInfo = workspaceResult.mCachedPredictedItems.get(i);
int rank = ranks.get(i);
- WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(appInfo);
- itemInfo.container = Favorites.CONTAINER_HOTSEAT_PREDICTION;
+ WorkspaceItemInfo itemInfo =
+ new WorkspaceItemInfo((WorkspaceItemInfo) predictions.get(i));
+ itemInfo.container = CONTAINER_HOTSEAT_PREDICTION;
itemInfo.rank = rank;
itemInfo.cellX = mHotseat.getCellXFromOrder(rank);
itemInfo.cellY = mHotseat.getCellYFromOrder(rank);
@@ -569,8 +573,7 @@
return null;
}
- return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
- mBgDataModel.cachedPredictedItems, mBgDataModel.widgetsModel, null);
+ return new WorkspaceResult(mBgDataModel, mBgDataModel.widgetsModel, null);
}
}
@@ -594,11 +597,10 @@
}
@Override
- public WorkspaceResult call() throws Exception {
+ public WorkspaceResult call() {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI);
- return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
- mBgDataModel.cachedPredictedItems, null, mWidgetProvidersMap);
+ return new WorkspaceResult(mBgDataModel, null, mWidgetProvidersMap);
}
}
@@ -618,17 +620,16 @@
private static class WorkspaceResult {
private final ArrayList<ItemInfo> mWorkspaceItems;
private final ArrayList<LauncherAppWidgetInfo> mAppWidgets;
- private final ArrayList<AppInfo> mCachedPredictedItems;
+ private final FixedContainerItems mHotseatPredictions;
private final WidgetsModel mWidgetsModel;
private final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap;
- private WorkspaceResult(ArrayList<ItemInfo> workspaceItems,
- ArrayList<LauncherAppWidgetInfo> appWidgets,
- ArrayList<AppInfo> cachedPredictedItems, WidgetsModel widgetsModel,
+ private WorkspaceResult(BgDataModel dataModel,
+ WidgetsModel widgetsModel,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) {
- mWorkspaceItems = workspaceItems;
- mAppWidgets = appWidgets;
- mCachedPredictedItems = cachedPredictedItems;
+ mWorkspaceItems = dataModel.workspaceItems;
+ mAppWidgets = dataModel.appWidgets;
+ mHotseatPredictions = dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION);
mWidgetsModel = widgetsModel;
mWidgetProvidersMap = widgetProviderInfoMap;
}
diff --git a/src/com/android/launcher3/graphics/OverviewScrim.java b/src/com/android/launcher3/graphics/OverviewScrim.java
index 94acbfd..c0c3e5e 100644
--- a/src/com/android/launcher3/graphics/OverviewScrim.java
+++ b/src/com/android/launcher3/graphics/OverviewScrim.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
import android.graphics.Rect;
+import android.util.FloatProperty;
import android.view.View;
import android.view.ViewGroup;
@@ -33,10 +34,25 @@
*/
public class OverviewScrim extends Scrim {
+ public static final FloatProperty<OverviewScrim> SCRIM_MULTIPLIER =
+ new FloatProperty<OverviewScrim>("scrimMultiplier") {
+ @Override
+ public Float get(OverviewScrim scrim) {
+ return scrim.mScrimMultiplier;
+ }
+
+ @Override
+ public void setValue(OverviewScrim scrim, float v) {
+ scrim.setScrimMultiplier(v);
+ }
+ };
+
private @NonNull View mStableScrimmedView;
// Might be higher up if mStableScrimmedView is invisible.
private @Nullable View mCurrentScrimmedView;
+ private float mScrimMultiplier = 1f;
+
public OverviewScrim(View view) {
super(view);
mStableScrimmedView = mCurrentScrimmedView = mLauncher.getOverviewPanel();
@@ -68,4 +84,16 @@
public @Nullable View getScrimmedView() {
return mCurrentScrimmedView;
}
+
+ private void setScrimMultiplier(float scrimMultiplier) {
+ if (Float.compare(mScrimMultiplier, scrimMultiplier) != 0) {
+ mScrimMultiplier = scrimMultiplier;
+ invalidate();
+ }
+ }
+
+ @Override
+ protected int getScrimAlpha() {
+ return Math.round(super.getScrimAlpha() * mScrimMultiplier);
+ }
}
diff --git a/src/com/android/launcher3/graphics/Scrim.java b/src/com/android/launcher3/graphics/Scrim.java
index f90962d..a151cba 100644
--- a/src/com/android/launcher3/graphics/Scrim.java
+++ b/src/com/android/launcher3/graphics/Scrim.java
@@ -61,7 +61,11 @@
}
public void draw(Canvas canvas) {
- canvas.drawColor(setColorAlphaBound(mScrimColor, mScrimAlpha));
+ canvas.drawColor(setColorAlphaBound(mScrimColor, getScrimAlpha()));
+ }
+
+ protected int getScrimAlpha() {
+ return mScrimAlpha;
}
private void setScrimProgress(float progress) {
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 2282339..ec1c3ef 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -316,7 +316,13 @@
LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON(625),
@UiEvent(doc = "User tapped on image content in Overview Select mode.")
- LAUNCHER_SELECT_MODE_IMAGE(627);
+ LAUNCHER_SELECT_MODE_IMAGE(627),
+
+ @UiEvent(doc = "A folder was replaced by a single item")
+ LAUNCHER_FOLDER_CONVERTED_TO_ICON(628),
+
+ @UiEvent(doc = "A hotseat prediction item was pinned")
+ LAUNCHER_HOTSEAT_PREDICTION_PINNED(629);
// ADD MORE
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index 31a81b8..a40cc26 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -19,26 +19,21 @@
import static com.android.launcher3.logging.LoggerUtils.newAction;
import static com.android.launcher3.logging.LoggerUtils.newCommandAction;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
-import static com.android.launcher3.logging.LoggerUtils.newControlTarget;
import static com.android.launcher3.logging.LoggerUtils.newDropTarget;
import static com.android.launcher3.logging.LoggerUtils.newItemTarget;
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
import static com.android.launcher3.logging.LoggerUtils.newTarget;
import static com.android.launcher3.logging.LoggerUtils.newTouchAction;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
import static com.android.launcher3.userevent.nano.LauncherLogProto.TipType;
import static java.util.Optional.ofNullable;
-import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.os.Process;
import android.os.SystemClock;
-import android.os.UserHandle;
import android.util.Log;
import android.view.View;
@@ -54,7 +49,6 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.LauncherEvent;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.LogConfig;
import com.android.launcher3.util.ResourceBasedOverride;
@@ -101,7 +95,7 @@
*
* @return whether container data was added.
*/
- public boolean fillLogContainer(@Nullable View v, Target child,
+ private boolean fillLogContainer(@Nullable View v, Target child,
@Nullable ArrayList<Target> targets) {
LogContainerProvider firstParent = StatsLogUtils.getLaunchProviderRecursive(v);
if (v == null || !(v.getTag() instanceof ItemInfo) || firstParent == null) {
@@ -125,55 +119,6 @@
private boolean mAppOrTaskLaunch;
private boolean mPreviousHomeGesture;
- // APP_ICON SHORTCUT WIDGET
- // --------------------------------------------------------------
- // packageNameHash required optional required
- // componentNameHash required required
- // intentHash required
- // --------------------------------------------------------------
-
- @Deprecated
- public void logAppLaunch(View v, Intent intent, @Nullable UserHandle userHandle) {
- Target itemTarget = newItemTarget(v, mInstantAppResolver);
- Action action = newTouchAction(Action.Touch.TAP);
- ArrayList<Target> targets = makeTargetsList(itemTarget);
- if (fillLogContainer(v, itemTarget, targets)) {
- onFillInLogContainerData((ItemInfo) v.getTag(), itemTarget, targets);
- fillIntentInfo(itemTarget, intent, userHandle);
- }
- LauncherEvent event = newLauncherEvent(action, targets);
- dispatchUserEvent(event, intent);
- mAppOrTaskLaunch = true;
- }
-
- /**
- * Placeholder method.
- */
- public void logActionTip(int actionType, int viewType) {
- }
-
- @Deprecated
- public void logTaskLaunchOrDismiss(int action, int direction, int taskIndex,
- ComponentKey componentKey) {
- LauncherEvent event = newLauncherEvent(newTouchAction(action), // TAP or SWIPE or FLING
- newTarget(Target.Type.ITEM));
- if (action == Action.Touch.SWIPE || action == Action.Touch.FLING) {
- // Direction DOWN means the task was launched, UP means it was dismissed.
- event.action.dir = direction;
- }
- event.srcTarget[0].itemType = ItemType.TASK;
- event.srcTarget[0].pageIndex = taskIndex;
- fillComponentInfo(event.srcTarget[0], componentKey.componentName);
- dispatchUserEvent(event, null);
- mAppOrTaskLaunch = true;
- }
-
- protected void fillIntentInfo(Target target, Intent intent, @Nullable UserHandle userHandle) {
- target.intentHash = intent.hashCode();
- target.isWorkApp = userHandle != null && !userHandle.equals(Process.myUserHandle());
- fillComponentInfo(target, intent.getComponent());
- }
-
private void fillComponentInfo(Target target, ComponentName cn) {
if (cn != null) {
target.packageNameHash = (mUuidStr + cn.getPackageName()).hashCode();
@@ -181,22 +126,6 @@
}
}
- public void logNotificationLaunch(View v, PendingIntent intent) {
- LauncherEvent event = newLauncherEvent(newTouchAction(Action.Touch.TAP),
- newItemTarget(v, mInstantAppResolver), newTarget(Target.Type.CONTAINER));
- Target itemTarget = newItemTarget(v, mInstantAppResolver);
- ArrayList<Target> targets = makeTargetsList(itemTarget);
-
- if (fillLogContainer(v, itemTarget, targets)) {
- itemTarget.packageNameHash = (mUuidStr + intent.getCreatorPackage()).hashCode();
- }
- dispatchUserEvent(event, null);
- }
-
- public void logActionCommand(int command, Target srcTarget) {
- logActionCommand(command, srcTarget, null);
- }
-
public void logActionCommand(int command, int srcContainerType, int dstContainerType) {
logActionCommand(command, newContainerTarget(srcContainerType),
dstContainerType >= 0 ? newContainerTarget(dstContainerType) : null);
@@ -227,25 +156,6 @@
dispatchUserEvent(event, null);
}
- /**
- * TODO: Make this function work when a container view is passed as the 2nd param.
- */
- public void logActionCommand(int command, View itemView, int srcContainerType) {
- LauncherEvent event = newLauncherEvent(newCommandAction(command),
- newItemTarget(itemView, mInstantAppResolver), newTarget(Target.Type.CONTAINER));
-
- Target itemTarget = newItemTarget(itemView, mInstantAppResolver);
- ArrayList<Target> targets = makeTargetsList(itemTarget);
-
- if (fillLogContainer(itemView, itemTarget, targets)) {
- // TODO: Remove the following two lines once fillInLogContainerData can take in a
- // container view.
- itemTarget.type = Target.Type.CONTAINER;
- itemTarget.containerType = srcContainerType;
- }
- dispatchUserEvent(event, null);
- }
-
public void logActionOnControl(int action, int controlType) {
logActionOnControl(action, controlType, null);
}
@@ -332,7 +242,6 @@
event.srcTarget[0].spanX = downX;
event.srcTarget[0].spanY = downY;
dispatchUserEvent(event, null);
- resetElapsedContainerMillis("state changed");
}
public void logActionOnItem(int action, int dir, int itemType) {
@@ -386,7 +295,6 @@
ArrayList<Target> targets = makeTargetsList(child);
fillLogContainer(icon, child, targets);
dispatchUserEvent(newLauncherEvent(newTouchAction(Action.Touch.TAP), targets), null);
- resetElapsedContainerMillis("deep shortcut open");
}
public void logDragNDrop(DropTarget.DragObject dragObj, View dropTargetAsView) {
@@ -397,7 +305,7 @@
Target destChild = newItemTarget(dragObj.originalDragInfo, mInstantAppResolver);
ArrayList<Target> destTargets = makeTargetsList(destChild);
- dragObj.dragSource.fillInLogContainerData(dragObj.originalDragInfo, srcChild, srcTargets);
+ //dragObj.dragSource.fillInLogContainerData(dragObj.originalDragInfo, srcChild, srcTargets);
if (dropTargetAsView instanceof LogContainerProvider) {
((LogContainerProvider) dropTargetAsView).fillInLogContainerData(dragObj.dragInfo,
destChild, destTargets);
@@ -414,35 +322,6 @@
dispatchUserEvent(event, null);
}
- public void logActionBack(boolean completed, int downX, int downY, boolean isButton,
- boolean gestureSwipeLeft, int containerType) {
- int actionTouch = isButton ? Action.Touch.TAP : Action.Touch.SWIPE;
- Action action = newCommandAction(actionTouch);
- action.command = Action.Command.BACK;
- action.dir = isButton ? Action.Direction.NONE :
- gestureSwipeLeft ? Action.Direction.LEFT : Action.Direction.RIGHT;
- Target target = newControlTarget(isButton ? ControlType.BACK_BUTTON :
- ControlType.BACK_GESTURE);
- target.spanX = downX;
- target.spanY = downY;
- target.cardinality = completed ? 1 : 0;
- LauncherEvent event = newLauncherEvent(action, target, newContainerTarget(containerType));
-
- dispatchUserEvent(event, null);
- }
-
- /**
- * Currently logs following containers: workspace, allapps, widget tray.
- */
- public final void resetElapsedContainerMillis(String reason) {
- mElapsedContainerMillis = SystemClock.uptimeMillis();
- if (!IS_VERBOSE) {
- return;
- }
- Log.d(TAG, "resetElapsedContainerMillis reason=" + reason);
-
- }
-
public final void startSession() {
mSessionStarted = true;
mElapsedSessionMillis = SystemClock.uptimeMillis();
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index eb5d106..2695e66 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -305,7 +305,7 @@
*
* @return the corresponding AppInfo or null
*/
- private @Nullable AppInfo findAppInfo(@NonNull ComponentName componentName,
+ public @Nullable AppInfo findAppInfo(@NonNull ComponentName componentName,
@NonNull UserHandle user) {
for (AppInfo info: data) {
if (componentName.equals(info.componentName) && user.equals(info.user)) {
diff --git a/src/com/android/launcher3/model/BaseLoaderResults.java b/src/com/android/launcher3/model/BaseLoaderResults.java
index 586333f..5c85bab 100644
--- a/src/com/android/launcher3/model/BaseLoaderResults.java
+++ b/src/com/android/launcher3/model/BaseLoaderResults.java
@@ -17,7 +17,6 @@
package com.android.launcher3.model;
import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems;
-import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks;
import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially;
import android.util.Log;
@@ -206,9 +205,6 @@
mExtraItems.forEach(item ->
executeCallbacksTask(c -> c.bindExtraContainerItems(item), mainExecutor));
- // Locate available spots for prediction using currentWorkspaceItems
- IntArray gaps = getMissingHotseatRanks(currentWorkspaceItems, idp.numHotseatIcons);
- bindPredictedItems(gaps, mainExecutor);
// In case of validFirstPage, only bind the first screen, and defer binding the
// remaining screens after first onDraw (and an optional the fade animation whichever
// happens later).
@@ -261,11 +257,6 @@
}
}
- private void bindPredictedItems(IntArray ranks, final Executor executor) {
- ArrayList<AppInfo> items = new ArrayList<>(mBgDataModel.cachedPredictedItems);
- executeCallbacksTask(c -> c.bindPredictedItems(items, ranks), executor);
- }
-
protected void executeCallbacksTask(CallbackTask task, Executor executor) {
executor.execute(() -> {
if (mMyBindingId != mBgDataModel.lastBindId) {
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index 140342f..49b40ed 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -31,7 +31,6 @@
import android.util.ArraySet;
import android.util.Log;
-import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Workspace;
@@ -104,11 +103,6 @@
public final IntSparseArrayMap<FixedContainerItems> extraItems = new IntSparseArrayMap<>();
/**
- * List of all cached predicted items visible on home screen
- */
- public final ArrayList<AppInfo> cachedPredictedItems = new ArrayList<>();
-
- /**
* Maps all launcher activities to counts of their shortcuts.
*/
public final HashMap<ComponentKey, Integer> deepShortcutMap = new HashMap<>();
@@ -298,8 +292,7 @@
.filter(wi -> wi.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
.map(ShortcutKey::fromItemInfo),
// Pending shortcuts
- InstallShortcutReceiver.getPendingShortcuts(context)
- .stream().filter(si -> si.user.equals(user)))
+ ItemInstallQueue.INSTANCE.get(context).getPendingShortcuts(user))
.collect(groupingBy(ShortcutKey::getPackageName,
mapping(ShortcutKey::getId, Collectors.toSet())));
@@ -472,10 +465,5 @@
default void bindExtraContainerItems(FixedContainerItems item) { }
void bindAllApplications(AppInfo[] apps, int flags);
-
- /**
- * Binds predicted appInfos at at available prediction slots.
- */
- void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks);
}
}
diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java
index 5112304..70d1b48 100644
--- a/src/com/android/launcher3/model/FirstScreenBroadcast.java
+++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java
@@ -17,25 +17,30 @@
import static android.os.Process.myUserHandle;
+import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInstaller.SessionInfo;
+import android.os.UserHandle;
import android.util.Log;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map;
import java.util.Set;
+import java.util.stream.Collectors;
/**
* Helper class to send broadcasts to package installers that have:
@@ -61,26 +66,10 @@
private static final String VERIFICATION_TOKEN_EXTRA = "verificationToken";
- private final MultiHashMap<String, String> mPackagesForInstaller;
+ private final HashMap<PackageUserKey, SessionInfo> mSessionInfoForPackage;
public FirstScreenBroadcast(HashMap<PackageUserKey, SessionInfo> sessionInfoForPackage) {
- mPackagesForInstaller = getPackagesForInstaller(sessionInfoForPackage);
- }
-
- /**
- * @return Map where the key is the package name of the installer, and the value is a list
- * of packages with active sessions for that installer.
- */
- private MultiHashMap<String, String> getPackagesForInstaller(
- HashMap<PackageUserKey, SessionInfo> sessionInfoForPackage) {
- MultiHashMap<String, String> packagesForInstaller = new MultiHashMap<>();
- for (Map.Entry<PackageUserKey, SessionInfo> entry : sessionInfoForPackage.entrySet()) {
- if (myUserHandle().equals(entry.getKey().mUser)) {
- packagesForInstaller.addToList(entry.getValue().getInstallerPackageName(),
- entry.getKey().mPackageName);
- }
- }
- return packagesForInstaller;
+ mSessionInfoForPackage = sessionInfoForPackage;
}
/**
@@ -88,9 +77,15 @@
* first screen.
*/
public void sendBroadcasts(Context context, List<ItemInfo> firstScreenItems) {
- for (Map.Entry<String, ArrayList<String>> entry : mPackagesForInstaller.entrySet()) {
- sendBroadcastToInstaller(context, entry.getKey(), entry.getValue(), firstScreenItems);
- }
+ UserHandle myUser = myUserHandle();
+ mSessionInfoForPackage
+ .values()
+ .stream()
+ .filter(info -> myUser.equals(getUserHandle(info)))
+ .collect(groupingBy(SessionInfo::getInstallerPackageName,
+ mapping(SessionInfo::getAppPackageName, Collectors.toSet())))
+ .forEach((installer, packages) ->
+ sendBroadcastToInstaller(context, installer, packages, firstScreenItems));
}
/**
@@ -99,7 +94,7 @@
* @param firstScreenItems List of items on the first screen.
*/
private void sendBroadcastToInstaller(Context context, String installerPackageName,
- List<String> packages, List<ItemInfo> firstScreenItems) {
+ Set<String> packages, List<ItemInfo> firstScreenItems) {
Set<String> folderItems = new HashSet<>();
Set<String> workspaceItems = new HashSet<>();
Set<String> hotseatItems = new HashSet<>();
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
new file mode 100644
index 0000000..5e48a0f
--- /dev/null
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+package com.android.launcher3.model;
+
+import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID;
+
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
+import static com.android.launcher3.model.data.AppInfo.makeLaunchIntent;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.LauncherActivityInfo;
+import android.content.pm.LauncherApps;
+import android.content.pm.ShortcutInfo;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
+
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.shortcuts.ShortcutKey;
+import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.PersistedItemArray;
+import com.android.launcher3.util.Preconditions;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Class to maintain a queue of pending items to be added to the workspace.
+ */
+public class ItemInstallQueue {
+
+ public static final int FLAG_ACTIVITY_PAUSED = 1;
+ public static final int FLAG_LOADER_RUNNING = 2;
+ public static final int FLAG_DRAG_AND_DROP = 4;
+
+ private static final String TAG = "InstallShortcutReceiver";
+
+ // The set of shortcuts that are pending install
+ private static final String APPS_PENDING_INSTALL = "apps_to_install";
+
+ public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
+ public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
+
+ public static MainThreadInitializedObject<ItemInstallQueue> INSTANCE =
+ new MainThreadInitializedObject<>(ItemInstallQueue::new);
+
+ private final PersistedItemArray<PendingInstallShortcutInfo> mStorage =
+ new PersistedItemArray<>(APPS_PENDING_INSTALL);
+ private final Context mContext;
+
+ // Determines whether to defer installing shortcuts immediately until
+ // processAllPendingInstalls() is called.
+ private int mInstallQueueDisabledFlags = 0;
+
+ // Only accessed on worker thread
+ private List<PendingInstallShortcutInfo> mItems;
+
+ private ItemInstallQueue(Context context) {
+ mContext = context;
+ }
+
+ @WorkerThread
+ private void ensureQueueLoaded() {
+ Preconditions.assertWorkerThread();
+ if (mItems == null) {
+ mItems = mStorage.read(mContext, this::decode);
+ }
+ }
+
+ @WorkerThread
+ private void addToQueue(PendingInstallShortcutInfo info) {
+ ensureQueueLoaded();
+ mItems.add(info);
+ mStorage.write(mContext, mItems);
+ }
+
+ @WorkerThread
+ private void flushQueueInBackground() {
+ Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
+ if (launcher == null) {
+ // Launcher not loaded
+ return;
+ }
+ ensureQueueLoaded();
+ if (mItems.isEmpty()) {
+ return;
+ }
+
+ List<Pair<ItemInfo, Object>> installQueue = mItems.stream()
+ .map(info -> info.getItemInfo(mContext))
+ .collect(Collectors.toList());
+
+ // Add the items and clear queue
+ if (!installQueue.isEmpty()) {
+ launcher.getModel().addAndBindAddedWorkspaceItems(installQueue);
+ }
+ mItems.clear();
+ mStorage.getFile(mContext).delete();
+ }
+
+ /**
+ * Removes previously added items from the queue.
+ */
+ @WorkerThread
+ public void removeFromInstallQueue(HashSet<String> packageNames, UserHandle user) {
+ if (packageNames.isEmpty()) {
+ return;
+ }
+ ensureQueueLoaded();
+ if (mItems.removeIf(item ->
+ item.user.equals(user) && packageNames.contains(getIntentPackage(item.intent)))) {
+ mStorage.write(mContext, mItems);
+ }
+ }
+
+ /**
+ * Adds an item to the install queue
+ */
+ public void queueItem(ShortcutInfo info) {
+ queuePendingShortcutInfo(new PendingInstallShortcutInfo(info));
+ }
+
+ /**
+ * Adds an item to the install queue
+ */
+ public void queueItem(AppWidgetProviderInfo info, int widgetId) {
+ queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, widgetId));
+ }
+
+ /**
+ * Adds an item to the install queue
+ */
+ public void queueItem(String packageName, UserHandle userHandle) {
+ queuePendingShortcutInfo(new PendingInstallShortcutInfo(packageName, userHandle));
+ }
+
+ /**
+ * Returns a stream of all pending shortcuts in the queue
+ */
+ @WorkerThread
+ public Stream<ShortcutKey> getPendingShortcuts(UserHandle user) {
+ ensureQueueLoaded();
+ return mItems.stream()
+ .filter(item -> item.itemType == ITEM_TYPE_DEEP_SHORTCUT && user.equals(item.user))
+ .map(item -> ShortcutKey.fromIntent(item.intent, user));
+ }
+
+ private void queuePendingShortcutInfo(PendingInstallShortcutInfo info) {
+ // Queue the item up for adding if launcher has not loaded properly yet
+ MODEL_EXECUTOR.post(() -> addToQueue(info));
+ flushInstallQueue();
+ }
+
+ /**
+ * Pauses the push-to-model flow until unpaused. All items are held in the queue and
+ * not added to the model.
+ */
+ public void pauseModelPush(int flag) {
+ mInstallQueueDisabledFlags |= flag;
+ }
+
+ /**
+ * Adds all the queue items to the model if the use is completely resumed.
+ */
+ public void resumeModelPush(int flag) {
+ mInstallQueueDisabledFlags &= ~flag;
+ flushInstallQueue();
+ }
+
+ private void flushInstallQueue() {
+ if (mInstallQueueDisabledFlags != 0) {
+ return;
+ }
+ MODEL_EXECUTOR.post(this::flushQueueInBackground);
+ }
+
+ private static class PendingInstallShortcutInfo extends ItemInfo {
+
+ final Intent intent;
+
+ @Nullable ShortcutInfo shortcutInfo;
+ @Nullable AppWidgetProviderInfo providerInfo;
+
+ /**
+ * Initializes a PendingInstallShortcutInfo to represent a pending launcher target.
+ */
+ public PendingInstallShortcutInfo(String packageName, UserHandle userHandle) {
+ itemType = Favorites.ITEM_TYPE_APPLICATION;
+ intent = new Intent().setPackage(packageName);
+ user = userHandle;
+ }
+
+ /**
+ * Initializes a PendingInstallShortcutInfo to represent a deep shortcut.
+ */
+ public PendingInstallShortcutInfo(ShortcutInfo info) {
+ itemType = Favorites.ITEM_TYPE_DEEP_SHORTCUT;
+ intent = ShortcutKey.makeIntent(info);
+ user = info.getUserHandle();
+
+ shortcutInfo = info;
+ }
+
+ /**
+ * Initializes a PendingInstallShortcutInfo to represent an app widget.
+ */
+ public PendingInstallShortcutInfo(AppWidgetProviderInfo info, int widgetId) {
+ itemType = Favorites.ITEM_TYPE_APPWIDGET;
+ intent = new Intent()
+ .setComponent(info.provider)
+ .putExtra(EXTRA_APPWIDGET_ID, widgetId);
+ user = info.getProfile();
+
+ providerInfo = info;
+ }
+
+ @Override
+ public Intent getIntent() {
+ return intent;
+ }
+
+ public Pair<ItemInfo, Object> getItemInfo(Context context) {
+ switch (itemType) {
+ case ITEM_TYPE_APPLICATION: {
+ String packageName = intent.getPackage();
+ List<LauncherActivityInfo> laiList =
+ context.getSystemService(LauncherApps.class)
+ .getActivityList(packageName, user);
+
+ final WorkspaceItemInfo si = new WorkspaceItemInfo();
+ si.user = user;
+ si.itemType = ITEM_TYPE_APPLICATION;
+
+ LauncherActivityInfo lai;
+ boolean usePackageIcon = laiList.isEmpty();
+ if (usePackageIcon) {
+ lai = null;
+ si.intent = makeLaunchIntent(new ComponentName(packageName, ""))
+ .setPackage(packageName);
+ si.status |= WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
+ } else {
+ lai = laiList.get(0);
+ si.intent = makeLaunchIntent(lai);
+ }
+ LauncherAppState.getInstance(context).getIconCache()
+ .getTitleAndIcon(si, () -> lai, usePackageIcon, false);
+ return Pair.create(si, null);
+ }
+ case ITEM_TYPE_DEEP_SHORTCUT: {
+ WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, context);
+ LauncherAppState.getInstance(context).getIconCache()
+ .getShortcutIcon(itemInfo, shortcutInfo);
+ return Pair.create(itemInfo, shortcutInfo);
+ }
+ case ITEM_TYPE_APPWIDGET: {
+ LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
+ .fromProviderInfo(context, providerInfo);
+ LauncherAppWidgetInfo widgetInfo = new LauncherAppWidgetInfo(
+ intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0),
+ info.provider);
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(context);
+ widgetInfo.minSpanX = info.minSpanX;
+ widgetInfo.minSpanY = info.minSpanY;
+ widgetInfo.spanX = Math.min(info.spanX, idp.numColumns);
+ widgetInfo.spanY = Math.min(info.spanY, idp.numRows);
+ widgetInfo.user = user;
+ return Pair.create(widgetInfo, providerInfo);
+ }
+ }
+ return null;
+ }
+ }
+
+ private static String getIntentPackage(Intent intent) {
+ return intent.getComponent() == null
+ ? intent.getPackage() : intent.getComponent().getPackageName();
+ }
+
+ private PendingInstallShortcutInfo decode(int itemType, UserHandle user, Intent intent) {
+ switch (itemType) {
+ case Favorites.ITEM_TYPE_APPLICATION:
+ return new PendingInstallShortcutInfo(intent.getPackage(), user);
+ case Favorites.ITEM_TYPE_DEEP_SHORTCUT: {
+ List<ShortcutInfo> si = ShortcutKey.fromIntent(intent, user)
+ .buildRequest(mContext)
+ .query(ShortcutRequest.ALL);
+ if (si.isEmpty()) {
+ return null;
+ } else {
+ return new PendingInstallShortcutInfo(si.get(0));
+ }
+ }
+ case Favorites.ITEM_TYPE_APPWIDGET: {
+ int widgetId = intent.getIntExtra(EXTRA_APPWIDGET_ID, 0);
+ AppWidgetProviderInfo info =
+ AppWidgetManager.getInstance(mContext).getAppWidgetInfo(widgetId);
+ if (info == null || !info.provider.equals(intent.getComponent())
+ || !info.getProfile().equals(user)) {
+ return null;
+ }
+ return new PendingInstallShortcutInfo(info, widgetId);
+ }
+ default:
+ Log.e(TAG, "Unknown item type");
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 1dd8c11..a9e385f 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -48,8 +48,6 @@
import android.util.LongSparseArray;
import android.util.TimingLogger;
-import androidx.annotation.WorkerThread;
-
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
@@ -83,7 +81,6 @@
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.LooperIdleLock;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.TraceHelper;
@@ -92,8 +89,10 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.CancellationException;
/**
@@ -190,13 +189,13 @@
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
loadWorkspace(allShortcuts);
- loadCachedPredictions();
logger.addSplit("loadWorkspace");
verifyNotStopped();
mResults.bindWorkspace();
logger.addSplit("bindWorkspace");
+ mModelDelegate.workspaceLoadComplete();
// Notify the installer packages of packages with active installs on the first screen.
sendFirstScreenActiveInstallsBroadcast();
logger.addSplit("sendFirstScreenActiveInstallsBroadcast");
@@ -304,7 +303,7 @@
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
final boolean isSafeMode = pmHelper.isSafeMode();
final boolean isSdCardReady = Utilities.isBootCompleted();
- final MultiHashMap<UserHandle, String> pendingPackages = new MultiHashMap<>();
+ final Set<PackageUserKey> pendingPackages = new HashSet<>();
boolean clearDb = false;
try {
@@ -485,7 +484,7 @@
// SdCard is not ready yet. Package might get available,
// once it is ready.
Log.d(TAG, "Missing pkg, will check later: " + targetPkg);
- pendingPackages.addToList(c.user, targetPkg);
+ pendingPackages.add(new PackageUserKey(targetPkg, c.user));
// Add the icon on the workspace anyway.
allowMissingTarget = true;
} else {
@@ -839,24 +838,6 @@
}
}
- @WorkerThread
- private void loadCachedPredictions() {
- synchronized (mBgDataModel) {
- List<ComponentKey> componentKeys =
- mApp.getPredictionModel().getPredictionComponentKeys();
- List<LauncherActivityInfo> l;
- mBgDataModel.cachedPredictedItems.clear();
- for (ComponentKey key : componentKeys) {
- l = mLauncherApps.getActivityList(key.componentName.getPackageName(), key.user);
- if (l.size() == 0) continue;
- AppInfo info = new AppInfo(l.get(0), key.user,
- mUserManagerState.isUserQuiet(key.user));
- mBgDataModel.cachedPredictedItems.add(info);
- mIconCache.getTitleAndIcon(info, false);
- }
- }
- }
-
private void sanitizeData() {
Context context = mApp.getContext();
if (mItemsDeleted) {
@@ -900,14 +881,6 @@
PackageInstallInfo.fromInstallingState(info));
}
}
- for (AppInfo item : mBgDataModel.cachedPredictedItems) {
- List<LauncherActivityInfo> l = mLauncherApps.getActivityList(
- item.componentName.getPackageName(), item.user);
- for (LauncherActivityInfo info : l) {
- boolean quietMode = mUserManagerState.isUserQuiet(item.user);
- mBgAllAppsList.add(new AppInfo(info, item.user, quietMode), info);
- }
- }
mBgAllAppsList.setFlags(FLAG_QUIET_MODE_ENABLED,
mUserManagerState.isAnyProfileQuietModeEnabled());
diff --git a/src/com/android/launcher3/model/ModelDelegate.java b/src/com/android/launcher3/model/ModelDelegate.java
index 53e8a86..3ed8809 100644
--- a/src/com/android/launcher3/model/ModelDelegate.java
+++ b/src/com/android/launcher3/model/ModelDelegate.java
@@ -72,6 +72,12 @@
public void loadItems(UserManagerState ums, Map<ShortcutKey, ShortcutInfo> pinnedShortcuts) { }
/**
+ * Called during loader after workspace loading is complete
+ */
+ @WorkerThread
+ public void workspaceLoadComplete() { }
+
+ /**
* Called when the delegate is no loner needed
*/
@WorkerThread
diff --git a/src/com/android/launcher3/model/ModelUtils.java b/src/com/android/launcher3/model/ModelUtils.java
index a8cc9ad..9b5fac8 100644
--- a/src/com/android/launcher3/model/ModelUtils.java
+++ b/src/com/android/launcher3/model/ModelUtils.java
@@ -36,8 +36,8 @@
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.stream.IntStream;
/**
@@ -56,13 +56,7 @@
ArrayList<T> currentScreenItems,
ArrayList<T> otherScreenItems) {
// Purge any null ItemInfos
- Iterator<T> iter = allWorkspaceItems.iterator();
- while (iter.hasNext()) {
- ItemInfo i = iter.next();
- if (i == null) {
- iter.remove();
- }
- }
+ allWorkspaceItems.removeIf(Objects::isNull);
// Order the set of items by their containers first, this allows use to walk through the
// list sequentially, build up a list of containers that are in the specified screen,
// as well as all items in those containers.
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index c0ae6f9..896bfb6 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -28,7 +28,6 @@
import android.os.UserManager;
import android.util.Log;
-import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.config.FeatureFlags;
@@ -320,7 +319,8 @@
deleteAndBindComponentsRemoved(removeMatch);
// Remove any queued items from the install queue
- InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser);
+ ItemInstallQueue.INSTANCE.get(context)
+ .removeFromInstallQueue(removedPackages, mUser);
}
if (mOp == OP_ADD) {
diff --git a/src/com/android/launcher3/model/PredictionModel.java b/src/com/android/launcher3/model/PredictionModel.java
deleted file mode 100644
index cb3903d..0000000
--- a/src/com/android/launcher3/model/PredictionModel.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2020 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.
- */
-package com.android.launcher3.model;
-
-import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.UserHandle;
-
-import androidx.annotation.AnyThread;
-import androidx.annotation.WorkerThread;
-
-import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.pm.UserCache;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.Preconditions;
-import com.android.launcher3.util.ResourceBasedOverride;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Model Helper for app predictions
- */
-public class PredictionModel implements ResourceBasedOverride {
-
- private static final String CACHED_ITEMS_KEY = "predicted_item_keys";
- private static final int MAX_CACHE_ITEMS = 5;
-
- protected Context mContext;
- private SharedPreferences mDevicePrefs;
- private UserCache mUserCache;
-
-
- /**
- * Retrieve instance of this object that can be overridden in runtime based on the build
- * variant of the application.
- */
- public static PredictionModel newInstance(Context context) {
- PredictionModel model = Overrides.getObject(PredictionModel.class, context,
- R.string.prediction_model_class);
- model.init(context);
- return model;
- }
-
- protected void init(Context context) {
- mContext = context;
- mDevicePrefs = Utilities.getDevicePrefs(mContext);
- mUserCache = UserCache.INSTANCE.get(mContext);
-
- }
-
- /**
- * Formats and stores a list of component key in device preferences.
- */
- @AnyThread
- public void cachePredictionComponentKeys(List<ComponentKey> componentKeys) {
- MODEL_EXECUTOR.execute(() -> {
- LauncherAppState appState = LauncherAppState.getInstance(mContext);
- StringBuilder builder = new StringBuilder();
- int count = Math.min(componentKeys.size(), MAX_CACHE_ITEMS);
- for (int i = 0; i < count; i++) {
- builder.append(serializeComponentKeyToString(componentKeys.get(i)));
- builder.append("\n");
- }
- if (componentKeys.isEmpty() /* should invalidate loader items */) {
- appState.getModel().enqueueModelUpdateTask(new BaseModelUpdateTask() {
- @Override
- public void execute(LauncherAppState app, BgDataModel model, AllAppsList apps) {
- model.cachedPredictedItems.clear();
- }
- });
- }
- mDevicePrefs.edit().putString(CACHED_ITEMS_KEY, builder.toString()).apply();
- });
- }
-
- /**
- * parses and returns ComponentKeys saved by
- * {@link PredictionModel#cachePredictionComponentKeys(List)}
- */
- @WorkerThread
- public List<ComponentKey> getPredictionComponentKeys() {
- Preconditions.assertWorkerThread();
- ArrayList<ComponentKey> items = new ArrayList<>();
- String cachedBlob = mDevicePrefs.getString(CACHED_ITEMS_KEY, "");
- for (String line : cachedBlob.split("\n")) {
- ComponentKey key = getComponentKeyFromSerializedString(line);
- if (key != null) {
- items.add(key);
- }
-
- }
- return items;
- }
-
- private String serializeComponentKeyToString(ComponentKey componentKey) {
- long userSerialNumber = mUserCache.getSerialNumberForUser(componentKey.user);
- return componentKey.componentName.flattenToString() + "#" + userSerialNumber;
- }
-
- private ComponentKey getComponentKeyFromSerializedString(String str) {
- int sep = str.indexOf('#');
- if (sep < 0 || (sep + 1) >= str.length()) {
- return null;
- }
- ComponentName componentName = ComponentName.unflattenFromString(str.substring(0, sep));
- if (componentName == null) {
- return null;
- }
- try {
- long serialNumber = Long.parseLong(str.substring(sep + 1));
- UserHandle userHandle = mUserCache.getUserForSerialNumber(serialNumber);
- return userHandle != null ? new ComponentKey(componentName, userHandle) : null;
- } catch (NumberFormatException ex) {
- return null;
- }
- }
-}
diff --git a/src/com/android/launcher3/model/SdCardAvailableReceiver.java b/src/com/android/launcher3/model/SdCardAvailableReceiver.java
index eb3cb52..3798575 100644
--- a/src/com/android/launcher3/model/SdCardAvailableReceiver.java
+++ b/src/com/android/launcher3/model/SdCardAvailableReceiver.java
@@ -24,12 +24,11 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherModel;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
+import com.android.launcher3.util.PackageUserKey;
import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Map.Entry;
+import java.util.Set;
/**
* Helper class to re-query app status when SD-card becomes available.
@@ -42,10 +41,9 @@
private final LauncherModel mModel;
private final Context mContext;
- private final MultiHashMap<UserHandle, String> mPackages;
+ private final Set<PackageUserKey> mPackages;
- public SdCardAvailableReceiver(LauncherAppState app,
- MultiHashMap<UserHandle, String> packages) {
+ public SdCardAvailableReceiver(LauncherAppState app, Set<PackageUserKey> packages) {
mModel = app.getModel();
mContext = app.getContext();
mPackages = packages;
@@ -55,19 +53,17 @@
public void onReceive(Context context, Intent intent) {
final LauncherApps launcherApps = context.getSystemService(LauncherApps.class);
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
- for (Entry<UserHandle, ArrayList<String>> entry : mPackages.entrySet()) {
- UserHandle user = entry.getKey();
+ for (PackageUserKey puk : mPackages) {
+ UserHandle user = puk.mUser;
final ArrayList<String> packagesRemoved = new ArrayList<>();
final ArrayList<String> packagesUnavailable = new ArrayList<>();
- for (String pkg : new HashSet<>(entry.getValue())) {
- if (!launcherApps.isPackageEnabled(pkg, user)) {
- if (pmHelper.isAppOnSdcard(pkg, user)) {
- packagesUnavailable.add(pkg);
- } else {
- packagesRemoved.add(pkg);
- }
+ if (!launcherApps.isPackageEnabled(puk.mPackageName, user)) {
+ if (pmHelper.isAppOnSdcard(puk.mPackageName, user)) {
+ packagesUnavailable.add(puk.mPackageName);
+ } else {
+ packagesRemoved.add(puk.mPackageName);
}
}
if (!packagesRemoved.isEmpty()) {
diff --git a/src/com/android/launcher3/model/ShortcutsChangedTask.java b/src/com/android/launcher3/model/ShortcutsChangedTask.java
index 88006ba..6fedad1 100644
--- a/src/com/android/launcher3/model/ShortcutsChangedTask.java
+++ b/src/com/android/launcher3/model/ShortcutsChangedTask.java
@@ -25,11 +25,12 @@
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.shortcuts.ShortcutRequest;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.MultiHashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* Handles changes due to shortcut manager updates (deep shortcut changes)
@@ -53,54 +54,53 @@
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
final Context context = app.getContext();
// Find WorkspaceItemInfo's that have changed on the workspace.
- HashSet<ShortcutKey> removedKeys = new HashSet<>();
- MultiHashMap<ShortcutKey, WorkspaceItemInfo> keyToShortcutInfo = new MultiHashMap<>();
- HashSet<String> allIds = new HashSet<>();
+ ArrayList<WorkspaceItemInfo> matchingWorkspaceItems = new ArrayList<>();
synchronized (dataModel) {
dataModel.forAllWorkspaceItemInfos(mUser, si -> {
if ((si.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& mPackageName.equals(si.getIntent().getPackage())) {
- keyToShortcutInfo.addToList(ShortcutKey.fromItemInfo(si), si);
- allIds.add(si.getDeepShortcutId());
+ matchingWorkspaceItems.add(si);
}
});
}
- final ArrayList<WorkspaceItemInfo> updatedWorkspaceItemInfos = new ArrayList<>();
- if (!keyToShortcutInfo.isEmpty()) {
+ if (!matchingWorkspaceItems.isEmpty()) {
// Update the workspace to reflect the changes to updated shortcuts residing on it.
+ List<String> allLauncherKnownIds = matchingWorkspaceItems.stream()
+ .map(WorkspaceItemInfo::getDeepShortcutId)
+ .distinct()
+ .collect(Collectors.toList());
List<ShortcutInfo> shortcuts = new ShortcutRequest(context, mUser)
- .forPackage(mPackageName, new ArrayList<>(allIds))
+ .forPackage(mPackageName, allLauncherKnownIds)
.query(ShortcutRequest.ALL);
+
+ Set<String> nonPinnedIds = new HashSet<>(allLauncherKnownIds);
+ ArrayList<WorkspaceItemInfo> updatedWorkspaceItemInfos = new ArrayList<>();
for (ShortcutInfo fullDetails : shortcuts) {
- ShortcutKey key = ShortcutKey.fromInfo(fullDetails);
- List<WorkspaceItemInfo> workspaceItemInfos = keyToShortcutInfo.remove(key);
if (!fullDetails.isPinned()) {
- // The shortcut was previously pinned but is no longer, so remove it from
- // the workspace and our pinned shortcut counts.
- // Note that we put this check here, after querying for full details,
- // because there's a possible race condition between pinning and
- // receiving this callback.
- removedKeys.add(key);
continue;
}
- for (final WorkspaceItemInfo workspaceItemInfo : workspaceItemInfos) {
- workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context);
- app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails);
- updatedWorkspaceItemInfos.add(workspaceItemInfo);
- }
+
+ String sid = fullDetails.getId();
+ nonPinnedIds.remove(sid);
+ matchingWorkspaceItems
+ .stream()
+ .filter(itemInfo -> sid.equals(itemInfo.getDeepShortcutId()))
+ .forEach(workspaceItemInfo -> {
+ workspaceItemInfo.updateFromDeepShortcutInfo(fullDetails, context);
+ app.getIconCache().getShortcutIcon(workspaceItemInfo, fullDetails);
+ updatedWorkspaceItemInfos.add(workspaceItemInfo);
+ });
}
- }
- // If there are still entries in keyToShortcutInfo, that means that
- // the corresponding shortcuts weren't passed in onShortcutsChanged(). This
- // means they were cleared, so we remove and unpin them now.
- removedKeys.addAll(keyToShortcutInfo.keySet());
-
- bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
- if (!keyToShortcutInfo.isEmpty()) {
- deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(removedKeys));
+ bindUpdatedWorkspaceItems(updatedWorkspaceItemInfos);
+ if (!nonPinnedIds.isEmpty()) {
+ deleteAndBindComponentsRemoved(ItemInfoMatcher.ofShortcutKeys(
+ nonPinnedIds.stream()
+ .map(id -> new ShortcutKey(mPackageName, mUser, id))
+ .collect(Collectors.toSet())));
+ }
}
if (mUpdateIdMap) {
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index 835f72d..80eeb22 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -106,7 +106,6 @@
view, 0, 0, view.getWidth(), view.getHeight()).toBundle();
try {
intent.send(null, 0, null, null, null, null, activityOptions);
- launcher.getUserEventDispatcher().logNotificationLaunch(view, intent);
launcher.getStatsLogManager().logger().withItemInfo(mItemInfo)
.log(LAUNCHER_NOTIFICATION_LAUNCH_TAP);
} catch (PendingIntent.CanceledException e) {
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index d546013..753a6dd 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -32,11 +32,11 @@
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
-import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.ItemInstallQueue;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.LooperExecutor;
@@ -213,8 +213,8 @@
&& !mPromiseIconIds.contains(sessionInfo.getSessionId())
&& new PackageManagerHelper(mAppContext).getApplicationInfo(
sessionInfo.getAppPackageName(), getUserHandle(sessionInfo), 0) == null) {
- InstallShortcutReceiver.queueApplication(
- sessionInfo.getAppPackageName(), getUserHandle(sessionInfo), mAppContext);
+ ItemInstallQueue.INSTANCE.get(mAppContext)
+ .queueItem(sessionInfo.getAppPackageName(), getUserHandle(sessionInfo));
mPromiseIconIds.add(sessionInfo.getSessionId());
updatePromiseIconPrefs();
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 896fb18..26b32b8 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -20,12 +20,9 @@
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
-import static com.android.launcher3.notification.NotificationMainView.NOTIFICATION_ITEM_INFO;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS;
import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.animation.AnimatorSet;
@@ -147,17 +144,6 @@
return (type & TYPE_ACTION_POPUP) != 0;
}
- @Override
- public void logActionCommand(int command) {
- mLauncher.getUserEventDispatcher().logActionCommand(
- command, mOriginalIcon, getLogContainerType());
- }
-
- @Override
- public int getLogContainerType() {
- return ContainerType.DEEPSHORTCUTS;
- }
-
public OnClickListener getItemClickListener() {
return (view) -> {
mLauncher.getItemOnClickListener().onClick(view);
@@ -496,18 +482,6 @@
}
@Override
- public void fillInLogContainerData(ItemInfo childInfo, Target child,
- ArrayList<Target> parents) {
- if (childInfo == NOTIFICATION_ITEM_INFO) {
- child.itemType = ItemType.NOTIFICATION;
- } else {
- child.itemType = ItemType.DEEPSHORTCUT;
- child.rank = childInfo.rank;
- }
- parents.add(newContainerTarget(ContainerType.DEEPSHORTCUTS));
- }
-
- @Override
protected void onCreateCloseAnimation(AnimatorSet anim) {
// Animate original icon's text back in.
anim.play(mOriginalIcon.createTextAlphaAnimator(true /* fadeIn */));
diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java
index 5a5f668..76048ba 100644
--- a/src/com/android/launcher3/popup/PopupDataProvider.java
+++ b/src/com/android/launcher3/popup/PopupDataProvider.java
@@ -38,7 +38,6 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
@@ -202,20 +201,11 @@
}
public List<WidgetItem> getWidgetsForPackageUser(PackageUserKey packageUserKey) {
- for (WidgetListRowEntry entry : mAllWidgets) {
- if (entry.pkgItem.packageName.equals(packageUserKey.mPackageName)) {
- ArrayList<WidgetItem> widgets = new ArrayList<>(entry.widgets);
- // Remove widgets not associated with the correct user.
- Iterator<WidgetItem> iterator = widgets.iterator();
- while (iterator.hasNext()) {
- if (!iterator.next().user.equals(packageUserKey.mUser)) {
- iterator.remove();
- }
- }
- return widgets.isEmpty() ? null : widgets;
- }
- }
- return null;
+ return mAllWidgets.stream()
+ .filter(row -> row.pkgItem.packageName.equals(packageUserKey.mPackageName))
+ .flatMap(row -> row.widgets.stream())
+ .filter(widget -> packageUserKey.mUser.equals(widget.user))
+ .collect(Collectors.toList());
}
/**
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 7998488..81302ac 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -99,7 +99,7 @@
final List<WidgetItem> widgets =
launcher.getPopupDataProvider().getWidgetsForPackageUser(new PackageUserKey(
itemInfo.getTargetComponent().getPackageName(), itemInfo.user));
- if (widgets == null) {
+ if (widgets.isEmpty()) {
return null;
}
return new Widgets(launcher, itemInfo);
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 31c3014..2b04365 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -197,9 +197,6 @@
public void bindItems(List<ItemInfo> shortcuts, boolean forceAnimateIcons) { }
@Override
- public void bindPredictedItems(List<AppInfo> appInfos, IntArray ranks) { }
-
- @Override
public void bindScreens(IntArray orderedScreenIds) { }
@Override
diff --git a/src/com/android/launcher3/settings/SettingsActivity.java b/src/com/android/launcher3/settings/SettingsActivity.java
index ec3a467..922425f 100644
--- a/src/com/android/launcher3/settings/SettingsActivity.java
+++ b/src/com/android/launcher3/settings/SettingsActivity.java
@@ -44,6 +44,7 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.SecureSettingsObserver;
@@ -171,6 +172,10 @@
protected boolean initPreference(Preference preference) {
switch (preference.getKey()) {
case NOTIFICATION_DOTS_PREFERENCE_KEY:
+ if (WidgetsModel.GO_DISABLE_NOTIFICATION_DOTS) {
+ return false;
+ }
+
// Listen to system notification dot settings while this UI is active.
mNotificationDotsObserver = newNotificationSettingsObserver(
getActivity(), (NotificationDotsPreference) preference);
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 6ff1254..beb5b68 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -312,7 +312,13 @@
handler.setStateWithAnimation(state, mConfig, builder);
}
}
- builder.addListener(new AnimationSuccessListener() {
+ builder.addListener(createStateAnimationListener(state));
+ mConfig.setAnimation(builder.buildAnim(), state);
+ return builder;
+ }
+
+ private AnimatorListener createStateAnimationListener(STATE_TYPE state) {
+ return new AnimationSuccessListener() {
@Override
public void onAnimationStart(Animator animation) {
@@ -327,9 +333,7 @@
}
onStateTransitionEnd(state);
}
- });
- mConfig.setAnimation(builder.buildAnim(), state);
- return builder;
+ };
}
private void onStateTransitionStart(STATE_TYPE state) {
@@ -397,6 +401,19 @@
}
/**
+ * @see #setCurrentAnimation(AnimatorSet, Animator...). Using this method tells the StateManager
+ * that this is a custom animation to the given state, and thus the StateManager will add an
+ * animation listener to call {@link #onStateTransitionStart} and {@link #onStateTransitionEnd}.
+ * @param anim The custom animation to the given state.
+ * @param toState The state we are animating towards.
+ */
+ public void setCurrentAnimation(AnimatorSet anim, STATE_TYPE toState) {
+ cancelAnimation();
+ setCurrentAnimation(anim);
+ anim.addListener(createStateAnimationListener(toState));
+ }
+
+ /**
* Sets the animation as the current state animation, i.e., canceled when
* starting another animation and may block some launcher interactions while running.
*
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 8616881..30f8fb0 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -27,12 +27,11 @@
public static final int NORMAL_STATE_ORDINAL = 0;
public static final int SPRING_LOADED_STATE_ORDINAL = 1;
public static final int OVERVIEW_STATE_ORDINAL = 2;
- public static final int OVERVIEW_PEEK_STATE_ORDINAL = 3;
- public static final int OVERVIEW_MODAL_TASK_STATE_ORDINAL = 4;
- public static final int QUICK_SWITCH_STATE_ORDINAL = 5;
- public static final int ALL_APPS_STATE_ORDINAL = 6;
- public static final int BACKGROUND_APP_STATE_ORDINAL = 7;
- public static final int HINT_STATE_ORDINAL = 8;
+ public static final int OVERVIEW_MODAL_TASK_STATE_ORDINAL = 3;
+ public static final int QUICK_SWITCH_STATE_ORDINAL = 4;
+ public static final int ALL_APPS_STATE_ORDINAL = 5;
+ public static final int BACKGROUND_APP_STATE_ORDINAL = 6;
+ public static final int HINT_STATE_ORDINAL = 7;
public static final String TAPL_EVENTS_TAG = "TaplEvents";
public static final String SEQUENCE_MAIN = "Main";
public static final String SEQUENCE_TIS = "TIS";
@@ -46,8 +45,6 @@
return "SpringLoaded";
case OVERVIEW_STATE_ORDINAL:
return "Overview";
- case OVERVIEW_PEEK_STATE_ORDINAL:
- return "OverviewPeek";
case OVERVIEW_MODAL_TASK_STATE_ORDINAL:
return "OverviewModal";
case QUICK_SWITCH_STATE_ORDINAL:
@@ -98,7 +95,6 @@
public static final String REQUEST_ENABLE_DEBUG_TRACING = "enable-debug-tracing";
public static final String REQUEST_DISABLE_DEBUG_TRACING = "disable-debug-tracing";
- public static final String REQUEST_OVERVIEW_ACTIONS_ENABLED = "overview-actions-enabled";
public static final String REQUEST_OVERVIEW_SHARE_ENABLED = "overview-share-enabled";
public static boolean sDisableSensorRotation;
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index e5c8441..355c949 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -50,7 +50,7 @@
private final ArrayList<DisplayListChangeListener> mListListeners = new ArrayList<>();
private DisplayController(Context context) {
- mDefaultDisplay = new DisplayHolder(context, DEFAULT_DISPLAY);
+ mDefaultDisplay = DisplayHolder.create(context, DEFAULT_DISPLAY);
DisplayManager dm = context.getSystemService(DisplayManager.class);
dm.registerDisplayListener(this, UI_HELPER_EXECUTOR.getHandler());
@@ -58,7 +58,11 @@
@Override
public final void onDisplayAdded(int displayId) {
- DisplayHolder holder = new DisplayHolder(mDefaultDisplay.mDisplayContext, displayId);
+ DisplayHolder holder = DisplayHolder.create(mDefaultDisplay.mDisplayContext, displayId);
+ if (holder == null) {
+ // Display is already removed by the time we dot this.
+ return;
+ }
synchronized (mOtherDisplays) {
mOtherDisplays.put(displayId, holder);
}
@@ -153,12 +157,8 @@
private final ArrayList<DisplayInfoChangeListener> mListeners = new ArrayList<>();
private DisplayController.Info mInfo;
- public DisplayHolder(Context context, int id) {
- DisplayManager dm = context.getSystemService(DisplayManager.class);
- // Use application context to create display context so that it can have its own
- // Resources.
- mDisplayContext = context.getApplicationContext()
- .createDisplayContext(dm.getDisplay(id));
+ private DisplayHolder(Context displayContext) {
+ mDisplayContext = displayContext;
// Note that the Display object must be obtained from DisplayManager which is
// associated to the display context, so the Display is isolated from Activity and
// Application to provide the actual state of device that excludes the additional
@@ -207,6 +207,17 @@
}
}
+ private static DisplayHolder create(Context context, int id) {
+ DisplayManager dm = context.getSystemService(DisplayManager.class);
+ Display display = dm.getDisplay(id);
+ if (display == null) {
+ return null;
+ }
+ // Use application context to create display context so that it can have its own
+ // Resources.
+ Context displayContext = context.getApplicationContext().createDisplayContext(display);
+ return new DisplayHolder(displayContext);
+ }
}
public static class Info {
diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java
index e98af35..d26bb57 100644
--- a/src/com/android/launcher3/util/ItemInfoMatcher.java
+++ b/src/com/android/launcher3/util/ItemInfoMatcher.java
@@ -27,6 +27,7 @@
import com.android.launcher3.shortcuts.ShortcutKey;
import java.util.HashSet;
+import java.util.Set;
/**
* A utility class to check for {@link ItemInfo}
@@ -99,7 +100,7 @@
return (info, cn) -> packageNames.contains(cn.getPackageName()) && info.user.equals(user);
}
- static ItemInfoMatcher ofShortcutKeys(HashSet<ShortcutKey> keys) {
+ static ItemInfoMatcher ofShortcutKeys(Set<ShortcutKey> keys) {
return (info, cn) -> info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
keys.contains(ShortcutKey.fromItemInfo(info));
}
diff --git a/src/com/android/launcher3/util/MultiHashMap.java b/src/com/android/launcher3/util/MultiHashMap.java
deleted file mode 100644
index b7275c1..0000000
--- a/src/com/android/launcher3/util/MultiHashMap.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-package com.android.launcher3.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-
-/**
- * A utility map from keys to an ArrayList of values.
- */
-public class MultiHashMap<K, V> extends HashMap<K, ArrayList<V>> {
-
- public MultiHashMap() { }
-
- public MultiHashMap(int size) {
- super(size);
- }
-
- public void addToList(K key, V value) {
- ArrayList<V> list = get(key);
- if (list == null) {
- list = new ArrayList<>();
- list.add(value);
- put(key, list);
- } else {
- list.add(value);
- }
- }
-
- @Override
- public MultiHashMap<K, V> clone() {
- MultiHashMap<K, V> map = new MultiHashMap<>(size());
- for (Entry<K, ArrayList<V>> entry : entrySet()) {
- map.put(entry.getKey(), new ArrayList<V>(entry.getValue()));
- }
- return map;
- }
-}
diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java
index 6e5e7d9..1b33197 100644
--- a/src/com/android/launcher3/util/OnboardingPrefs.java
+++ b/src/com/android/launcher3/util/OnboardingPrefs.java
@@ -44,7 +44,8 @@
*/
@StringDef(value = {
HOME_BOUNCE_SEEN,
- SHELF_BOUNCE_SEEN
+ SHELF_BOUNCE_SEEN,
+ HOTSEAT_LONGPRESS_TIP_SEEN
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventBoolKey {}
diff --git a/src/com/android/launcher3/util/PersistedItemArray.java b/src/com/android/launcher3/util/PersistedItemArray.java
index ae20638..7ff2abb 100644
--- a/src/com/android/launcher3/util/PersistedItemArray.java
+++ b/src/com/android/launcher3/util/PersistedItemArray.java
@@ -68,8 +68,7 @@
*/
@WorkerThread
public void write(Context context, List<T> items) {
- AtomicFile file = new AtomicFile(context.getFileStreamPath(mFileName));
-
+ AtomicFile file = getFile(context);
FileOutputStream fos;
try {
fos = file.startWrite();
@@ -124,9 +123,7 @@
@WorkerThread
public List<T> read(Context context, ItemFactory<T> factory, LongFunction<UserHandle> userFn) {
List<T> result = new ArrayList<>();
- AtomicFile file = new AtomicFile(context.getFileStreamPath(mFileName));
-
- try (FileInputStream fis = file.openRead()) {
+ try (FileInputStream fis = getFile(context).openRead()) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new InputStreamReader(fis, StandardCharsets.UTF_8));
@@ -167,6 +164,13 @@
}
/**
+ * Returns the underlying file used for persisting data
+ */
+ public AtomicFile getFile(Context context) {
+ return new AtomicFile(context.getFileStreamPath(mFileName));
+ }
+
+ /**
* Interface to create an ItemInfo during parsing
*/
public interface ItemFactory<T extends ItemInfo> {
diff --git a/src/com/android/launcher3/views/ArrowTipView.java b/src/com/android/launcher3/views/ArrowTipView.java
index b4a6b14..1f12a2f 100644
--- a/src/com/android/launcher3/views/ArrowTipView.java
+++ b/src/com/android/launcher3/views/ArrowTipView.java
@@ -87,10 +87,6 @@
}
@Override
- public void logActionCommand(int command) {
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_ON_BOARD_POPUP) != 0;
}
diff --git a/src/com/android/launcher3/views/FloatingSurfaceView.java b/src/com/android/launcher3/views/FloatingSurfaceView.java
index 9582232..011f6de 100644
--- a/src/com/android/launcher3/views/FloatingSurfaceView.java
+++ b/src/com/android/launcher3/views/FloatingSurfaceView.java
@@ -122,9 +122,6 @@
}
@Override
- public void logActionCommand(int command) { }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_ICON_SURFACE) != 0;
}
diff --git a/src/com/android/launcher3/views/HeroSearchResultView.java b/src/com/android/launcher3/views/HeroSearchResultView.java
index c2a02bc..761ef0d 100644
--- a/src/com/android/launcher3/views/HeroSearchResultView.java
+++ b/src/com/android/launcher3/views/HeroSearchResultView.java
@@ -30,25 +30,27 @@
import com.android.launcher3.DropTarget;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
-import com.android.launcher3.allapps.AlphabeticalAppsList;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.graphics.DragPreviewProvider;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
import com.android.launcher3.touch.ItemLongClickListener;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
-import java.util.ArrayList;
import java.util.List;
/**
* A view representing a high confidence app search result that includes shortcuts
*/
-public class HeroSearchResultView extends LinearLayout implements DragSource {
+public class HeroSearchResultView extends LinearLayout implements DragSource,
+ AllAppsSearchBarController.PayloadResultHandler<List<ItemInfoWithIcon>> {
+ public static final int MAX_SHORTCUTS_COUNT = 2;
BubbleTextView mBubbleTextView;
View mIconView;
BubbleTextView[] mDeepShortcutTextViews = new BubbleTextView[2];
@@ -96,18 +98,18 @@
/**
* Apply {@link ItemInfo} for appIcon and shortcut Icons
*/
- public void prepareUsingAdapterItem(AlphabeticalAppsList.HeroAppAdapterItem adapterItem) {
+ @Override
+ public void applyAdapterInfo(AdapterItemWithPayload<List<ItemInfoWithIcon>> adapterItem) {
mBubbleTextView.applyFromApplicationInfo(adapterItem.appInfo);
mIconView.setBackground(mBubbleTextView.getIcon());
mIconView.setTag(adapterItem.appInfo);
- List<WorkspaceItemInfo> shorcutInfos = adapterItem.getShortcutInfos();
+ List<ItemInfoWithIcon> shorcutInfos = adapterItem.getPayload();
for (int i = 0; i < mDeepShortcutTextViews.length; i++) {
mDeepShortcutTextViews[i].setVisibility(shorcutInfos.size() > i ? VISIBLE : GONE);
if (i < shorcutInfos.size()) {
- mDeepShortcutTextViews[i].applyFromWorkspaceItem(shorcutInfos.get(i));
+ mDeepShortcutTextViews[i].applyFromItemInfoWithIcon(shorcutInfos.get(i));
}
}
-
}
@Override
@@ -116,17 +118,10 @@
mBubbleTextView.setIconVisible(true);
}
- @Override
- public void fillInLogContainerData(ItemInfo childInfo, LauncherLogProto.Target child,
- ArrayList<LauncherLogProto.Target> parents) {
-
- }
-
private void setWillDrawIcon(boolean willDraw) {
mIconView.setVisibility(willDraw ? View.VISIBLE : View.INVISIBLE);
}
-
/**
* Drag and drop handler for popup items in Launcher activity
*/
diff --git a/src/com/android/launcher3/views/ListenerView.java b/src/com/android/launcher3/views/ListenerView.java
index 3ef778b..6e3f0ce 100644
--- a/src/com/android/launcher3/views/ListenerView.java
+++ b/src/com/android/launcher3/views/ListenerView.java
@@ -85,11 +85,6 @@
}
@Override
- public void logActionCommand(int command) {
- // Users do not interact with FloatingIconView, so there is nothing to log here.
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_LISTENER) != 0;
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index 9ad2331..3ec20d5 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -108,11 +108,6 @@
}
@Override
- public void logActionCommand(int command) {
- // TODO:
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_OPTIONS_POPUP) != 0;
}
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 7f0765b..77cec80 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -32,6 +32,7 @@
import com.android.launcher3.Insettable;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
import com.android.launcher3.uioverrides.WallpaperColorInfo.OnChangeListener;
import com.android.launcher3.util.Themes;
@@ -41,6 +42,7 @@
*/
public class ScrimView<T extends Launcher> extends View implements Insettable, OnChangeListener {
+ private static final float SCRIM_ALPHA = .75f;
protected final T mLauncher;
private final WallpaperColorInfo mWallpaperColorInfo;
protected final int mEndScrim;
@@ -59,7 +61,11 @@
super(context, attrs);
mLauncher = Launcher.cast(Launcher.getLauncher(context));
mWallpaperColorInfo = WallpaperColorInfo.INSTANCE.get(context);
- mEndScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
+ int endScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
+ endScrim = ColorUtils.setAlphaComponent(endScrim, (int) (255 * SCRIM_ALPHA));
+ }
+ mEndScrim = endScrim;
mIsScrimDark = ColorUtils.calculateLuminance(mEndScrim) < 0.5f;
mMaxScrimAlpha = 0.7f;
diff --git a/src/com/android/launcher3/views/SearchResultPlayItem.java b/src/com/android/launcher3/views/SearchResultPlayItem.java
new file mode 100644
index 0000000..19a4c5d
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchResultPlayItem.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+package com.android.launcher3.views;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsGridAdapter.AdapterItemWithPayload;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * A View representing a PlayStore item.
+ */
+public class SearchResultPlayItem extends LinearLayout implements
+ AllAppsSearchBarController.PayloadResultHandler<Bundle> {
+ private final DeviceProfile mDeviceProfile;
+ private View mIconView;
+ private TextView mTitleView;
+ private TextView[] mDetailViews = new TextView[3];
+ private Button mPreviewButton;
+ private String mPackageName;
+ private boolean mIsInstantGame;
+
+ public SearchResultPlayItem(Context context) {
+ this(context, null, 0);
+ }
+
+ public SearchResultPlayItem(Context context,
+ @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public SearchResultPlayItem(Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mDeviceProfile = Launcher.getLauncher(getContext()).getDeviceProfile();
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mIconView = findViewById(R.id.icon);
+ mTitleView = findViewById(R.id.title_view);
+ mPreviewButton = findViewById(R.id.try_button);
+ mPreviewButton.setOnClickListener(view -> launchInstantGame());
+ mDetailViews[0] = findViewById(R.id.detail_0);
+ mDetailViews[1] = findViewById(R.id.detail_1);
+ mDetailViews[2] = findViewById(R.id.detail_2);
+
+ ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
+ iconParams.height = mDeviceProfile.allAppsIconSizePx;
+ iconParams.width = mDeviceProfile.allAppsIconSizePx;
+ setOnClickListener(view -> handleSelection());
+
+ }
+
+ @Override
+ public void applyAdapterInfo(AdapterItemWithPayload<Bundle> adapterItemWithPayload) {
+ Bundle bundle = adapterItemWithPayload.getPayload();
+ adapterItemWithPayload.setSelectionHandler(this::handleSelection);
+ if (bundle.getString("package", "").equals(mPackageName)) {
+ return;
+ }
+ mIsInstantGame = bundle.getBoolean("instant_game", false);
+ mPackageName = bundle.getString("package");
+ mPreviewButton.setVisibility(mIsInstantGame ? VISIBLE : GONE);
+ mTitleView.setText(bundle.getString("title"));
+// TODO: Should use a generic type to get values b/165320033
+ showIfNecessary(mDetailViews[0], bundle.getString("price"));
+ showIfNecessary(mDetailViews[1], bundle.getString("rating"));
+ showIfNecessary(mDetailViews[2], bundle.getString("category"));
+
+ mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
+ UI_HELPER_EXECUTOR.execute(() -> {
+ try {
+// TODO: Handle caching
+ URL url = new URL(bundle.getString("icon_url"));
+ Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(),
+ Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
+ mDeviceProfile.allAppsIconSizePx, false));
+ mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ }
+
+ private void showIfNecessary(TextView textView, @Nullable String string) {
+ if (string == null || string.isEmpty()) {
+ textView.setVisibility(GONE);
+ } else {
+ textView.setText(string);
+ textView.setVisibility(VISIBLE);
+ }
+ }
+
+ private void handleSelection() {
+ if (mPackageName == null) return;
+ Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(
+ "https://play.google.com/store/apps/details?id="
+ + mPackageName));
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(i);
+ }
+
+ private void launchInstantGame() {
+ if (!mIsInstantGame) return;
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ String referrer = "Pixel_Launcher";
+ String id = mPackageName;
+ String deepLinkUrl = "market://details?id=" + id + "&launch=true&referrer=" + referrer;
+ intent.setPackage("com.android.vending");
+ intent.setData(Uri.parse(deepLinkUrl));
+ intent.putExtra("overlay", true);
+ intent.putExtra("callerId", getContext().getPackageName());
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(intent);
+ }
+}
diff --git a/src/com/android/launcher3/views/SearchSectionHeaderView.java b/src/com/android/launcher3/views/SearchSectionHeaderView.java
new file mode 100644
index 0000000..d439ee3
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchSectionHeaderView.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+package com.android.launcher3.views;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+
+/**
+ * Header text view that shows a title for a given section in All apps search
+ */
+public class SearchSectionHeaderView extends TextView implements
+ AllAppsSearchBarController.PayloadResultHandler<String> {
+ public SearchSectionHeaderView(Context context) {
+ super(context);
+ }
+
+ public SearchSectionHeaderView(Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SearchSectionHeaderView(Context context, @Nullable AttributeSet attrs, int styleAttr) {
+ super(context, attrs, styleAttr);
+ }
+
+ @Override
+ public void applyAdapterInfo(AllAppsGridAdapter.AdapterItemWithPayload<String> adapterItem) {
+ String title = adapterItem.getPayload();
+ if (title == null || !title.isEmpty()) {
+ setText(title);
+ setVisibility(VISIBLE);
+ } else {
+ setVisibility(INVISIBLE);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/SearchSettingsRowView.java b/src/com/android/launcher3/views/SearchSettingsRowView.java
new file mode 100644
index 0000000..08c78ff
--- /dev/null
+++ b/src/com/android/launcher3/views/SearchSettingsRowView.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+package com.android.launcher3.views;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.search.AllAppsSearchBarController;
+
+import java.util.ArrayList;
+
+/**
+ * A row of tappable TextViews with a breadcrumb for settings search.
+ */
+public class SearchSettingsRowView extends LinearLayout implements
+ View.OnClickListener, AllAppsSearchBarController.PayloadResultHandler<Bundle> {
+
+ private TextView mTitleView;
+ private TextView mDescriptionView;
+ private TextView mBreadcrumbsView;
+ private Intent mIntent;
+
+ public SearchSettingsRowView(@NonNull Context context) {
+ super(context);
+ }
+
+ public SearchSettingsRowView(@NonNull Context context,
+ @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SearchSettingsRowView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mTitleView = findViewById(R.id.title);
+ mDescriptionView = findViewById(R.id.description);
+ mBreadcrumbsView = findViewById(R.id.breadcrumbs);
+ setOnClickListener(this);
+ }
+
+ @Override
+ public void applyAdapterInfo(
+ AllAppsGridAdapter.AdapterItemWithPayload<Bundle> adapterItemWithPayload) {
+ Bundle bundle = adapterItemWithPayload.getPayload();
+ mIntent = bundle.getParcelable("intent");
+ showIfAvailable(mTitleView, bundle.getString("title"));
+ showIfAvailable(mDescriptionView, bundle.getString("description"));
+ ArrayList<String> breadcrumbs = bundle.getStringArrayList("breadcrumbs");
+ //TODO: implement RTL friendly breadcrumbs view
+ showIfAvailable(mBreadcrumbsView, breadcrumbs != null
+ ? String.join(" > ", breadcrumbs) : null);
+ adapterItemWithPayload.setSelectionHandler(() -> onClick(this));
+ }
+
+ private void showIfAvailable(TextView view, @Nullable String string) {
+ if (TextUtils.isEmpty(string)) {
+ view.setVisibility(GONE);
+ } else {
+ view.setVisibility(VISIBLE);
+ view.setText(string);
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mIntent == null) return;
+ // TODO: create ItemInfo object and then use it to call startActivityForResult for proper
+ // WW logging
+ Launcher launcher = Launcher.getLauncher(view.getContext());
+ launcher.startActivityForResult(mIntent, 0);
+ }
+}
diff --git a/src/com/android/launcher3/views/Snackbar.java b/src/com/android/launcher3/views/Snackbar.java
index 513ce59..49fcd2e 100644
--- a/src/com/android/launcher3/views/Snackbar.java
+++ b/src/com/android/launcher3/views/Snackbar.java
@@ -167,11 +167,6 @@
}
@Override
- public void logActionCommand(int command) {
- // TODO
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_SNACKBAR) != 0;
}
diff --git a/src/com/android/launcher3/views/WorkEduView.java b/src/com/android/launcher3/views/WorkEduView.java
index d35a38f..d6737db 100644
--- a/src/com/android/launcher3/views/WorkEduView.java
+++ b/src/com/android/launcher3/views/WorkEduView.java
@@ -38,7 +38,6 @@
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.statemanager.StateManager.StateListener;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
/**
* On boarding flow for users right after setting up work profile
@@ -89,16 +88,6 @@
}
@Override
- public void logActionCommand(int command) {
- // Since this is on-boarding popup, it is not a user controlled action.
- }
-
- @Override
- public int getLogContainerType() {
- return LauncherLogProto.ContainerType.TIP;
- }
-
- @Override
protected boolean isOfType(int type) {
return (type & TYPE_ON_BOARD_POPUP) != 0;
}
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 3e5113a..01af96c 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -16,7 +16,6 @@
package com.android.launcher3.widget;
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
-import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
import android.content.Context;
import android.graphics.Point;
@@ -31,20 +30,15 @@
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragOptions;
-import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
-import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.AbstractSlideInView;
-import java.util.ArrayList;
-
/**
* Base class for various widgets popup
*/
@@ -149,28 +143,6 @@
isSheetDark ? SystemUiController.FLAG_DARK_NAV : SystemUiController.FLAG_LIGHT_NAV);
}
- @Override
- public void fillInLogContainerData(ItemInfo childInfo, Target child,
- ArrayList<Target> parents) {
- Target target = newContainerTarget(ContainerType.WIDGETS);
- target.cardinality = getElementsRowCount();
- parents.add(target);
- }
-
- @Override
- public final void logActionCommand(int command) {
- Target target = newContainerTarget(getLogContainerType());
- target.cardinality = getElementsRowCount();
- mLauncher.getUserEventDispatcher().logActionCommand(command, target);
- }
-
- @Override
- public int getLogContainerType() {
- return ContainerType.WIDGETS;
- }
-
- protected abstract int getElementsRowCount();
-
protected SystemUiController getSystemUiController() {
return mLauncher.getSystemUiController();
}
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 30be7a6..3585a18 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -180,11 +180,6 @@
}
@Override
- protected int getElementsRowCount() {
- return 1;
- }
-
- @Override
protected Pair<View, String> getAccessibilityTarget() {
return Pair.create(findViewById(R.id.title), getContext().getString(
mIsOpen ? R.string.widgets_list : R.string.widgets_list_closed));
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index 68a3ec5..4c8c339 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -243,11 +243,6 @@
}
@Override
- protected int getElementsRowCount() {
- return mAdapter.getItemCount();
- }
-
- @Override
public void addHintCloseAnim(
float distanceToMove, Interpolator interpolator, PendingAnimation target) {
target.setFloat(mRecyclerView, VIEW_TRANSLATE_Y, -distanceToMove, interpolator);
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index a45521d..5bf9690 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -23,9 +23,12 @@
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
-import com.android.launcher3.icons.IconCache;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.Adapter;
+
import com.android.launcher3.R;
import com.android.launcher3.WidgetPreviewLoader;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.util.LabelComparator;
@@ -34,9 +37,6 @@
import java.util.Comparator;
import java.util.List;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.Adapter;
-
/**
* List view adapter for the widget tray.
*
@@ -128,7 +128,7 @@
int childCount = row.getChildCount();
if (expectedChildCount > childCount) {
- for (int i = childCount ; i < expectedChildCount; i++) {
+ for (int i = childCount; i < expectedChildCount; i++) {
if ((i & 1) == 1) {
// Add a divider for odd index
mLayoutInflater.inflate(R.layout.widget_list_divider, row);
@@ -144,24 +144,24 @@
}
}
} else if (expectedChildCount < childCount) {
- for (int i = expectedChildCount ; i < childCount; i++) {
+ for (int i = expectedChildCount; i < childCount; i++) {
row.getChildAt(i).setVisibility(View.GONE);
}
}
// Bind the views in the application info section.
- holder.title.applyFromPackageItemInfo(entry.pkgItem);
+ holder.title.applyFromItemInfoWithIcon(entry.pkgItem);
// Bind the view in the widget horizontal tray region.
- for (int i=0; i < infoList.size(); i++) {
- WidgetCell widget = (WidgetCell) row.getChildAt(2*i);
+ for (int i = 0; i < infoList.size(); i++) {
+ WidgetCell widget = (WidgetCell) row.getChildAt(2 * i);
widget.applyFromCellItem(infoList.get(i), mWidgetPreviewLoader);
widget.setApplyBitmapDeferred(mApplyBitmapDeferred);
widget.ensurePreview();
widget.setVisibility(View.VISIBLE);
if (i > 0) {
- row.getChildAt(2*i - 1).setVisibility(View.VISIBLE);
+ row.getChildAt(2 * i - 1).setVisibility(View.VISIBLE);
}
}
}
@@ -185,7 +185,7 @@
@Override
public void onViewRecycled(WidgetsRowViewHolder holder) {
int total = holder.cellContainer.getChildCount();
- for (int i = 0; i < total; i+=2) {
+ for (int i = 0; i < total; i += 2) {
WidgetCell widget = (WidgetCell) holder.cellContainer.getChildAt(i);
widget.clear();
}
diff --git a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
index c57f07d..be20e2d 100644
--- a/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
+++ b/src_plugins/com/android/systemui/plugins/AllAppsSearchPlugin.java
@@ -16,35 +16,28 @@
package com.android.systemui.plugins;
-import android.app.Activity;
-import android.view.ViewGroup;
-import android.widget.EditText;
+import android.os.Bundle;
import com.android.systemui.plugins.annotations.ProvidesInterface;
+import java.util.List;
+import java.util.function.Consumer;
+
/**
- * Implement this plugin interface to replace the all apps recycler view of the all apps drawer.
+ * Implement this plugin interface to fetch search result data from the plugin side.
*/
@ProvidesInterface(action = AllAppsSearchPlugin.ACTION, version = AllAppsSearchPlugin.VERSION)
public interface AllAppsSearchPlugin extends Plugin {
String ACTION = "com.android.systemui.action.PLUGIN_ALL_APPS_SEARCH_ACTIONS";
- int VERSION = 3;
-
- /** Following are the order that these methods should be called. */
- void setup(ViewGroup parent, Activity activity, float allAppsContainerHeight);
+ int VERSION = 4;
/**
- * When drag starts, pass window inset related fields and the progress to indicate
- * whether user is swiping down or swiping up
+ * Send signal when user starts typing.
*/
- void onDragStart(float progress);
+ void startedTyping();
- /** progress is between [0, 1] 1: down, 0: up */
- void setProgress(float progress);
-
- /** Called when container animation stops, so that plugin can perform cleanups */
- void onAnimationEnd(float progress);
-
- /** pass over the search box object */
- void setEditText(EditText editText);
+ /**
+ * Send over the query and get the search results.
+ */
+ void performSearch(String query, Consumer<List<Bundle>> results);
}
diff --git a/src_plugins/com/android/systemui/plugins/UserEventPlugin.java b/src_plugins/com/android/systemui/plugins/UserEventPlugin.java
deleted file mode 100644
index 0e3664a..0000000
--- a/src_plugins/com/android/systemui/plugins/UserEventPlugin.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.plugins;
-
-import com.android.systemui.plugins.annotations.ProvidesInterface;
-
-/**
- * Implement this plugin interface to access user event log on the device for prototype purpose.
- * NOTE: plugin is for internal prototype only and is not visible in production environment.
- */
-@ProvidesInterface(action = UserEventPlugin.ACTION, version = UserEventPlugin.VERSION)
-public interface UserEventPlugin extends Plugin {
- String ACTION = "com.android.launcher3.action.PLUGIN_USER_EVENT_LOG";
- int VERSION = 1;
-
- /**
- * Callback to be triggered whenever an user event occurs.
- */
- void onUserEvent(Object event);
-}
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java b/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
index dcb4636..269af7b 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/LoaderResults.java
@@ -21,7 +21,6 @@
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.Callbacks;
import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.widget.WidgetListRowEntry;
import java.util.ArrayList;
@@ -34,12 +33,7 @@
public LoaderResults(LauncherAppState app, BgDataModel dataModel,
AllAppsList allAppsList, Callbacks[] callbacks) {
- this(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
- }
-
- public LoaderResults(LauncherAppState app, BgDataModel dataModel,
- AllAppsList allAppsList, Callbacks[] callbacks, LooperExecutor executor) {
- super(app, dataModel, allAppsList, callbacks, executor);
+ super(app, dataModel, allAppsList, callbacks, MAIN_EXECUTOR);
}
@Override
diff --git a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
index 9d87788..34ebbac 100644
--- a/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
+++ b/src_shortcuts_overrides/com/android/launcher3/model/WidgetsModel.java
@@ -26,7 +26,6 @@
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
-import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.widget.WidgetItemComparator;
@@ -36,11 +35,12 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* Widgets data model that is used by the adapters of the widget views and controllers.
@@ -51,14 +51,13 @@
// True is the widget support is disabled.
public static final boolean GO_DISABLE_WIDGETS = false;
+ public static final boolean GO_DISABLE_NOTIFICATION_DOTS = false;
private static final String TAG = "WidgetsModel";
private static final boolean DEBUG = false;
/* Map of widgets and shortcuts that are tracked per package. */
- private final MultiHashMap<PackageItemInfo, WidgetItem> mWidgetsList = new MultiHashMap<>();
-
- private AppFilter mAppFilter;
+ private final Map<PackageItemInfo, List<WidgetItem>> mWidgetsList = new HashMap<>();
/**
* Returns a list of {@link WidgetListRowEntry}. All {@link WidgetItem} in a single row
@@ -73,8 +72,9 @@
AlphabeticIndexCompat indexer = new AlphabeticIndexCompat(context);
WidgetItemComparator widgetComparator = new WidgetItemComparator();
- for (Map.Entry<PackageItemInfo, ArrayList<WidgetItem>> entry : mWidgetsList.entrySet()) {
- WidgetListRowEntry row = new WidgetListRowEntry(entry.getKey(), entry.getValue());
+ for (Map.Entry<PackageItemInfo, List<WidgetItem>> entry : mWidgetsList.entrySet()) {
+ WidgetListRowEntry row = new WidgetListRowEntry(
+ entry.getKey(), new ArrayList<>(entry.getValue()));
row.titleSectionName = (row.pkgItem.title == null) ? "" :
indexer.computeSectionName(row.pkgItem.title);
Collections.sort(row.widgets, widgetComparator);
@@ -145,77 +145,42 @@
if (packageUser == null) {
mWidgetsList.clear();
} else {
- // Only clear the widgets for the given package/user.
- PackageItemInfo packageItem = null;
- for (PackageItemInfo item : mWidgetsList.keySet()) {
- if (item.packageName.equals(packageUser.mPackageName)) {
- packageItem = item;
- break;
- }
- }
+ PackageItemInfo packageItem = mWidgetsList.keySet()
+ .stream()
+ .filter(item -> item.packageName.equals(packageUser.mPackageName))
+ .findFirst()
+ .orElse(null);
if (packageItem != null) {
// We want to preserve the user that was on the packageItem previously,
// so add it to tmpPackageItemInfos here to avoid creating a new entry.
tmpPackageItemInfos.put(packageItem.packageName, packageItem);
- Iterator<WidgetItem> widgetItemIterator = mWidgetsList.get(packageItem).iterator();
- while (widgetItemIterator.hasNext()) {
- WidgetItem nextWidget = widgetItemIterator.next();
- if (nextWidget.componentName.getPackageName().equals(packageUser.mPackageName)
- && nextWidget.user.equals(packageUser.mUser)) {
- widgetItemIterator.remove();
- }
- }
+ // Add the widgets for other users in the rawList as it only contains widgets for
+ // packageUser
+ List<WidgetItem> otherUserItems = mWidgetsList.remove(packageItem);
+ otherUserItems.removeIf(w -> w.user.equals(packageUser.mUser));
+ rawWidgetsShortcuts.addAll(otherUserItems);
}
}
- InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
UserHandle myUser = Process.myUserHandle();
// add and update.
- for (WidgetItem item : rawWidgetsShortcuts) {
- if (item.widgetInfo != null) {
- if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) {
- // Widget is hidden from picker
- continue;
- }
-
- // Ensure that all widgets we show can be added on a workspace of this size
- int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX);
- int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY);
- if (minSpanX > idp.numColumns || minSpanY > idp.numRows) {
- if (DEBUG) {
- Log.d(TAG, String.format(
- "Widget %s : (%d X %d) can't fit on this device",
- item.componentName, minSpanX, minSpanY));
+ mWidgetsList.putAll(rawWidgetsShortcuts.stream()
+ .filter(new WidgetValidityCheck(app))
+ .collect(Collectors.groupingBy(item -> {
+ String packageName = item.componentName.getPackageName();
+ PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName);
+ if (pInfo == null) {
+ pInfo = new PackageItemInfo(packageName);
+ pInfo.user = item.user;
+ tmpPackageItemInfos.put(packageName, pInfo);
+ } else if (!myUser.equals(pInfo.user)) {
+ // Keep updating the user, until we get the primary user.
+ pInfo.user = item.user;
}
- continue;
- }
- }
-
- if (mAppFilter == null) {
- mAppFilter = AppFilter.newInstance(app.getContext());
- }
- if (!mAppFilter.shouldShowApp(item.componentName)) {
- if (DEBUG) {
- Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
- item.componentName));
- }
- continue;
- }
-
- String packageName = item.componentName.getPackageName();
- PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName);
- if (pInfo == null) {
- pInfo = new PackageItemInfo(packageName);
- pInfo.user = item.user;
- tmpPackageItemInfos.put(packageName, pInfo);
- } else if (!myUser.equals(pInfo.user)) {
- // Keep updating the user, until we get the primary user.
- pInfo.user = item.user;
- }
- mWidgetsList.addToList(pInfo, item);
- }
+ return pInfo;
+ })));
// Update each package entry
IconCache iconCache = app.getIconCache();
@@ -226,9 +191,9 @@
public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
LauncherAppState app) {
- for (Entry<PackageItemInfo, ArrayList<WidgetItem>> entry : mWidgetsList.entrySet()) {
+ for (Entry<PackageItemInfo, List<WidgetItem>> entry : mWidgetsList.entrySet()) {
if (packageNames.contains(entry.getKey().packageName)) {
- ArrayList<WidgetItem> items = entry.getValue();
+ List<WidgetItem> items = entry.getValue();
int count = items.size();
for (int i = 0; i < count; i++) {
WidgetItem item = items.get(i);
@@ -248,7 +213,7 @@
public WidgetItem getWidgetProviderInfoByProviderName(
ComponentName providerName) {
- ArrayList<WidgetItem> widgetsList = mWidgetsList.get(
+ List<WidgetItem> widgetsList = mWidgetsList.get(
new PackageItemInfo(providerName.getPackageName()));
if (widgetsList == null) {
return null;
@@ -261,4 +226,46 @@
}
return null;
}
+
+ private static class WidgetValidityCheck implements Predicate<WidgetItem> {
+
+ private final InvariantDeviceProfile mIdp;
+ private final AppFilter mAppFilter;
+
+ WidgetValidityCheck(LauncherAppState app) {
+ mIdp = app.getInvariantDeviceProfile();
+ mAppFilter = AppFilter.newInstance(app.getContext());
+ }
+
+ @Override
+ public boolean test(WidgetItem item) {
+ if (item.widgetInfo != null) {
+ if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) {
+ // Widget is hidden from picker
+ return false;
+ }
+
+ // Ensure that all widgets we show can be added on a workspace of this size
+ int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX);
+ int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY);
+ if (minSpanX > mIdp.numColumns || minSpanY > mIdp.numRows) {
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "Widget %s : (%d X %d) can't fit on this device",
+ item.componentName, minSpanX, minSpanY));
+ }
+ return false;
+ }
+ }
+ if (!mAppFilter.shouldShowApp(item.componentName)) {
+ if (DEBUG) {
+ Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
+ item.componentName));
+ }
+ return false;
+ }
+
+ return true;
+ }
+ }
}
\ No newline at end of file
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
index 7a6332c..d102bcc 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -38,10 +38,6 @@
return new OverviewState(id);
}
- public static OverviewState newPeekState(int id) {
- return new OverviewState(id);
- }
-
public static OverviewState newSwitchState(int id) {
return new OverviewState(id);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 92ab9b8..80adf05 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1304,17 +1304,8 @@
if (getNavigationModel() == NavigationModel.TWO_BUTTON) {
return true;
}
- // Overview actions hide all apps
- if (overviewActionsEnabled()) {
- return false;
- }
- // ...otherwise there should be all apps
- return true;
- }
-
- private boolean overviewActionsEnabled() {
- return getTestInfo(TestProtocol.REQUEST_OVERVIEW_ACTIONS_ENABLED).getBoolean(
- TestProtocol.TEST_INFO_RESPONSE_FIELD);
+ // ...otherwise there are overview actions, which hide all apps
+ return false;
}
boolean overviewShareEnabled() {