Generalize ActivityTracker to support RecentsWindowManager
Continued quick switch couldn't work using existing infrastructure until RecentsWindowManager could be properly tracked by ActivityTracker. Refactored ActivityTracker into ContextTracker to support this.
Also refactored ActivityInitListener into ContextInitListener to fit the updated pattern.
Flag: com.android.launcher3.enable_fallback_overview_in_window
Fixes: 366023051
Test: RecentsWindowSwipeHandlerTestCase; Attempted continued quick switch from home and launched app
Change-Id: Ic38ebf3611ef22fbfd1ddeb79d72d8a3621940a0
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a8840fe..8547eb4 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -224,10 +224,10 @@
import com.android.launcher3.touch.AllAppsSwipeController;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.ActivityResultInfo;
-import com.android.launcher3.util.ActivityTracker;
import com.android.launcher3.util.BackPressHandler;
import com.android.launcher3.util.CannedAnimationCoordinator;
import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ContextTracker;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
import com.android.launcher3.util.ItemInflater;
@@ -292,7 +292,8 @@
PluginListener<LauncherOverlayPlugin> {
public static final String TAG = "Launcher";
- public static final ActivityTracker<Launcher> ACTIVITY_TRACKER = new ActivityTracker<>();
+ public static final ContextTracker.ActivityTracker<Launcher> ACTIVITY_TRACKER =
+ new ContextTracker.ActivityTracker<>();
static final boolean LOGD = false;
@@ -1778,7 +1779,7 @@
@Override
public void onDestroy() {
super.onDestroy();
- ACTIVITY_TRACKER.onActivityDestroyed(this);
+ ACTIVITY_TRACKER.onContextDestroyed(this);
SettingsCache.INSTANCE.get(this).unregister(TOUCHPAD_NATURAL_SCROLLING,
mNaturalScrollingChangedListener);
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 981e3a6..43c148a 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -34,7 +34,7 @@
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.Launcher;
-import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
+import com.android.launcher3.util.ContextTracker.SchedulerCallback;
import com.android.launcher3.widget.PendingItemDragHelper;
import java.util.UUID;
@@ -74,9 +74,9 @@
}
@Override
- public boolean init(Launcher launcher, boolean alreadyOnHome) {
- AbstractFloatingView.closeAllOpenViews(launcher, alreadyOnHome);
- launcher.getStateManager().goToState(NORMAL, alreadyOnHome /* animated */);
+ public boolean init(Launcher launcher, boolean isHomeStarted) {
+ AbstractFloatingView.closeAllOpenViews(launcher, /* animate= */ isHomeStarted);
+ launcher.getStateManager().goToState(NORMAL, /* animated= */ isHomeStarted);
launcher.getDragLayer().setOnDragListener(this);
launcher.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK);
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index 59d1d00..49f75eb 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -121,7 +121,7 @@
@WorkerThread
private void flushQueueInBackground() {
- Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
+ Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedContext();
if (launcher == null) {
// Launcher not loaded
return;
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index b3bcada..4c9da5d 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -36,6 +36,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.LauncherPrefChangeListener;
import com.android.launcher3.LauncherPrefs;
+import com.android.launcher3.util.ContextTracker;
import com.android.launcher3.util.DisplayController;
/**
@@ -72,7 +73,7 @@
/**
* Rotation request made by
- * {@link com.android.launcher3.util.ActivityTracker.SchedulerCallback}.
+ * {@link ContextTracker.SchedulerCallback}.
* This supersedes any other request.
*/
private int mStateHandlerRequest = REQUEST_NONE;
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 3a93981..aa3f2f2 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -246,12 +246,12 @@
case TestProtocol.REQUEST_GET_SPLIT_SELECTION_ACTIVE:
response.putBoolean(TEST_INFO_RESPONSE_FIELD, enableSplitContextually()
- && Launcher.ACTIVITY_TRACKER.getCreatedActivity().isSplitSelectionActive());
+ && Launcher.ACTIVITY_TRACKER.getCreatedContext().isSplitSelectionActive());
return response;
case TestProtocol.REQUEST_ENABLE_ROTATION:
MAIN_EXECUTOR.submit(() ->
- Launcher.ACTIVITY_TRACKER.getCreatedActivity().getRotationHelper()
+ Launcher.ACTIVITY_TRACKER.getCreatedContext().getRotationHelper()
.forceAllowRotationForTesting(Boolean.parseBoolean(arg)));
return response;
@@ -475,12 +475,12 @@
}
protected boolean isLauncherInitialized() {
- return Launcher.ACTIVITY_TRACKER.getCreatedActivity() == null
+ return Launcher.ACTIVITY_TRACKER.getCreatedContext() == null
|| LauncherAppState.getInstance(mContext).getModel().isModelLoaded();
}
protected WindowInsets getWindowInsets(){
- return Launcher.ACTIVITY_TRACKER.getCreatedActivity().getWindow().getDecorView()
+ return Launcher.ACTIVITY_TRACKER.getCreatedContext().getWindow().getDecorView()
.getRootWindowInsets();
}
@@ -489,7 +489,7 @@
*/
public static <T> Bundle getLauncherUIProperty(
BundleSetter<T> bundleSetter, Function<Launcher, T> provider) {
- return getUIProperty(bundleSetter, provider, Launcher.ACTIVITY_TRACKER::getCreatedActivity);
+ return getUIProperty(bundleSetter, provider, Launcher.ACTIVITY_TRACKER::getCreatedContext);
}
/**
diff --git a/src/com/android/launcher3/util/ActivityTracker.java b/src/com/android/launcher3/util/ActivityTracker.java
deleted file mode 100644
index b2d0d75..0000000
--- a/src/com/android/launcher3/util/ActivityTracker.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.launcher3.util;
-
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-
-import com.android.launcher3.BaseActivity;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-/**
- * Helper class to statically track activity creation
- * @param <T> The activity type to track
- */
-public final class ActivityTracker<T extends BaseActivity> {
-
- private static final String TAG = "ActivityTracker";
-
- private WeakReference<T> mCurrentActivity = new WeakReference<>(null);
- private CopyOnWriteArrayList<SchedulerCallback<T>> mCallbacks = new CopyOnWriteArrayList<>();
-
- @Nullable
- public <R extends T> R getCreatedActivity() {
- return (R) mCurrentActivity.get();
- }
-
- public void onActivityDestroyed(T activity) {
- if (mCurrentActivity.get() == activity) {
- mCurrentActivity.clear();
- }
- }
-
- /**
- * Call {@link SchedulerCallback#init(BaseActivity, boolean)} when the
- * activity is ready. If the activity is already created, this is called immediately.
- *
- * The tracker maintains a strong ref to the callback, so it is up to the caller to return
- * {@code false} in the callback OR to unregister the callback explicitly.
- *
- * @param callback The callback to call init() on when the activity is ready.
- */
- public void registerCallback(SchedulerCallback<T> callback, String reasonString) {
- Log.d(TAG, "Registering callback: " + callback + ", reason=" + reasonString);
- T activity = mCurrentActivity.get();
- mCallbacks.add(callback);
- if (activity != null) {
- if (!callback.init(activity, activity.isStarted())) {
- unregisterCallback(callback, "ActivityTracker.registerCallback: Intent handled");
- }
- }
- }
-
- /**
- * Unregisters a registered callback.
- */
- public void unregisterCallback(SchedulerCallback<T> callback, String reasonString) {
- Log.d(TAG, "Unregistering callback: " + callback + ", reason=" + reasonString);
- mCallbacks.remove(callback);
- }
-
- public boolean handleCreate(T activity) {
- mCurrentActivity = new WeakReference<>(activity);
- return handleIntent(activity, false /* alreadyOnHome */);
- }
-
- public boolean handleNewIntent(T activity) {
- return handleIntent(activity, activity.isStarted());
- }
-
- private boolean handleIntent(T activity, boolean alreadyOnHome) {
- boolean handled = false;
- if (!mCallbacks.isEmpty()) {
- Log.d(TAG, "handleIntent: mCallbacks=" + mCallbacks);
- }
- for (SchedulerCallback<T> cb : mCallbacks) {
- if (!cb.init(activity, alreadyOnHome)) {
- // Callback doesn't want any more updates
- unregisterCallback(cb, "ActivityTracker.handleIntent: Intent handled");
- }
- handled = true;
- }
- return handled;
- }
-
- public void dump(String prefix, PrintWriter writer) {
- writer.println(prefix + "ActivityTracker:");
- writer.println(prefix + "\tmCurrentActivity=" + mCurrentActivity.get());
- writer.println(prefix + "\tmCallbacks=" + mCallbacks);
- }
-
- public interface SchedulerCallback<T extends BaseActivity> {
-
- /**
- * Called when the activity is ready.
- * @param alreadyOnHome Whether the activity is already started.
- * @return Whether to continue receiving callbacks (i.e. if the activity is recreated).
- */
- boolean init(T activity, boolean alreadyOnHome);
- }
-}
diff --git a/src/com/android/launcher3/util/ContextTracker.java b/src/com/android/launcher3/util/ContextTracker.java
new file mode 100644
index 0000000..c729b4b
--- /dev/null
+++ b/src/com/android/launcher3/util/ContextTracker.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.views.ActivityContext;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Helper class to statically track activity creation
+ * @param <CONTEXT> The context type to track
+ */
+public abstract class ContextTracker<CONTEXT extends ActivityContext> {
+
+ private static final String TAG = "ContextTracker";
+
+ private WeakReference<CONTEXT> mCurrentContext = new WeakReference<>(null);
+ private CopyOnWriteArrayList<SchedulerCallback<CONTEXT>> mCallbacks =
+ new CopyOnWriteArrayList<>();
+
+ @Nullable
+ public <R extends CONTEXT> R getCreatedContext() {
+ return (R) mCurrentContext.get();
+ }
+
+ public void onContextDestroyed(CONTEXT context) {
+ if (mCurrentContext.get() == context) {
+ mCurrentContext.clear();
+ }
+ }
+
+ public abstract boolean isHomeStarted(CONTEXT context);
+
+ /**
+ * Call {@link SchedulerCallback#init(ActivityContext, boolean)} when the
+ * context is ready. If the context is already created, this is called immediately.
+ *
+ * The tracker maintains a strong ref to the callback, so it is up to the caller to return
+ * {@code false} in the callback OR to unregister the callback explicitly.
+ *
+ * @param callback The callback to call init() on when the context is ready.
+ */
+ public void registerCallback(SchedulerCallback<CONTEXT> callback, String reasonString) {
+ Log.d(TAG, "Registering callback: " + callback + ", reason=" + reasonString);
+ CONTEXT context = mCurrentContext.get();
+ mCallbacks.add(callback);
+ if (context != null) {
+ if (!callback.init(context, isHomeStarted(context))) {
+ unregisterCallback(callback, "ContextTracker.registerCallback: Intent handled");
+ }
+ }
+ }
+
+ /**
+ * Unregisters a registered callback.
+ */
+ public void unregisterCallback(SchedulerCallback<CONTEXT> callback, String reasonString) {
+ Log.d(TAG, "Unregistering callback: " + callback + ", reason=" + reasonString);
+ mCallbacks.remove(callback);
+ }
+
+ public boolean handleCreate(CONTEXT context) {
+ mCurrentContext = new WeakReference<>(context);
+ return handleCreate(context, /* alreadyOnHome= */ false);
+ }
+
+ public boolean handleNewIntent(CONTEXT context) {
+ return handleCreate(context, isHomeStarted(context));
+ }
+
+ private boolean handleCreate(CONTEXT context, boolean isHomeStarted) {
+ boolean handled = false;
+ if (!mCallbacks.isEmpty()) {
+ Log.d(TAG, "handleIntent: mCallbacks=" + mCallbacks);
+ }
+ for (SchedulerCallback<CONTEXT> cb : mCallbacks) {
+ if (!cb.init(context, isHomeStarted)) {
+ // Callback doesn't want any more updates
+ unregisterCallback(cb, "ContextTracker.handleIntent: Intent handled");
+ }
+ handled = true;
+ }
+ return handled;
+ }
+
+ public void dump(String prefix, PrintWriter writer) {
+ writer.println(prefix + "ContextTracker:");
+ writer.println(prefix + "\tmCurrentContext=" + mCurrentContext.get());
+ writer.println(prefix + "\tmCallbacks=" + mCallbacks);
+ }
+
+ public interface SchedulerCallback<T extends ActivityContext> {
+
+ /**
+ * Called when the context is ready.
+ * @param isHomeStarted Whether the home activity is already started.
+ * @return Whether to continue receiving callbacks (i.e. if the context is recreated).
+ */
+ boolean init(T context, boolean isHomeStarted);
+ }
+
+ public static final class ActivityTracker<T extends BaseActivity> extends ContextTracker<T> {
+
+ @Override
+ public boolean isHomeStarted(T context) {
+ return context.isStarted();
+ }
+ }
+}