diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index 19a16e341a..ff5bf0d1e5 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -45,6 +45,9 @@ + + + + android:name="com.android.launcher3.SessionCommitReceiver" > - + @@ -117,7 +117,6 @@ android:name="com.android.launcher3.notification.NotificationListener" android:label="@string/notification_dots_service_title" android:enabled="@bool/notification_dots_enabled" - android:exported="true" android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"> @@ -131,7 +130,6 @@ android:theme="@style/AppItemActivityTheme" android:excludeFromRecents="true" android:autoRemoveFromRecents="true" - android:exported="true" android:label="@string/action_add_to_workspace" > @@ -167,7 +165,6 @@ android:name="com.android.launcher3.settings.SettingsActivity" android:label="@string/settings_button_text" android:theme="@style/HomeSettingsTheme" - android:exported="true" android:autoRemoveFromRecents="true"> @@ -190,7 +187,6 @@ android:name="com.android.launcher3.secondarydisplay.SecondaryDisplayLauncher" android:theme="@style/AppTheme" android:launchMode="singleTop" - android:exported="true" android:enabled="true"> diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8e01f82018..b031ffbee4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -53,7 +53,6 @@ android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" - android:exported="true" android:enabled="true"> diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java index aa3710b6d9..e649ce1de4 100644 --- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java +++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java @@ -164,12 +164,6 @@ public class DebugTestInformationHandler extends TestInformationHandler { } case TestProtocol.REQUEST_GET_TEST_EVENTS: { - if (sEvents == null) { - // sEvents can be null if Launcher died and restarted after - // REQUEST_START_EVENT_LOGGING. - return response; - } - synchronized (sEvents) { response.putStringArrayList( TestProtocol.TEST_INFO_RESPONSE_FIELD, new ArrayList<>(sEvents)); diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto index cd229ae015..561196941c 100644 --- a/protos/launcher_atom.proto +++ b/protos/launcher_atom.proto @@ -131,7 +131,6 @@ message Application { // Legacy shortcuts and shortcuts handled by ShortcutManager message Shortcut { optional string shortcut_name = 1; - optional string shortcut_id = 2; } // AppWidgets handled by AppWidgetManager diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml index 53910e344b..60afddb0a8 100644 --- a/quickstep/AndroidManifest-launcher.xml +++ b/quickstep/AndroidManifest-launcher.xml @@ -53,7 +53,6 @@ android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" - android:exported="true" android:enabled="true"> diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 4e7c3fa75b..e49f2ecdc0 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -17,91 +17,97 @@ ** limitations under the License. */ --> + - - - - - - + + + - + - + - + + android:excludeFromRecents="true" + android:launchMode="singleTask" + android:clearTaskOnLaunch="true" + android:stateNotNeeded="true" + android:theme="@style/LauncherTheme" + android:screenOrientation="unspecified" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" + android:resizeableActivity="true" + android:resumeWhilePausing="true" + android:taskAffinity="" /> - + - + - - + + - + - + - + - - + + + android:permission="${packageName}.permission.HOTSEAT_EDU"> diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java index 8cabe3d80b..4c7943b10b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java @@ -16,12 +16,6 @@ package com.android.launcher3.appprediction; import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_LEFT; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_QUICKSWITCH_RIGHT; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import android.annotation.TargetApi; @@ -37,38 +31,29 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; -import android.os.Process; -import android.os.SystemClock; import android.os.UserHandle; -import android.text.TextUtils; import android.util.Log; -import androidx.annotation.AnyThread; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.annotation.WorkerThread; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; -import com.android.launcher3.logger.LauncherAtom; -import com.android.launcher3.logger.LauncherAtom.ContainerInfo; -import com.android.launcher3.logger.LauncherAtom.FolderContainer; -import com.android.launcher3.logger.LauncherAtom.HotseatContainer; -import com.android.launcher3.logger.LauncherAtom.WorkspaceContainer; -import com.android.launcher3.logging.StatsLogManager.EventEnum; import com.android.launcher3.model.AppLaunchTracker; -import com.android.launcher3.pm.UserCache; -import com.android.quickstep.logging.StatsLogCompatManager; -import com.android.quickstep.logging.StatsLogCompatManager.StatsLogConsumer; +import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; +import com.android.systemui.plugins.AppLaunchEventsPlugin; +import com.android.systemui.plugins.PluginListener; -import java.util.Locale; -import java.util.function.Predicate; +import java.util.ArrayList; +import java.util.List; /** * Subclass of app tracker which publishes the data to the prediction engine and gets back results. */ @TargetApi(Build.VERSION_CODES.Q) -public class PredictionAppTracker extends AppLaunchTracker implements StatsLogConsumer { +public class PredictionAppTracker extends AppLaunchTracker + implements PluginListener { private static final String TAG = "PredictionAppTracker"; private static final boolean DBG = false; @@ -80,9 +65,11 @@ public class PredictionAppTracker extends AppLaunchTracker implements StatsLogCo protected final Context mContext; private final Handler mMessageHandler; + private final List mAppLaunchEventsPluginsList; // Accessed only on worker thread private AppPredictor mHomeAppPredictor; + private AppPredictor mRecentsOverviewPredictor; public PredictionAppTracker(Context context) { mContext = context; @@ -90,6 +77,10 @@ public class PredictionAppTracker extends AppLaunchTracker implements StatsLogCo InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged); mMessageHandler.sendEmptyMessage(MSG_INIT); + + mAppLaunchEventsPluginsList = new ArrayList<>(); + PluginManagerWrapper.INSTANCE.get(context) + .addPluginListener(this, AppLaunchEventsPlugin.class, true); } @UiThread @@ -106,7 +97,10 @@ public class PredictionAppTracker extends AppLaunchTracker implements StatsLogCo mHomeAppPredictor.destroy(); mHomeAppPredictor = null; } - StatsLogCompatManager.LOGS_CONSUMER.remove(this); + if (mRecentsOverviewPredictor != null) { + mRecentsOverviewPredictor.destroy(); + mRecentsOverviewPredictor = null; + } } @WorkerThread @@ -148,7 +142,7 @@ public class PredictionAppTracker extends AppLaunchTracker implements StatsLogCo // Initialize the clients int count = InvariantDeviceProfile.INSTANCE.get(mContext).numAllAppsColumns; mHomeAppPredictor = createPredictor(Client.HOME, count); - StatsLogCompatManager.LOGS_CONSUMER.add(this); + mRecentsOverviewPredictor = createPredictor(Client.OVERVIEW, count); return true; } case MSG_DESTROY: { @@ -163,7 +157,12 @@ public class PredictionAppTracker extends AppLaunchTracker implements StatsLogCo } case MSG_PREDICT: { if (mHomeAppPredictor != null) { - mHomeAppPredictor.requestPredictionUpdate(); + String client = (String) msg.obj; + if (Client.HOME.id.equals(client)) { + mHomeAppPredictor.requestPredictionUpdate(); + } else { + mRecentsOverviewPredictor.requestPredictionUpdate(); + } } return true; } @@ -180,142 +179,98 @@ public class PredictionAppTracker extends AppLaunchTracker implements StatsLogCo if (DBG) { Log.d(TAG, String.format("Sent immediate message to update %s", client)); } + + // Relay onReturnedToHome to every plugin. + mAppLaunchEventsPluginsList.forEach(AppLaunchEventsPlugin::onReturnedToHome); } - @AnyThread - private void sendEvent(LauncherAtom.ItemInfo atomInfo, int eventId) { - AppTarget target = toAppTarget(atomInfo); - if (target != null) { - AppTargetEvent event = new AppTargetEvent.Builder(target, eventId) - .setLaunchLocation(getContainer(atomInfo)) + @Override + @UiThread + public void onStartShortcut(String packageName, String shortcutId, UserHandle user, + String container) { + // TODO: Use the full shortcut info + AppTarget target = new AppTarget.Builder( + new AppTargetId("shortcut:" + shortcutId), packageName, user) + .setClassName(shortcutId) + .build(); + + sendLaunch(target, container); + + // Relay onStartShortcut info to every connected plugin. + mAppLaunchEventsPluginsList + .forEach(plugin -> plugin.onStartShortcut( + packageName, + shortcutId, + user, + container != null ? container : CONTAINER_DEFAULT) + ); + + } + + @Override + @UiThread + public void onStartApp(ComponentName cn, UserHandle user, String container) { + if (cn != null) { + AppTarget target = new AppTarget.Builder( + new AppTargetId("app:" + cn), cn.getPackageName(), user) + .setClassName(cn.getClassName()) .build(); - Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); + sendLaunch(target, container); + + // Relay onStartApp to every connected plugin. + mAppLaunchEventsPluginsList + .forEach(plugin -> plugin.onStartApp( + cn, + user, + container != null ? container : CONTAINER_DEFAULT) + ); } } @Override - public void consume(EventEnum event, LauncherAtom.ItemInfo atomInfo) { - if (event == LAUNCHER_APP_LAUNCH_TAP - || event == LAUNCHER_TASK_LAUNCH_SWIPE_DOWN - || event == LAUNCHER_TASK_LAUNCH_TAP - || event == LAUNCHER_QUICKSWITCH_RIGHT - || event == LAUNCHER_QUICKSWITCH_LEFT) { - sendEvent(atomInfo, AppTargetEvent.ACTION_LAUNCH); - } else if (event == LAUNCHER_ITEM_DROPPED_ON_DONT_SUGGEST) { - sendEvent(atomInfo, AppTargetEvent.ACTION_DISMISS); - } + @UiThread + public void onDismissApp(ComponentName cn, UserHandle user, String container) { + if (cn == null) return; + AppTarget target = new AppTarget.Builder( + new AppTargetId("app: " + cn), cn.getPackageName(), user) + .setClassName(cn.getClassName()) + .build(); + sendDismiss(target, container); + + // Relay onDismissApp to every connected plugin. + mAppLaunchEventsPluginsList + .forEach(plugin -> plugin.onDismissApp( + cn, + user, + container != null ? container : CONTAINER_DEFAULT) + ); } - @Nullable - private AppTarget toAppTarget(LauncherAtom.ItemInfo info) { - UserHandle userHandle = Process.myUserHandle(); - if (info.getIsWork()) { - userHandle = UserCache.INSTANCE.get(mContext).getUserProfiles().stream() - .filter(((Predicate) userHandle::equals).negate()) - .findAny() - .orElse(null); - } - if (userHandle == null) { - return null; - } - ComponentName cn = null; - String id = null; - - switch (info.getItemCase()) { - case APPLICATION: { - LauncherAtom.Application app = info.getApplication(); - if ((cn = parseNullable(app.getComponentName())) != null) { - id = "app:" + cn.getPackageName(); - } - break; - } - case SHORTCUT: { - LauncherAtom.Shortcut si = info.getShortcut(); - if (!TextUtils.isEmpty(si.getShortcutId()) - && (cn = parseNullable(si.getShortcutName())) != null) { - id = "shortcut:" + si.getShortcutId(); - } - break; - } - case WIDGET: { - LauncherAtom.Widget widget = info.getWidget(); - if ((cn = parseNullable(widget.getComponentName())) != null) { - id = "widget:" + cn.getPackageName(); - } - break; - } - case TASK: { - LauncherAtom.Task task = info.getTask(); - if ((cn = parseNullable(task.getComponentName())) != null) { - id = "app:" + cn.getPackageName(); - } - break; - } - case FOLDER_ICON: { - id = "folder:" + SystemClock.uptimeMillis(); - cn = new ComponentName(mContext.getPackageName(), "#folder"); - } - } - if (id != null && cn != null) { - return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle) - .setClassName(cn.getClassName()) - .build(); - } - return null; + @UiThread + private void sendEvent(AppTarget target, String container, int eventId) { + AppTargetEvent event = new AppTargetEvent.Builder(target, eventId) + .setLaunchLocation(container == null ? CONTAINER_DEFAULT : container) + .build(); + Message.obtain(mMessageHandler, MSG_LAUNCH, event).sendToTarget(); } - private String getContainer(LauncherAtom.ItemInfo info) { - ContainerInfo ci = info.getContainerInfo(); - switch (ci.getContainerCase()) { - case WORKSPACE: { - // In case the item type is not widgets, the spaceX and spanY default to 1. - int spanX = info.getWidget().getSpanX(); - int spanY = info.getWidget().getSpanY(); - return getWorkspaceContainerString(ci.getWorkspace(), spanX, spanY); - } - case HOTSEAT: { - return getHotseatContainerString(ci.getHotseat()); - } - case TASK_SWITCHER_CONTAINER: { - return "task-switcher"; - } - case ALL_APPS_CONTAINER: { - return "all-apps"; - } - case SEARCH_RESULT_CONTAINER: { - return "search-results"; - } - case PREDICTED_HOTSEAT_CONTAINER: { - return "predictions/hotseat"; - } - case PREDICTION_CONTAINER: { - return "predictions"; - } - case FOLDER: { - FolderContainer fc = ci.getFolder(); - switch (fc.getParentContainerCase()) { - case WORKSPACE: - return "folder/" + getWorkspaceContainerString(fc.getWorkspace(), 1, 1); - case HOTSEAT: - return "folder/" + getHotseatContainerString(fc.getHotseat()); - } - return "folder"; - } - } - return ""; + @UiThread + private void sendLaunch(AppTarget target, String container) { + sendEvent(target, container, AppTargetEvent.ACTION_LAUNCH); } - private static String getWorkspaceContainerString(WorkspaceContainer wc, int spanX, int spanY) { - return String.format(Locale.ENGLISH, "workspace/%d/[%d,%d]/[%d,%d]", - wc.getPageIndex(), wc.getGridX(), wc.getGridY(), spanX, spanY); + @UiThread + private void sendDismiss(AppTarget target, String container) { + sendEvent(target, container, AppTargetEvent.ACTION_DISMISS); } - private static String getHotseatContainerString(HotseatContainer hc) { - return String.format(Locale.ENGLISH, "hotseat/%d", hc.getIndex()); + @Override + public void onPluginConnected(AppLaunchEventsPlugin appLaunchEventsPlugin, Context context) { + mAppLaunchEventsPluginsList.add(appLaunchEventsPlugin); } - private static ComponentName parseNullable(String componentNameString) { - return TextUtils.isEmpty(componentNameString) - ? null : ComponentName.unflattenFromString(componentNameString); + @Override + public void onPluginDisconnected(AppLaunchEventsPlugin appLaunchEventsPlugin) { + mAppLaunchEventsPluginsList.remove(appLaunchEventsPlugin); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java index e11c701640..44691d3bb0 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -56,6 +56,7 @@ import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.keyboard.FocusIndicatorHelper; import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper; import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider; +import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; @@ -92,6 +93,9 @@ public class PredictionRowView extends LinearLayout implements private static final Interpolator ALPHA_FACTOR_INTERPOLATOR = (t) -> (t < 0.8f) ? 0 : (t - 0.8f) / 0.2f; + private static final OnClickListener PREDICTION_CLICK_LISTENER = + ItemClickHandler.getInstance(AppLaunchTracker.CONTAINER_PREDICTIONS); + private final Launcher mLauncher; private final PredictionUiStateManager mPredictionUiStateManager; private int mNumPredictedAppsPerRow; @@ -242,7 +246,7 @@ public class PredictionRowView extends LinearLayout implements while (getChildCount() < mNumPredictedAppsPerRow) { BubbleTextView icon = (BubbleTextView) inflater.inflate( R.layout.all_apps_icon, this, false); - icon.setOnClickListener(ItemClickHandler.INSTANCE); + icon.setOnClickListener(PREDICTION_CLICK_LISTENER); icon.setOnLongClickListener(ItemLongClickListener.INSTANCE_ALL_APPS); icon.setLongPressTimeoutFactor(1f); icon.setOnFocusChangeListener(mFocusHelper); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java index 830c1032ba..a0f6b044ba 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java @@ -75,7 +75,8 @@ public class PredictionUiStateManager implements StateListener, // TODO (b/129421797): Update the client constants public enum Client { - HOME("home"); + HOME("home"), + OVERVIEW("overview"); public final String id; @@ -90,9 +91,10 @@ public class PredictionUiStateManager implements StateListener, private final Context mContext; private final DynamicItemCache mDynamicItemCache; - private List mPredictionServicePredictions = Collections.emptyList(); + private final List[] mPredictionServicePredictions; private int mMaxIconsPerRow; + private Client mActiveClient; private AllAppsContainerView mAppsView; @@ -106,10 +108,16 @@ public class PredictionUiStateManager implements StateListener, mDynamicItemCache = new DynamicItemCache(context, this::onAppsUpdated); + mActiveClient = Client.HOME; + InvariantDeviceProfile idp = LauncherAppState.getIDP(context); mMaxIconsPerRow = idp.numColumns; idp.addOnChangeListener(this); + mPredictionServicePredictions = new List[Client.values().length]; + for (int i = 0; i < mPredictionServicePredictions.length; i++) { + mPredictionServicePredictions[i] = Collections.emptyList(); + } mGettingValidPredictionResults = Utilities.getDevicePrefs(context) .getBoolean(LAST_PREDICTION_ENABLED_STATE, true); @@ -122,6 +130,18 @@ public class PredictionUiStateManager implements StateListener, mMaxIconsPerRow = profile.numColumns; } + public Client getClient() { + return mActiveClient; + } + + public void switchClient(Client client) { + if (client == mActiveClient) { + return; + } + mActiveClient = client; + dispatchOnChange(true); + } + public void setTargetAppsView(AllAppsContainerView appsView) { if (mAppsView != null) { mAppsView.getAppsStore().removeUpdateListener(this); @@ -175,8 +195,10 @@ public class PredictionUiStateManager implements StateListener, } private void updatePredictionStateAfterCallback() { - boolean validResults = mPredictionServicePredictions != null - && !mPredictionServicePredictions.isEmpty(); + boolean validResults = false; + for (List l : mPredictionServicePredictions) { + validResults |= l != null && !l.isEmpty(); + } if (validResults != mGettingValidPredictionResults) { mGettingValidPredictionResults = validResults; Utilities.getDevicePrefs(mContext).edit() @@ -188,7 +210,7 @@ public class PredictionUiStateManager implements StateListener, public AppPredictor.Callback appPredictorCallback(Client client) { return targets -> { - mPredictionServicePredictions = targets; + mPredictionServicePredictions[client.ordinal()] = targets; updatePredictionStateAfterCallback(); }; } @@ -216,7 +238,7 @@ public class PredictionUiStateManager implements StateListener, state.apps = new ArrayList<>(); - List appTargets = mPredictionServicePredictions; + List appTargets = mPredictionServicePredictions[mActiveClient.ordinal()]; if (!appTargets.isEmpty()) { for (AppTarget appTarget : appTargets) { ComponentKey key; diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index bdbd1e955d..9a03d92e48 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -34,6 +34,8 @@ import android.os.Bundle; import android.util.Log; import android.view.View; +import androidx.annotation.Nullable; + import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; @@ -127,11 +129,12 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { } @Override - public boolean startActivitySafely(View v, Intent intent, ItemInfo item) { + public boolean startActivitySafely(View v, Intent intent, ItemInfo item, + @Nullable String sourceContainer) { if (mHotseatPredictionController != null) { mHotseatPredictionController.setPauseUIUpdate(true); } - return super.startActivitySafely(v, intent, item); + return super.startActivitySafely(v, intent, item, sourceContainer); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java index 9310685e30..de83caf162 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/AppToOverviewAnimationProvider.java @@ -24,7 +24,6 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MOD import android.animation.Animator; import android.animation.AnimatorSet; -import android.app.ActivityManager.RunningTaskInfo; import android.util.Log; import android.view.animation.Interpolator; @@ -53,17 +52,17 @@ final class AppToOverviewAnimationProvider> extend private final BaseActivityInterface mActivityInterface; // The id of the currently running task that is transitioning to overview. - private final RunningTaskInfo mTargetTask; + private final int mTargetTaskId; private final RecentsAnimationDeviceState mDeviceState; private T mActivity; private RecentsView mRecentsView; AppToOverviewAnimationProvider( - BaseActivityInterface activityInterface, RunningTaskInfo targetTask, + BaseActivityInterface activityInterface, int targetTaskId, RecentsAnimationDeviceState deviceState) { mActivityInterface = activityInterface; - mTargetTask = targetTask; + mTargetTaskId = targetTaskId; mDeviceState = deviceState; } @@ -74,7 +73,7 @@ final class AppToOverviewAnimationProvider> extend * @param wasVisible true if it was visible before */ boolean onActivityReady(T activity, Boolean wasVisible) { - activity.getOverviewPanel().showCurrentTask(mTargetTask); + activity.getOverviewPanel().showCurrentTask(mTargetTaskId); AbstractFloatingView.closeAllOpenViews(activity, wasVisible); BaseActivityInterface.AnimationFactory factory = mActivityInterface.prepareRecentsUI( mDeviceState, @@ -123,8 +122,7 @@ final class AppToOverviewAnimationProvider> extend wallpaperTargets, MODE_CLOSING); // Use the top closing app to determine the insets for the animation - RemoteAnimationTargetCompat runningTaskTarget = mTargetTask == null ? null - : targets.findTask(mTargetTask.taskId); + RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mTargetTaskId); if (runningTaskTarget == null) { Log.e(TAG, "No closing app"); return pa.buildAnim(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index b49299d2fe..a63f3a802f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -15,8 +15,6 @@ */ package com.android.quickstep; -import static android.widget.Toast.LENGTH_SHORT; - 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.VibratorWrapper.OVERVIEW_HAPTIC; @@ -29,13 +27,11 @@ import android.graphics.Rect; import android.os.Build; import android.util.Log; import android.view.MotionEvent; -import android.widget.Toast; import androidx.annotation.CallSuper; import androidx.annotation.UiThread; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.R; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.VibratorWrapper; @@ -142,10 +138,10 @@ public abstract class BaseSwipeUpHandler, Q extend mRecentsView.getNextPageTaskView().launchTask(false /* animate */, true /* freezeTaskList */); } else { + int taskId = mRecentsView.getNextPageTaskView().getTask().key.id; if (!mCanceled) { - TaskView nextTask = mRecentsView.getNextPageTaskView(); + TaskView nextTask = mRecentsView.getTaskView(taskId); if (nextTask != null) { - int taskId = nextTask.getTask().key.id; mGestureState.updateLastStartedTaskId(taskId); boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds() .contains(taskId); @@ -162,10 +158,6 @@ public abstract class BaseSwipeUpHandler, Q extend mRecentsAnimationController.finish(true /* toRecents */, null); } }, MAIN_EXECUTOR.getHandler()); - } else { - mActivityInterface.onLaunchTaskFailed(); - Toast.makeText(mContext, R.string.activity_not_available, LENGTH_SHORT).show(); - mRecentsAnimationController.finish(true /* toRecents */, null); } } mCanceled = false; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 5905695b4a..6c4c5d3f4d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -38,6 +38,7 @@ import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINI 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.SysUINavigationMode.Mode.TWO_BUTTONS; 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; @@ -59,7 +60,6 @@ import android.view.ViewTreeObserver.OnDrawListener; import android.view.WindowInsets; import android.view.animation.Interpolator; -import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.android.launcher3.AbstractFloatingView; @@ -70,7 +70,6 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; -import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; @@ -267,6 +266,10 @@ public abstract class BaseSwipeUpHandlerV2, Q exte mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED | STATE_RESUME_LAST_TASK, this::notifyTransitionCancelled); + mGestureState.runOnceAtState(STATE_END_TARGET_SET, + () -> mDeviceState.onEndTargetCalculated(mGestureState.getEndTarget(), + mActivityInterface)); + if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) { mStateCallback.addChangeListener(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT, @@ -310,6 +313,12 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } setupRecentsViewUi(); + + if (mDeviceState.getNavMode() == TWO_BUTTONS) { + // If the device is in two button mode, swiping up will show overview with predictions + // so we need to kick off switching to the overview predictions as soon as possible + mActivityInterface.updateOverviewPredictionState(); + } linkRecentsViewScroll(); return true; @@ -391,11 +400,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte mGestureState.getActivityInterface().setOnDeferredActivityLaunchCallback( mOnDeferredActivityLaunch); - mGestureState.runOnceAtState(STATE_END_TARGET_SET, - () -> mDeviceState.getRotationTouchHelper(). - onEndTargetCalculated(mGestureState.getEndTarget(), - mActivityInterface)); - notifyGestureStartedAsync(); } @@ -419,7 +423,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } protected void notifyGestureAnimationStartToRecents() { - mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask()); + mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId()); } private void launcherFrameDrawn() { @@ -447,6 +451,12 @@ public abstract class BaseSwipeUpHandlerV2, Q exte @Override public void onMotionPauseChanged(boolean isPaused) { setShelfState(isPaused ? PEEK : HIDE, ShelfPeekAnim.INTERPOLATOR, ShelfPeekAnim.DURATION); + + if (mDeviceState.isFullyGesturalNavMode() && isPaused) { + // In fully gestural nav mode, switch to overview predictions once the user has paused + // (this is a no-op if the predictions are already in that state) + mActivityInterface.updateOverviewPredictionState(); + } } public void maybeUpdateRecentsAttachedState() { @@ -545,6 +555,14 @@ public abstract class BaseSwipeUpHandlerV2, Q exte @Override public void updateFinalShift() { + if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { + if (mRecentsAnimationTargets != null) { + LiveTileOverlay.INSTANCE.update( + mTaskViewSimulator.getCurrentCropRect(), + mTaskViewSimulator.getCurrentCornerRadius()); + } + } + final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW; if (passed != mPassedOverviewThreshold) { mPassedOverviewThreshold = passed; @@ -555,14 +573,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte updateSysUiFlags(mCurrentShift.value); applyWindowTransform(); - if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { - if (mRecentsAnimationTargets != null) { - LiveTileOverlay.INSTANCE.update( - mTaskViewSimulator.getCurrentRect(), - mTaskViewSimulator.getCurrentCornerRadius()); - } - } - updateLauncherTransitionProgress(); } @@ -879,7 +889,22 @@ public abstract class BaseSwipeUpHandlerV2, Q exte animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); } - private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) { + private void doLogGesture(GestureEndTarget endTarget) { + DeviceProfile dp = mDp; + if (dp == null || mDownPos == null) { + // We probably never received an animation controller, skip logging. + return; + } + + int pageIndex = endTarget == LAST_TASK + ? LOG_NO_OP_PAGE_INDEX + : mRecentsView.getNextPage(); + UserEventDispatcher.newInstance(mContext).logStateChangeAction( + mLogAction, mLogDirection, + (int) mDownPos.x, (int) mDownPos.y, + ContainerType.NAVBAR, ContainerType.APP, + endTarget.containerType, + pageIndex); StatsLogManager.EventEnum event; switch (endTarget) { case HOME: @@ -897,29 +922,10 @@ public abstract class BaseSwipeUpHandlerV2, Q exte default: event = IGNORE; } - StatsLogger logger = StatsLogManager.newInstance(mContext).logger() + StatsLogManager.newInstance(mContext).logger() .withSrcState(LAUNCHER_STATE_BACKGROUND) - .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)); - if (targetTask != null) { - logger.withItemInfo(targetTask.getItemInfo()); - } - logger.log(event); - - - DeviceProfile dp = mDp; - if (dp == null || mDownPos == null) { - // We probably never received an animation controller, skip logging. - return; - } - int pageIndex = endTarget == LAST_TASK - ? LOG_NO_OP_PAGE_INDEX - : mRecentsView.getNextPage(); - UserEventDispatcher.newInstance(mContext).logStateChangeAction( - mLogAction, mLogDirection, - (int) mDownPos.x, (int) mDownPos.y, - ContainerType.NAVBAR, ContainerType.APP, - endTarget.containerType, - pageIndex); + .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)) + .log(event); } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ @@ -1124,7 +1130,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte private void resumeLastTask() { mRecentsAnimationController.finish(false /* toRecents */, null); ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); - doLogGesture(LAST_TASK, null); + doLogGesture(LAST_TASK); reset(); } @@ -1139,7 +1145,6 @@ public abstract class BaseSwipeUpHandlerV2, Q exte @UiThread private void startNewTaskInternal() { - TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView(); startNewTask(success -> { if (!success) { reset(); @@ -1148,7 +1153,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte endLauncherTransitionController(); updateSysUiFlags(1 /* windowProgress == overview */); } - doLogGesture(NEW_TASK, taskToLaunch); + doLogGesture(NEW_TASK); }); } @@ -1293,7 +1298,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte () -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); } ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true); - doLogGesture(HOME, mRecentsView == null ? null : mRecentsView.getCurrentPageTaskView()); + doLogGesture(HOME); } protected abstract void finishRecentsControllerToHome(Runnable callback); @@ -1308,7 +1313,7 @@ public abstract class BaseSwipeUpHandlerV2, Q exte mRecentsView.onSwipeUpAnimationSuccess(); SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG); - doLogGesture(RECENTS, mRecentsView.getCurrentPageTaskView()); + doLogGesture(RECENTS); reset(); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java index d1da0c1c10..33b9cdee08 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityInterface.java @@ -140,7 +140,7 @@ public final class FallbackActivityInterface extends } @Override - public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { + public void onExitOverview(RecentsAnimationDeviceState deviceState, Runnable exitRunnable) { // no-op, fake landscape not supported for 3P } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java index 1909f4772e..fc7a119f21 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackSwipeHandler.java @@ -140,6 +140,7 @@ public class FallbackSwipeHandler extends private final long mDuration; FallbackHomeAnimationFactory(long duration) { + super(null); mDuration = duration; if (mRunningOverHome) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java index b02035516d..edefbe1252 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityInterface.java @@ -105,7 +105,7 @@ public final class LauncherActivityInterface extends // recents, we assume the first task is invisible, making translation off by one task. launcher.getStateManager().reapplyState(); launcher.getRootView().setForceHideBackArrow(false); - notifyRecentsOfOrientation(deviceState.getRotationTouchHelper()); + notifyRecentsOfOrientation(deviceState); } @Override @@ -120,7 +120,7 @@ public final class LauncherActivityInterface extends @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, boolean activityVisible, Consumer callback) { - notifyRecentsOfOrientation(deviceState.getRotationTouchHelper()); + notifyRecentsOfOrientation(deviceState); DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) { @Override public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, @@ -228,7 +228,7 @@ public final class LauncherActivityInterface extends @Override - public void onExitOverview(RotationTouchHelper deviceState, Runnable exitRunnable) { + public void onExitOverview(RecentsAnimationDeviceState deviceState, Runnable exitRunnable) { final StateManager stateManager = getCreatedActivity().getStateManager(); stateManager.addStateListener( new StateManager.StateListener() { @@ -244,11 +244,11 @@ public final class LauncherActivityInterface extends }); } - private void notifyRecentsOfOrientation(RotationTouchHelper rotationTouchHelper) { + private void notifyRecentsOfOrientation(RecentsAnimationDeviceState deviceState) { // reset layout on swipe to home RecentsView recentsView = getCreatedActivity().getOverviewPanel(); - recentsView.setLayoutRotation(rotationTouchHelper.getCurrentActiveRotation(), - rotationTouchHelper.getDisplayRotation()); + recentsView.setLayoutRotation(deviceState.getCurrentActiveRotation(), + deviceState.getDisplayRotation()); } @Override @@ -261,6 +261,16 @@ public final class LauncherActivityInterface extends return true; } + @Override + public void updateOverviewPredictionState() { + Launcher launcher = getCreatedActivity(); + if (launcher == null) { + return; + } + PredictionUiStateManager.INSTANCE.get(launcher).switchClient( + PredictionUiStateManager.Client.OVERVIEW); + } + @Override public int getContainerType() { final Launcher launcher = getVisibleLauncher(); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java index 052d0a68a6..fa7d2689f3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherSwipeHandlerV2.java @@ -16,7 +16,6 @@ package com.android.quickstep; import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import android.animation.AnimatorSet; import android.content.Context; @@ -29,7 +28,6 @@ import androidx.annotation.NonNull; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.views.FloatingIconView; -import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.StaggeredWorkspaceAnim; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -74,39 +72,36 @@ public class LauncherSwipeHandlerV2 extends mActivity.getRootView().setForceHideBackArrow(true); mActivity.setHintUserWillBeActive(); - if (canUseWorkspaceView) { - // We want the window alpha to be 0 once this threshold is met, so that the - // FolderIconView can be seen morphing into the icon shape. - float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION; - homeAnimFactory = new LauncherHomeAnimationFactory() { - @Override - public RectF getWindowTargetRect() { + homeAnimFactory = new HomeAnimationFactory(floatingIconView) { + + @Override + public RectF getWindowTargetRect() { + if (canUseWorkspaceView) { return iconLocation; + } else { + return super.getWindowTargetRect(); } + } - @Override - public void setAnimation(RectFSpringAnim anim) { - anim.addAnimatorListener(floatingIconView); - floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged); - floatingIconView.setFastFinishRunnable(anim::end); - } + @NonNull + @Override + public AnimatorPlaybackController createActivityAnimationToHome() { + // Return an empty APC here since we have an non-user controlled animation + // to home. + long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); + return mActivity.getStateManager().createAnimationToNewWorkspace( + NORMAL, accuracy, 0 /* animComponents */); + } - @Override - public void update(RectF currentRect, float progress, float radius) { - floatingIconView.update(currentRect, 1f, progress, windowAlphaThreshold, - radius, false); - } + @Override + public void playAtomicAnimation(float velocity) { + new StaggeredWorkspaceAnim(mActivity, velocity, + true /* animateOverviewScrim */).start(); + } + }; - @Override - public void onCancel() { - floatingIconView.fastFinish(); - } - }; - } else { - homeAnimFactory = new LauncherHomeAnimationFactory(); - } } else { - homeAnimFactory = new HomeAnimationFactory() { + homeAnimFactory = new HomeAnimationFactory(null) { @Override public AnimatorPlaybackController createActivityAnimationToHome() { return AnimatorPlaybackController.wrap(new AnimatorSet(), duration); @@ -123,22 +118,4 @@ public class LauncherSwipeHandlerV2 extends mRecentsAnimationController.finish( true /* toRecents */, callback, true /* sendUserLeaveHint */); } - - private class LauncherHomeAnimationFactory extends HomeAnimationFactory { - @NonNull - @Override - public AnimatorPlaybackController createActivityAnimationToHome() { - // Return an empty APC here since we have an non-user controlled animation - // to home. - long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx); - return mActivity.getStateManager().createAnimationToNewWorkspace( - NORMAL, accuracy, 0 /* animComponents */); - } - - @Override - public void playAtomicAnimation(float velocity) { - new StaggeredWorkspaceAnim(mActivity, velocity, - true /* animateOverviewScrim */).start(); - } - } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java index dca33789e5..434a929b5c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewCommandHelper.java @@ -29,6 +29,7 @@ import android.view.ViewConfiguration; import androidx.annotation.BinderThread; +import com.android.launcher3.appprediction.PredictionUiStateManager; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -164,7 +165,7 @@ public class OverviewCommandHelper { mActivityInterface = mOverviewComponentObserver.getActivityInterface(); mCreateTime = SystemClock.elapsedRealtime(); mAnimationProvider = new AppToOverviewAnimationProvider<>(mActivityInterface, - ActivityManagerWrapper.getInstance().getRunningTask(), mDeviceState); + RecentsModel.getRunningTaskId(), mDeviceState); // Preload the plan mRecentsModel.getTasks(null); @@ -226,6 +227,10 @@ public class OverviewCommandHelper { LauncherLogProto.ContainerType.TASKSWITCHER); mUserEventLogged = true; } + + // Switch prediction client to overview + PredictionUiStateManager.INSTANCE.get(activity).switchClient( + PredictionUiStateManager.Client.OVERVIEW); return mAnimationProvider.onActivityReady(activity, wasVisible); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java index e54a21c073..dc8f1c54c8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeUpAnimationLogic.java @@ -17,6 +17,7 @@ package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.ACCEL_1_5; import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION; import android.animation.Animator; import android.content.Context; @@ -27,6 +28,7 @@ import android.graphics.RectF; import android.view.animation.Interpolator; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.UiThread; import com.android.launcher3.DeviceProfile; @@ -35,6 +37,7 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.touch.PagedOrientationHandler; +import com.android.launcher3.views.FloatingIconView; import com.android.quickstep.util.RectFSpringAnim; import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.util.TransformParams; @@ -82,8 +85,7 @@ public abstract class SwipeUpAnimationLogic { mTransformParams = transformParams; mTaskViewSimulator.setLayoutRotation( - mDeviceState.getRotationTouchHelper().getCurrentActiveRotation(), - mDeviceState.getRotationTouchHelper().getDisplayRotation()); + mDeviceState.getCurrentActiveRotation(), mDeviceState.getDisplayRotation()); } protected void initTransitionEndpoints(DeviceProfile dp) { @@ -146,6 +148,12 @@ public abstract class SwipeUpAnimationLogic { protected abstract class HomeAnimationFactory { + public FloatingIconView mIconView; + + public HomeAnimationFactory(@Nullable FloatingIconView iconView) { + mIconView = iconView; + } + public @NonNull RectF getWindowTargetRect() { PagedOrientationHandler orientationHandler = getOrientationHandler(); DeviceProfile dp = mDp; @@ -166,12 +174,6 @@ public abstract class SwipeUpAnimationLogic { public void playAtomicAnimation(float velocity) { // No-op } - - public void setAnimation(RectFSpringAnim anim) { } - - public void update(RectF currentRect, float progress, float radius) { } - - public void onCancel() { } } /** @@ -182,6 +184,8 @@ public abstract class SwipeUpAnimationLogic { protected RectFSpringAnim createWindowAnimationToHome(float startProgress, HomeAnimationFactory homeAnimationFactory) { final RectF targetRect = homeAnimationFactory.getWindowTargetRect(); + final FloatingIconView fiv = homeAnimationFactory.mIconView; + final boolean isFloatingIconView = fiv != null; mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor); mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress)); @@ -199,7 +203,11 @@ public abstract class SwipeUpAnimationLogic { windowToHomePositionMap.mapRect(startRect); RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext); - homeAnimationFactory.setAnimation(anim); + if (isFloatingIconView) { + anim.addAnimatorListener(fiv); + fiv.setOnTargetChangeListener(anim::onTargetPositionChanged); + fiv.setFastFinishRunnable(anim::end); + } SpringAnimationRunner runner = new SpringAnimationRunner( homeAnimationFactory, cropRectF, homeToWindowPositionMap); @@ -234,27 +242,32 @@ public abstract class SwipeUpAnimationLogic { final RectF mWindowCurrentRect = new RectF(); final Matrix mHomeToWindowPositionMap; - final HomeAnimationFactory mAnimationFactory; + final FloatingIconView mFIV; final AnimatorPlaybackController mHomeAnim; final RectF mCropRectF; final float mStartRadius; final float mEndRadius; + final float mWindowAlphaThreshold; SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF, Matrix homeToWindowPositionMap) { - mAnimationFactory = factory; mHomeAnim = factory.createActivityAnimationToHome(); mCropRectF = cropRectF; mHomeToWindowPositionMap = homeToWindowPositionMap; cropRectF.roundOut(mCropRect); + mFIV = factory.mIconView; // End on a "round-enough" radius so that the shape reveal doesn't have to do too much // rounding at the end of the animation. mStartRadius = mTaskViewSimulator.getCurrentCornerRadius(); mEndRadius = cropRectF.width() / 2f; + + // We want the window alpha to be 0 once this threshold is met, so that the + // FolderIconView can be seen morphing into the icon shape. + mWindowAlphaThreshold = mFIV != null ? 1f - SHAPE_PROGRESS_DURATION : 1f; } @Override @@ -269,7 +282,10 @@ public abstract class SwipeUpAnimationLogic { .setCornerRadius(cornerRadius); mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this)); - mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius)); + if (mFIV != null) { + mFIV.update(currentRect, 1f, progress, + mWindowAlphaThreshold, mMatrix.mapRadius(cornerRadius), false); + } } @Override @@ -282,7 +298,9 @@ public abstract class SwipeUpAnimationLogic { @Override public void onCancel() { - mAnimationFactory.onCancel(); + if (mFIV != null) { + mFIV.fastFinish(); + } } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index db512fa0f9..e9614d1351 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -19,7 +19,6 @@ package com.android.quickstep; import static android.view.Surface.ROTATION_0; import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; -import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBNAIL; import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED; import android.annotation.SuppressLint; @@ -147,29 +146,26 @@ public class TaskOverlayFactory implements ResourceBasedOverride { */ public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix, boolean rotated) { - getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null); + final boolean isAllowedByPolicy = thumbnail.isRealSnapshot; - if (thumbnail != null) { - getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated); - final boolean isAllowedByPolicy = thumbnail.isRealSnapshot; + getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated); - getActionsView().setCallbacks(new OverlayUICallbacks() { - @Override - public void onShare() { - if (isAllowedByPolicy) { - mImageApi.startShareActivity(); - } else { - showBlockedByPolicyMessage(); - } + getActionsView().setCallbacks(new OverlayUICallbacks() { + @Override + public void onShare() { + if (isAllowedByPolicy) { + mImageApi.startShareActivity(); + } else { + showBlockedByPolicyMessage(); } + } - @SuppressLint("NewApi") - @Override - public void onScreenshot() { - saveScreenshot(task); - } - }); - } + @SuppressLint("NewApi") + @Override + public void onScreenshot() { + saveScreenshot(task); + } + }); } /** diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 8837c0ec75..6e0b517b25 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -61,6 +61,7 @@ import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestLogging; @@ -257,7 +258,6 @@ public class TouchInteractionService extends Service implements PluginListener mAM.getRunningTask(false /* filterOnlyVisibleRecents */))); } return gestureState; @@ -661,7 +660,7 @@ public class TouchInteractionService extends Service implements PluginListener mAM.getRunningTask(true /* filterOnlyVisibleRecents */))); ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent(); ComponentName runningComponent = @@ -772,7 +771,13 @@ public class TouchInteractionService extends Service implements PluginListener { + AppLaunchTracker.INSTANCE.get(TouchInteractionService.this); + return false; + }).register(overviewIntent); + } else if (fromInit) { // The activity has been created before the initialization of overview service. It is // usually happens when booting or launcher is the top activity, so we should already // have the latest state. diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java index a946304779..d20bbe9780 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -63,6 +63,12 @@ public class FallbackRecentsView extends RecentsView mActivity.startHome(); } + @Override + public boolean shouldUseMultiWindowTaskSizeStrategy() { + // Just use the activity task size for multi-window as well. + return false; + } + /** * When starting gesture interaction from home, we add a temporary invisible tile corresponding * to the home task. This allows us to handle quick-switch similarly to a quick-switching @@ -70,7 +76,7 @@ public class FallbackRecentsView extends RecentsView */ public void onGestureAnimationStartOnHome(RunningTaskInfo homeTaskInfo) { mHomeTaskInfo = homeTaskInfo; - onGestureAnimationStart(homeTaskInfo); + onGestureAnimationStart(homeTaskInfo == null ? -1 : homeTaskInfo.taskId); } /** @@ -101,15 +107,14 @@ public class FallbackRecentsView extends RecentsView } @Override - protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) { - if (mHomeTaskInfo != null && runningTaskInfo != null && - mHomeTaskInfo.taskId == runningTaskInfo.taskId + protected boolean shouldAddDummyTaskView(int runningTaskId) { + if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == runningTaskId && getTaskViewCount() == 0) { // Do not add a dummy task if we are running over home with empty recents, so that we // show the empty recents message instead of showing a dummy task and later removing it. return false; } - return super.shouldAddDummyTaskView(runningTaskInfo); + return super.shouldAddDummyTaskView(runningTaskId); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java index 0c2c92cfb0..5ad48ebabc 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/AccessibilityInputConsumer.java @@ -99,8 +99,7 @@ public class AccessibilityInputConsumer extends DelegateInputConsumer { case ACTION_POINTER_DOWN: { if (mState == STATE_INACTIVE) { int pointerIndex = ev.getActionIndex(); - if (mDeviceState.getRotationTouchHelper() - .isInSwipeUpTouchRegion(ev, pointerIndex) + if (mDeviceState.isInSwipeUpTouchRegion(ev, pointerIndex) && mDelegate.allowInterceptByParent()) { setActive(ev); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java index a676390ce3..3a97216035 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java @@ -147,7 +147,7 @@ public class DeviceLockedInputConsumer implements InputConsumer, if (!mThresholdCrossed) { // Cancel interaction in case of multi-touch interaction int ptrIdx = ev.getActionIndex(); - if (!mDeviceState.getRotationTouchHelper().isInSwipeUpTouchRegion(ev, ptrIdx)) { + if (!mDeviceState.isInSwipeUpTouchRegion(ev, ptrIdx)) { int action = ev.getAction(); ev.setAction(ACTION_CANCEL); finishTouchTracking(ev); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index 6259f1f9fe..26df9c7b93 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -59,7 +59,6 @@ import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationDeviceState; -import com.android.quickstep.RotationTouchHelper; import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.CachedEventDispatcher; @@ -87,7 +86,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC private final NavBarPosition mNavBarPosition; private final TaskAnimationManager mTaskAnimationManager; private final GestureState mGestureState; - private final RotationTouchHelper mRotationTouchHelper; private RecentsAnimationCallbacks mActiveCallbacks; private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher(); private final InputMonitorCompat mInputMonitorCompat; @@ -165,7 +163,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture; mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe; - mRotationTouchHelper = mDeviceState.getRotationTouchHelper(); } @Override @@ -233,7 +230,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC if (!mPassedPilferInputSlop) { // Cancel interaction in case of multi-touch interaction int ptrIdx = ev.getActionIndex(); - if (!mRotationTouchHelper.isInSwipeUpTouchRegion(ev, ptrIdx)) { + if (!mDeviceState.isInSwipeUpTouchRegion(ev, ptrIdx)) { forceCancelGesture(ev); } } @@ -427,7 +424,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC @Override public void notifyOrientationSetup() { - mRotationTouchHelper.onStartGesture(); + mDeviceState.onStartGesture(); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java index 41203319b1..3cafd423ca 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java @@ -205,15 +205,13 @@ public class StaggeredWorkspaceAnim { ResourceProvider rp = DynamicResource.provider(v.getContext()); float stiffness = rp.getFloat(R.dimen.staggered_stiffness); float damping = rp.getFloat(R.dimen.staggered_damping_ratio); - float endTransY = 0; - float springVelocity = Math.abs(mVelocity) * Math.signum(endTransY - mSpringTransY); ValueAnimator springTransY = new SpringAnimationBuilder(v.getContext()) .setStiffness(stiffness) .setDampingRatio(damping) .setMinimumVisibleChange(1f) .setStartValue(mSpringTransY) - .setEndValue(endTransY) - .setStartVelocity(springVelocity) + .setEndValue(0) + .setStartVelocity(mVelocity) .build(v, VIEW_TRANSLATE_Y); springTransY.setStartDelay(startDelay); springTransY.addListener(new AnimatorListenerAdapter() { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java index 64ae1e0479..c9ed498af1 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TaskViewSimulator.java @@ -15,7 +15,6 @@ */ package com.android.quickstep.util; -import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.states.RotationHelper.deltaRotation; import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE; import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation; @@ -198,15 +197,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { return mTempRectF; } - /** - * Returns the current task bounds in the Launcher coordinate space. - */ - public RectF getCurrentRect() { - RectF result = getCurrentCropRect(); - mMatrix.mapRect(result); - return result; - } - public RecentsOrientedState getOrientationState() { return mOrientationState; } @@ -305,10 +295,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy { builder.withMatrix(mMatrix) .withWindowCrop(mTmpCropRect) .withCornerRadius(getCurrentCornerRadius()); - - if (ENABLE_QUICKSTEP_LIVE_TILE.get() && params.getRecentsSurface() != null) { - builder.withRelativeLayerTo(params.getRecentsSurface(), Integer.MAX_VALUE); - } } /** diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java index 756331dcdf..0135f7472c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/TransformParams.java @@ -16,7 +16,6 @@ package com.android.quickstep.util; import android.util.FloatProperty; -import android.view.SurfaceControl; import com.android.launcher3.Utilities; import com.android.launcher3.anim.Interpolators; @@ -59,7 +58,6 @@ public class TransformParams { private float mCornerRadius; private RemoteAnimationTargets mTargetSet; private SurfaceTransactionApplier mSyncTransactionApplier; - private SurfaceControl mRecentsSurface; private BuilderProxy mHomeBuilderProxy = BuilderProxy.ALWAYS_VISIBLE; private BuilderProxy mBaseBuilderProxy = BuilderProxy.ALWAYS_VISIBLE; @@ -140,8 +138,6 @@ public class TransformParams { public SurfaceParams[] createSurfaceParams(BuilderProxy proxy) { RemoteAnimationTargets targets = mTargetSet; SurfaceParams[] surfaceParams = new SurfaceParams[targets.unfilteredApps.length]; - mRecentsSurface = getRecentsSurface(targets); - for (int i = 0; i < targets.unfilteredApps.length; i++) { RemoteAnimationTargetCompat app = targets.unfilteredApps[i]; SurfaceParams.Builder builder = new SurfaceParams.Builder(app.leash); @@ -169,20 +165,6 @@ public class TransformParams { return surfaceParams; } - private static SurfaceControl getRecentsSurface(RemoteAnimationTargets targets) { - for (int i = 0; i < targets.unfilteredApps.length; i++) { - RemoteAnimationTargetCompat app = targets.unfilteredApps[i]; - if (app.mode == targets.targetMode) { - if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS) { - return app.leash.getSurfaceControl(); - } - } else { - return app.leash.getSurfaceControl(); - } - } - return null; - } - // Pubic getters so outside packages can read the values. public float getProgress() { @@ -197,10 +179,6 @@ public class TransformParams { return mCornerRadius; } - public SurfaceControl getRecentsSurface() { - return mRecentsSurface; - } - public RemoteAnimationTargets getTargetSet() { return mTargetSet; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java index c06dd9c0bd..0979c071bb 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/AllAppsEduView.java @@ -16,7 +16,6 @@ package com.android.quickstep.views; import static com.android.launcher3.LauncherState.ALL_APPS; -import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; @@ -43,10 +42,8 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; 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.Interpolators; -import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.util.Themes; @@ -54,7 +51,6 @@ import com.android.quickstep.util.MultiValueUpdateListener; /** * View used to educate the user on how to access All Apps when in No Nav Button navigation mode. - * Consumes all touches until after the animation is completed and the view is removed. */ public class AllAppsEduView extends AbstractFloatingView { @@ -114,19 +110,9 @@ public class AllAppsEduView extends AbstractFloatingView { return (type & TYPE_ALL_APPS_EDU) != 0; } - @Override - public boolean onBackPressed() { - return true; - } - - @Override - public boolean canInterceptEventsInSystemGestureRegion() { - return true; - } - @Override public boolean onControllerInterceptTouchEvent(MotionEvent ev) { - return true; + return mAnimation != null && mAnimation.isRunning(); } private void playAnimation() { @@ -153,12 +139,7 @@ public class AllAppsEduView extends AbstractFloatingView { config.userControlled = false; AnimatorPlaybackController stateAnimationController = mLauncher.getStateManager().createAnimationToNewWorkspace(ALL_APPS, config); - float maxAllAppsProgress = mLauncher.getDeviceProfile().isLandscape ? 0.35f : 0.15f; - - AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); - PendingAnimation allAppsAlpha = new PendingAnimation(config.duration); - allAppsController.setAlphas(ALL_APPS, config, allAppsAlpha); - mAnimation.play(allAppsAlpha.buildAnim()); + float maxAllAppsProgress = 0.15f; ValueAnimator intro = ValueAnimator.ofFloat(0, 1f); intro.setInterpolator(LINEAR); @@ -210,8 +191,7 @@ public class AllAppsEduView extends AbstractFloatingView { @Override public void onAnimationEnd(Animator animation) { mAnimation = null; - // Handles cancelling the animation used to hint towards All Apps. - mLauncher.getStateManager().goToState(NORMAL, false); + stateAnimationController.dispatchOnCancel(); handleClose(false); } }); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index 1034234138..846b94463f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -31,6 +31,7 @@ import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.content.Context; import android.os.Build; +import android.os.UserHandle; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.Surface; @@ -40,15 +41,20 @@ import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.Hotseat; import com.android.launcher3.LauncherState; import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.appprediction.PredictionUiStateManager; +import com.android.launcher3.appprediction.PredictionUiStateManager.Client; +import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; +import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.ScrimView; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.util.TransformParams; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.RecentsExtraCard; +import com.android.systemui.shared.recents.model.Task; /** * {@link RecentsView} used in Launcher activity @@ -174,6 +180,18 @@ public class LauncherRecentsView extends RecentsView super.onTaskLaunchAnimationEnd(success); } + @Override + public void onTaskLaunched(Task task) { + UserHandle user = UserHandle.of(task.key.userId); + AppLaunchTracker.INSTANCE.get(getContext()).onStartApp(task.getTopComponent(), user, + AppLaunchTracker.CONTAINER_OVERVIEW); + } + + @Override + public boolean shouldUseMultiWindowTaskSizeStrategy() { + return TraceHelper.whitelistIpcs("isInMultiWindowMode", mActivity::isInMultiWindowMode); + } + @Override public void scrollTo(int x, int y) { super.scrollTo(x, y); @@ -219,6 +237,9 @@ public class LauncherRecentsView extends RecentsView super.reset(); setLayoutRotation(Surface.ROTATION_0, Surface.ROTATION_0); + // We are moving to home or some other UI with no recents. Switch back to the home client, + // the home predictions should have been updated when the activity was resumed. + PredictionUiStateManager.INSTANCE.get(getContext()).switchClient(Client.HOME); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java index 79d57c55a2..a2da39855c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java @@ -70,14 +70,12 @@ public class OverviewActionsView extends FrameLayo @IntDef(flag = true, value = { DISABLED_SCROLLING, - DISABLED_ROTATED, - DISABLED_NO_THUMBNAIL}) + DISABLED_ROTATED}) @Retention(RetentionPolicy.SOURCE) public @interface ActionsDisabledFlags { } public static final int DISABLED_SCROLLING = 1 << 0; public static final int DISABLED_ROTATED = 1 << 1; - public static final int DISABLED_NO_THUMBNAIL = 1 << 2; private static final int INDEX_CONTENT_ALPHA = 0; private static final int INDEX_VISIBILITY_ALPHA = 1; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 1ad02a963d..7b24b03f2b 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -55,8 +55,10 @@ import android.animation.LayoutTransition.TransitionListener; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; -import android.app.ActivityManager.RunningTaskInfo; +import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; +import android.content.Intent; import android.content.res.Configuration; import android.graphics.Canvas; import android.graphics.Point; @@ -133,7 +135,6 @@ import com.android.quickstep.util.TransformParams; import com.android.systemui.plugins.ResourceProvider; import com.android.systemui.shared.recents.IPinnedStackAnimationListener; import com.android.systemui.shared.recents.model.Task; -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; @@ -146,7 +147,7 @@ import java.util.function.Consumer; /** * A list of recent tasks. */ -@TargetApi(Build.VERSION_CODES.R) +@TargetApi(Build.VERSION_CODES.P) public abstract class RecentsView extends PagedView implements Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener, @@ -376,7 +377,7 @@ public abstract class RecentsView extends PagedView mOrientationState.setMultiWindowMode(inMultiWindowMode); setLayoutRotation(mOrientationState.getTouchRotation(), mOrientationState.getDisplayRotation()); - updateChildTaskOrientations(); + rotateAllChildTasks(); } if (!inMultiWindowMode && mOverviewStateEnabled) { // TODO: Re-enable layout transitions for addition of the unpinned task @@ -1040,13 +1041,13 @@ public abstract class RecentsView extends PagedView /** * Called when a gesture from an app is starting. */ - public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) { + public void onGestureAnimationStart(int runningTaskId) { // This needs to be called before the other states are set since it can create the task view if (mOrientationState.setGestureActive(true)) { updateOrientationHandler(); } - showCurrentTask(runningTaskInfo); + showCurrentTask(runningTaskId); setEnableFreeScroll(false); setEnableDrawingLiveTile(false); setRunningTaskHidden(true); @@ -1077,7 +1078,7 @@ public abstract class RecentsView extends PagedView pa.addListener(AnimationSuccessListener.forRunnable(() -> { setLayoutRotation(newRotation, mOrientationState.getDisplayRotation()); mActivity.getDragLayer().recreateControllers(); - updateChildTaskOrientations(); + rotateAllChildTasks(); setRecentsChangedOrientation(false).start(); })); pa.start(); @@ -1098,7 +1099,7 @@ public abstract class RecentsView extends PagedView } - private void updateChildTaskOrientations() { + private void rotateAllChildTasks() { for (int i = 0; i < getTaskViewCount(); i++) { getTaskViewAt(i).setOrientationState(mOrientationState); } @@ -1126,8 +1127,8 @@ public abstract class RecentsView extends PagedView /** * Returns true if we should add a dummy taskView for the running task id */ - protected boolean shouldAddDummyTaskView(RunningTaskInfo runningTaskInfo) { - return runningTaskInfo != null && getTaskView(runningTaskInfo.taskId) == null; + protected boolean shouldAddDummyTaskView(int runningTaskId) { + return getTaskView(runningTaskId) == null; } /** @@ -1136,8 +1137,8 @@ public abstract class RecentsView extends PagedView * All subsequent calls to reload will keep the task as the first item until {@link #reset()} * is called. Also scrolls the view to this task. */ - public void showCurrentTask(RunningTaskInfo runningTaskInfo) { - if (shouldAddDummyTaskView(runningTaskInfo)) { + public void showCurrentTask(int runningTaskId) { + if (shouldAddDummyTaskView(runningTaskId)) { boolean wasEmpty = getChildCount() == 0; // Add an empty view for now until the task plan is loaded and applied final TaskView taskView = mTaskViewPool.getView(); @@ -1147,7 +1148,10 @@ public abstract class RecentsView extends PagedView } // The temporary running task is only used for the duration between the start of the // gesture and the task list is loaded and applied - mTmpRunningTask = Task.from(new TaskKey(runningTaskInfo), runningTaskInfo, false); + mTmpRunningTask = new Task(new Task.TaskKey(runningTaskId, 0, new Intent(), + new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0, + false, true, false, false, new ActivityManager.TaskDescription(), 0, + new ComponentName("", ""), false); taskView.bind(mTmpRunningTask, mOrientationState); // Measure and layout immediately so that the scroll values is updated instantly @@ -1158,7 +1162,7 @@ public abstract class RecentsView extends PagedView } boolean runningTaskTileHidden = mRunningTaskTileHidden; - setCurrentTask(runningTaskInfo == null ? -1 : runningTaskInfo.taskId); + setCurrentTask(runningTaskId); setCurrentPage(getRunningTaskIndex()); setRunningTaskViewShowScreenshot(false); setRunningTaskHidden(runningTaskTileHidden); @@ -1648,9 +1652,6 @@ public abstract class RecentsView extends PagedView super.setVisibility(visibility); if (mActionsView != null) { mActionsView.updateHiddenFlags(HIDDEN_NO_RECENTS, visibility != VISIBLE); - if (visibility != VISIBLE) { - mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false); - } } } @@ -1679,11 +1680,10 @@ public abstract class RecentsView extends PagedView : View.LAYOUT_DIRECTION_RTL); mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated()); mActivity.getDragLayer().recreateControllers(); - boolean isInLandscape = mOrientationState.getTouchRotation() != ROTATION_0 + boolean isInLandscape = mOrientationState.getTouchRotation() != 0 || mOrientationState.getRecentsActivityRotation() != ROTATION_0; mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, !mOrientationState.canRecentsActivityRotate() && isInLandscape); - updateChildTaskOrientations(); resetPaddingFromTaskSize(); requestLayout(); // Reapply the current page to update page scrolls. @@ -1998,12 +1998,19 @@ public abstract class RecentsView extends PagedView protected void onTaskLaunchAnimationUpdate(float progress, TaskView tv) { } + public abstract boolean shouldUseMultiWindowTaskSizeStrategy(); + protected void onTaskLaunchAnimationEnd(boolean success) { if (success) { resetTaskVisuals(); } } + /** + * Called when task activity is launched + */ + public void onTaskLaunched(Task task){ } + @Override protected void notifyPageSwitchListener(int prevPage) { super.notifyPageSwitchListener(prevPage); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java index 8b49f2c212..ef66b7a396 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskMenuView.java @@ -169,9 +169,7 @@ public class TaskMenuView extends AbstractFloatingView { } if (mIsOpen) { mOptionLayout.removeAllViews(); - if (!populateAndLayoutMenu()) { - close(false); - } + populateAndLayoutMenu(); } } @@ -188,22 +186,14 @@ public class TaskMenuView extends AbstractFloatingView { } mActivity.getDragLayer().addView(this); mTaskView = taskView; - if (!populateAndLayoutMenu()) { - return false; - } + populateAndLayoutMenu(); post(this::animateOpen); return true; } - /** @return true if successfully able to populate task view menu, false otherwise */ - private boolean populateAndLayoutMenu() { - if (mTaskView.getTask().icon == null) { - // Icon may not be loaded - return false; - } + private void populateAndLayoutMenu() { addMenuOptions(mTaskView); orientAroundTaskView(mTaskView); - return true; } private void addMenuOptions(TaskView taskView) { @@ -250,10 +240,8 @@ public class TaskMenuView extends AbstractFloatingView { setLayoutParams(params); setScaleX(taskView.getScaleX()); setScaleY(taskView.getScaleY()); - boolean canActivityRotate = taskView.getRecentsView() - .mOrientationState.canRecentsActivityRotate(); mOptionLayout.setOrientation(orientationHandler - .getTaskMenuLayoutOrientation(canActivityRotate, mOptionLayout)); + .getTaskMenuLayoutOrientation(mOptionLayout)); setPosition(sTempRect.left - insets.left, sTempRect.top - insets.top, taskView.getPagedOrientationHandler()); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java index 37f6faf523..b2f937f8c2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskThumbnailView.java @@ -357,7 +357,7 @@ public class TaskThumbnailView extends View implements PluginListener - - - - \ No newline at end of file diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml index 43bf0ea966..459d65faf7 100644 --- a/quickstep/res/layout/gesture_tutorial_fragment.xml +++ b/quickstep/res/layout/gesture_tutorial_fragment.xml @@ -24,14 +24,6 @@ android:layout_height="match_parent" android:background="@drawable/gesture_tutorial_ripple"/> - - + android:tint="?android:attr/textColorPrimary" + android:src="@drawable/gesture_tutorial_close_button"/> + android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end" + style="@style/TextAppearance.GestureTutorial.Title"/> + android:layout_marginStart="@dimen/gesture_tutorial_subtitle_margin_start_end" + android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end" + style="@style/TextAppearance.GestureTutorial.Subtitle"/> + style="@style/TextAppearance.GestureTutorial.Feedback"/>