From 750bbe08dab194be9c82cd3b8cb5dafaef961fff Mon Sep 17 00:00:00 2001 From: Kevin Date: Wed, 30 Jan 2019 17:05:20 -0800 Subject: [PATCH] Implement fallback recents activity for Go Implement recents activity for Go for when the default launcher does not have recents implemented. To do this, we factor out some common recents activity functionality from RecentsActivity and extend it to make a Go specific activity that pops in the icon recents fragment. Bug: 114136250 Test: Manual test NexusLauncher and Launcher3QuickstepGo by installing a quickstep-less launcher and setting it to default Change-Id: I936568489e8966da4a62e4b779ae660a220f2aeb --- .../res/layout/fallback_recents_activity.xml | 30 ++++ .../LauncherActivityControllerHelper.java | 12 -- .../android/quickstep/RecentsActivity.java | 74 ++++++++ .../fallback/GoRecentsActivityRootView.java | 31 ++++ .../res/layout/fallback_recents_activity.xml | 0 .../android/quickstep/RecentsActivity.java | 124 ++------------ .../fallback/FallbackRecentsView.java | 0 .../quickstep/fallback/RecentsRootView.java | 0 .../fallback/RecentsTaskController.java | 0 .../quickstep/BaseRecentsActivity.java | 162 ++++++++++++++++++ .../quickstep/RecentsActivityTracker.java | 28 +-- 11 files changed, 328 insertions(+), 133 deletions(-) create mode 100644 go/quickstep/res/layout/fallback_recents_activity.xml create mode 100644 go/quickstep/src/com/android/quickstep/RecentsActivity.java create mode 100644 go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java rename quickstep/{ => recents_ui_overrides}/res/layout/fallback_recents_activity.xml (100%) rename quickstep/{ => recents_ui_overrides}/src/com/android/quickstep/RecentsActivity.java (63%) rename quickstep/{ => recents_ui_overrides}/src/com/android/quickstep/fallback/FallbackRecentsView.java (100%) rename quickstep/{ => recents_ui_overrides}/src/com/android/quickstep/fallback/RecentsRootView.java (100%) rename quickstep/{ => recents_ui_overrides}/src/com/android/quickstep/fallback/RecentsTaskController.java (100%) create mode 100644 quickstep/src/com/android/quickstep/BaseRecentsActivity.java diff --git a/go/quickstep/res/layout/fallback_recents_activity.xml b/go/quickstep/res/layout/fallback_recents_activity.xml new file mode 100644 index 0000000000..653f463c91 --- /dev/null +++ b/go/quickstep/res/layout/fallback_recents_activity.xml @@ -0,0 +1,30 @@ + + + + + diff --git a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java index ac559ba999..ab4a2a0714 100644 --- a/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/go/quickstep/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -43,18 +43,6 @@ import java.util.function.Consumer; */ public final class LauncherActivityControllerHelper implements ActivityControlHelper{ - @Override - public LayoutListener createLayoutListener(Launcher activity) { - // Go does not have draggable task snapshots. - return null; - } - - - @Override - public void executeOnWindowAvailable(Launcher activity, Runnable action) { - // Go does not support live tiles. - } - @Override public void onTransitionCancelled(Launcher activity, boolean activityVisible) { LauncherState startState = activity.getStateManager().getRestState(); diff --git a/go/quickstep/src/com/android/quickstep/RecentsActivity.java b/go/quickstep/src/com/android/quickstep/RecentsActivity.java new file mode 100644 index 0000000000..a186aaa839 --- /dev/null +++ b/go/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -0,0 +1,74 @@ +/* + * 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; + +import android.app.ActivityOptions; +import android.view.View; + +import com.android.launcher3.R; +import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.fallback.GoRecentsActivityRootView; +import com.android.quickstep.views.IconRecentsView; + +/** + * A recents activity that displays recent tasks with an icon and small snapshot. + */ +public final class RecentsActivity extends BaseRecentsActivity { + + private GoRecentsActivityRootView mRecentsRootView; + private IconRecentsView mIconRecentsView; + + @Override + protected void initViews() { + setContentView(R.layout.fallback_recents_activity); + mRecentsRootView = findViewById(R.id.drag_layer); + mIconRecentsView = findViewById(R.id.overview_panel); + } + + @Override + protected void reapplyUi() { + //TODO: Implement this depending on how insets will affect the view. + } + + @Override + public BaseDragLayer getDragLayer() { + return mRecentsRootView; + } + + @Override + public View getRootView() { + return mRecentsRootView; + } + + @Override + public T getOverviewPanel() { + return (T) mIconRecentsView; + } + + @Override + public ActivityOptions getActivityLaunchOptions(View v) { + //TODO: Hook into recents launch animation + return null; + } + + @Override + protected void onStart() { + // Set the alpha to 1 before calling super, as it may get set back to 0 due to + // onActivityStart callback. + mIconRecentsView.setAlpha(0); + super.onStart(); + } +} diff --git a/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java b/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java new file mode 100644 index 0000000000..d748e89e91 --- /dev/null +++ b/go/quickstep/src/com/android/quickstep/fallback/GoRecentsActivityRootView.java @@ -0,0 +1,31 @@ +/* + * 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.fallback; + +import android.content.Context; +import android.util.AttributeSet; + +import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.RecentsActivity; + +/** + * Minimal implementation of {@link BaseDragLayer} for Go's fallback recents activity. + */ +public final class GoRecentsActivityRootView extends BaseDragLayer { + public GoRecentsActivityRootView(Context context, AttributeSet attrs) { + super(context, attrs, 1 /* alphaChannelCount */); + } +} diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml similarity index 100% rename from quickstep/res/layout/fallback_recents_activity.xml rename to quickstep/recents_ui_overrides/res/layout/fallback_recents_activity.xml diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java similarity index 63% rename from quickstep/src/com/android/quickstep/RecentsActivity.java rename to quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java index b76a1ab466..8d7039e600 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -15,12 +15,11 @@ */ package com.android.quickstep; -import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; -import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; - import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; -import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION; -import static com.android.launcher3.QuickstepAppTransitionManagerImpl.STATUS_BAR_TRANSITION_PRE_DELAY; +import static com.android.launcher3.QuickstepAppTransitionManagerImpl + .STATUS_BAR_TRANSITION_DURATION; +import static com.android.launcher3.QuickstepAppTransitionManagerImpl + .STATUS_BAR_TRANSITION_PRE_DELAY; import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; @@ -29,23 +28,16 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.app.ActivityOptions; -import android.content.Intent; import android.content.res.Configuration; -import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.View; -import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAnimationRunner; import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; -import com.android.launcher3.uioverrides.UiFactory; -import com.android.launcher3.util.SystemUiController; -import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsRootView; @@ -56,46 +48,22 @@ import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import java.io.FileDescriptor; -import java.io.PrintWriter; - /** - * A simple activity to show the recently launched tasks + * A recents activity that shows the recently launched tasks as swipable task cards. + * See {@link com.android.quickstep.views.RecentsView}. */ -public class RecentsActivity extends BaseDraggingActivity { +public final class RecentsActivity extends BaseRecentsActivity { private Handler mUiHandler = new Handler(Looper.getMainLooper()); private RecentsRootView mRecentsRootView; private FallbackRecentsView mFallbackRecentsView; - private Configuration mOldConfig; - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mOldConfig = new Configuration(getResources().getConfiguration()); - initDeviceProfile(); - + protected void initViews() { setContentView(R.layout.fallback_recents_activity); mRecentsRootView = findViewById(R.id.drag_layer); mFallbackRecentsView = findViewById(R.id.overview_panel); - mRecentsRootView.setup(); - - getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, - Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); - RecentsActivityTracker.onRecentsActivityCreate(this); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - int diff = newConfig.diff(mOldConfig); - if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) { - onHandleConfigChanged(); - } - mOldConfig.setTo(newConfig); - super.onConfigurationChanged(newConfig); } @Override @@ -110,16 +78,10 @@ public class RecentsActivity extends BaseDraggingActivity { } } - private void onHandleConfigChanged() { - mUserEventDispatcher = null; - initDeviceProfile(); - - AbstractFloatingView.closeOpenViews(this, true, - AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE); - dispatchDeviceProfileChanged(); - + @Override + protected void onHandleConfigChanged() { + super.onHandleConfigChanged(); mRecentsRootView.setup(); - reapplyUi(); } @Override @@ -127,15 +89,12 @@ public class RecentsActivity extends BaseDraggingActivity { mRecentsRootView.dispatchInsets(); } - private void initDeviceProfile() { + @Override + protected DeviceProfile createDeviceProfile() { DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this); - - // In case we are reusing IDP, create a copy so that we don't conflict with Launcher - // activity. - mDeviceProfile = (mRecentsRootView != null) && isInMultiWindowMode() + return (mRecentsRootView != null) && isInMultiWindowMode() ? dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize()) - : dp.copy(this); - onDeviceProfileInitiated(); + : super.createDeviceProfile(); } @Override @@ -211,55 +170,4 @@ public class RecentsActivity extends BaseDraggingActivity { super.onStart(); mFallbackRecentsView.resetTaskVisuals(); } - - @Override - protected void onStop() { - super.onStop(); - - // Workaround for b/78520668, explicitly trim memory once UI is hidden - onTrimMemory(TRIM_MEMORY_UI_HIDDEN); - } - - @Override - public void onEnterAnimationComplete() { - super.onEnterAnimationComplete(); - UiFactory.onEnterAnimationComplete(this); - } - - @Override - public void onTrimMemory(int level) { - super.onTrimMemory(level); - UiFactory.onTrimMemory(this, level); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - RecentsActivityTracker.onRecentsActivityNewIntent(this); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - RecentsActivityTracker.onRecentsActivityDestroy(this); - } - - @Override - public void onBackPressed() { - // TODO: Launch the task we came from - startHome(); - } - - public void startHome() { - startActivity(new Intent(Intent.ACTION_MAIN) - .addCategory(Intent.CATEGORY_HOME) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); - } - - @Override - public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { - super.dump(prefix, fd, writer, args); - writer.println(prefix + "Misc:"); - dumpMisc(writer); - } } diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java similarity index 100% rename from quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java similarity index 100% rename from quickstep/src/com/android/quickstep/fallback/RecentsRootView.java rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsRootView.java diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java similarity index 100% rename from quickstep/src/com/android/quickstep/fallback/RecentsTaskController.java rename to quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java diff --git a/quickstep/src/com/android/quickstep/BaseRecentsActivity.java b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java new file mode 100644 index 0000000000..c84013257b --- /dev/null +++ b/quickstep/src/com/android/quickstep/BaseRecentsActivity.java @@ -0,0 +1,162 @@ +/* + * 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; + +import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; +import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; + +import android.content.Intent; +import android.content.res.Configuration; +import android.os.Bundle; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.R; +import com.android.launcher3.uioverrides.UiFactory; +import com.android.launcher3.util.SystemUiController; +import com.android.launcher3.util.Themes; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +/** + * A base fallback recents activity that provides support for device profile changes, activity + * lifecycle tracking, and basic input handling from recents. + * + * This class is only used as a fallback in case the default launcher does not have a recents + * implementation. + */ +public abstract class BaseRecentsActivity extends BaseDraggingActivity { + + private Configuration mOldConfig; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mOldConfig = new Configuration(getResources().getConfiguration()); + initDeviceProfile(); + initViews(); + + getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW, + Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText)); + RecentsActivityTracker.onRecentsActivityCreate(this); + } + + /** + * Init drag layer and overview panel views. + */ + abstract protected void initViews(); + + @Override + public void onConfigurationChanged(Configuration newConfig) { + int diff = newConfig.diff(mOldConfig); + if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) { + onHandleConfigChanged(); + } + mOldConfig.setTo(newConfig); + super.onConfigurationChanged(newConfig); + } + + /** + * Logic for when device configuration changes (rotation, screen size change, multi-window, + * etc.) + */ + protected void onHandleConfigChanged() { + mUserEventDispatcher = null; + initDeviceProfile(); + + AbstractFloatingView.closeOpenViews(this, true, + AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE); + dispatchDeviceProfileChanged(); + + reapplyUi(); + } + + /** + * Initialize/update the device profile. + */ + private void initDeviceProfile() { + mDeviceProfile = createDeviceProfile(); + onDeviceProfileInitiated(); + } + + /** + * Generate the device profile to use in this activity. + * @return device profile + */ + protected DeviceProfile createDeviceProfile() { + DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this); + + // In case we are reusing IDP, create a copy so that we don't conflict with Launcher + // activity. + return dp.copy(this); + } + + + @Override + protected void onStop() { + super.onStop(); + + // Workaround for b/78520668, explicitly trim memory once UI is hidden + onTrimMemory(TRIM_MEMORY_UI_HIDDEN); + } + + @Override + public void onEnterAnimationComplete() { + super.onEnterAnimationComplete(); + UiFactory.onEnterAnimationComplete(this); + } + + @Override + public void onTrimMemory(int level) { + super.onTrimMemory(level); + UiFactory.onTrimMemory(this, level); + } + + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + RecentsActivityTracker.onRecentsActivityNewIntent(this); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + RecentsActivityTracker.onRecentsActivityDestroy(this); + } + + @Override + public void onBackPressed() { + // TODO: Launch the task we came from + startHome(); + } + + public void startHome() { + startActivity(new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + @Override + public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + super.dump(prefix, fd, writer, args); + writer.println(prefix + "Misc:"); + dumpMisc(writer); + } +} diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java index fb6090e2a5..0822e6199b 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java +++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java @@ -30,17 +30,18 @@ import java.lang.ref.WeakReference; import java.util.function.BiPredicate; /** - * Utility class to track create/destroy for RecentsActivity + * Utility class to track create/destroy for some {@link BaseRecentsActivity}. */ @TargetApi(Build.VERSION_CODES.P) -public class RecentsActivityTracker implements ActivityInitListener { +public class RecentsActivityTracker implements ActivityInitListener { - private static WeakReference sCurrentActivity = new WeakReference<>(null); + private static WeakReference sCurrentActivity = + new WeakReference<>(null); private static final Scheduler sScheduler = new Scheduler(); - private final BiPredicate mOnInitListener; + private final BiPredicate mOnInitListener; - public RecentsActivityTracker(BiPredicate onInitListener) { + public RecentsActivityTracker(BiPredicate onInitListener) { mOnInitListener = onInitListener; } @@ -54,12 +55,12 @@ public class RecentsActivityTracker implements ActivityInitListener { sScheduler.clearReference(this); } - private boolean init(RecentsActivity activity, boolean visible) { + private boolean init(T activity, boolean visible) { return mOnInitListener.test(activity, visible); } - public static RecentsActivity getCurrentActivity() { - return sCurrentActivity.get(); + public static T getCurrentActivity() { + return (T) sCurrentActivity.get(); } @Override @@ -71,17 +72,17 @@ public class RecentsActivityTracker implements ActivityInitListener { context.startActivity(intent, options); } - public static void onRecentsActivityCreate(RecentsActivity activity) { + public static void onRecentsActivityCreate(BaseRecentsActivity activity) { sCurrentActivity = new WeakReference<>(activity); sScheduler.initIfPending(activity, false); } - public static void onRecentsActivityNewIntent(RecentsActivity activity) { + public static void onRecentsActivityNewIntent(BaseRecentsActivity activity) { sScheduler.initIfPending(activity, activity.isStarted()); } - public static void onRecentsActivityDestroy(RecentsActivity activity) { + public static void onRecentsActivityDestroy(BaseRecentsActivity activity) { if (sCurrentActivity.get() == activity) { sCurrentActivity.clear(); } @@ -103,13 +104,14 @@ public class RecentsActivityTracker implements ActivityInitListener { @Override public void run() { - RecentsActivity activity = sCurrentActivity.get(); + BaseRecentsActivity activity = sCurrentActivity.get(); if (activity != null) { initIfPending(activity, activity.isStarted()); } } - public synchronized boolean initIfPending(RecentsActivity activity, boolean alreadyOnHome) { + public synchronized boolean initIfPending(BaseRecentsActivity activity, + boolean alreadyOnHome) { RecentsActivityTracker tracker = mPendingTracker.get(); if (tracker != null) { if (!tracker.init(activity, alreadyOnHome)) {