Moving SysUI with legacy Recents to another build target
- Move all legacy recents code out of the core sysui code
- Add separate target for products which still depend on it
- Move overview proxy implementation into another implementation of the
recents interface
Test: atest SystemUITests
Test: Push SystemUiWithLegacyRecents to the system image
adb shell pm disable com.google.android.apps.nexuslauncher/com.android.quickstep.TouchInteractionService
and ensure that the old recents implementation still works (and split
screen)
Change-Id: Iad67218ec37c13c79b6393d87f6bdc4f3996e2c6
Signed-off-by: Winson Chung <winsonc@google.com>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index b0fe190..b7844bc 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -44,13 +44,14 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.PluginInitializerImpl;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.NotificationData.KeyguardEnvironment;
diff --git a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java b/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
deleted file mode 100644
index fb343f9..0000000
--- a/packages/SystemUI/src/com/android/systemui/RecentsComponent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui;
-
-import android.graphics.Rect;
-import android.view.Display;
-import android.view.View;
-
-public interface RecentsComponent {
- void showRecentApps(boolean triggeredFromAltTab);
-
- /**
- * Docks the top-most task and opens recents.
- */
- boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
- int metricsDockAction);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index 36dbb0f..e0fc31b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -21,9 +21,11 @@
import java.io.PrintWriter;
-public interface BasePipManager {
+public interface BasePipManager {
void initialize(Context context);
void showPictureInPictureMenu();
+ default void expandPip() {}
+ default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
void onConfigurationChanged(Configuration newConfig);
- void dump(PrintWriter pw);
+ default void dump(PrintWriter pw) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index 864a6f9..70b581a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -24,8 +24,6 @@
import android.os.UserHandle;
import android.os.UserManager;
import com.android.systemui.SystemUI;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.ExpandPipEvent;
import com.android.systemui.statusbar.CommandQueue;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -68,7 +66,11 @@
}
public void expandPip() {
- EventBus.getDefault().send(new ExpandPipEvent());
+ mPipManager.expandPip();
+ }
+
+ public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
+ mPipManager.hidePipMenu(onStartCallback, onEndCallback);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 04746c1..08208e5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -38,8 +38,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.pip.BasePipManager;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.ExpandPipEvent;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -197,7 +195,6 @@
mMenuController, mInputConsumerController);
mAppOpsListener = new PipAppOpsListener(context, mActivityManager,
mTouchHandler.getMotionHelper());
- EventBus.getDefault().register(this);
}
/**
@@ -210,11 +207,20 @@
/**
* Expands the PIP.
*/
- public final void onBusEvent(ExpandPipEvent event) {
+ @Override
+ public void expandPip() {
mTouchHandler.getMotionHelper().expandPip(false /* skipAnimation */);
}
/**
+ * Hides the PIP menu.
+ */
+ @Override
+ public void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {
+ mMenuController.hideMenu(onStartCallback, onEndCallback);
+ }
+
+ /**
* Sent from KEYCODE_WINDOW handler in PhoneWindowManager, to request the menu to be shown.
*/
public void showPictureInPictureMenu() {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 2dc531a..b746c19 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -72,8 +72,6 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.HidePipMenuEvent;
import java.util.ArrayList;
import java.util.Collections;
@@ -151,7 +149,7 @@
cancelDelayedFinish();
break;
case MESSAGE_HIDE_MENU:
- hideMenu();
+ hideMenu((Runnable) msg.obj);
break;
case MESSAGE_UPDATE_ACTIONS: {
final Bundle data = (Bundle) msg.obj;
@@ -275,7 +273,6 @@
super.onStop();
cancelDelayedFinish();
- EventBus.getDefault().unregister(this);
}
@Override
@@ -335,19 +332,6 @@
// Do nothing
}
- public final void onBusEvent(HidePipMenuEvent event) {
- if (mMenuState != MENU_STATE_NONE) {
- // If the menu is visible in either the closed or full state, then hide the menu and
- // trigger the animation trigger afterwards
- event.getAnimationTrigger().increment();
- hideMenu(() -> {
- mHandler.post(() -> {
- event.getAnimationTrigger().decrement();
- });
- }, true /* notifyMenuVisibility */, false /* isDismissing */);
- }
- }
-
private void showMenu(int menuState, Rect stackBounds, Rect movementBounds,
boolean allowMenuTimeout, boolean resizeMenuOnShow) {
mAllowMenuTimeout = allowMenuTimeout;
@@ -398,8 +382,11 @@
}
private void hideMenu() {
- hideMenu(null /* animationFinishedRunnable */, true /* notifyMenuVisibility */,
- false /* isDismissing */);
+ hideMenu(null);
+ }
+
+ private void hideMenu(Runnable animationEndCallback) {
+ hideMenu(animationEndCallback, true /* notifyMenuVisibility */, false /* isDismissing */);
}
private void hideMenu(final Runnable animationFinishedRunnable, boolean notifyMenuVisibility,
@@ -450,9 +437,6 @@
}
notifyActivityCallback(mMessenger);
- // Register for HidePipMenuEvents once we notify the controller of this activity
- EventBus.getDefault().register(this);
-
ParceledListSlice actions = intent.getParcelableExtra(EXTRA_ACTIONS);
if (actions != null) {
mActions.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
index 360fe73..56b8324 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivityController.java
@@ -19,9 +19,9 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import android.app.ActivityTaskManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
import android.app.IActivityManager;
import android.app.RemoteAction;
import android.content.Context;
@@ -37,14 +37,8 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Log;
-import android.view.IWindowManager;
-
import com.android.systemui.pip.phone.PipMediaController.ActionListener;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.HidePipMenuEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.shared.system.InputConsumerController;
-
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -131,7 +125,7 @@
// The dismiss fraction update is sent frequently, so use a temporary bundle for the message
private Bundle mTmpDismissFractionData = new Bundle();
- private ReferenceCountedTrigger mOnAttachDecrementTrigger;
+ private Runnable mOnAnimationEndRunnable;
private boolean mStartActivityRequested;
private long mStartActivityRequestedTime;
private Messenger mToActivityMessenger;
@@ -171,9 +165,9 @@
case MESSAGE_UPDATE_ACTIVITY_CALLBACK: {
mToActivityMessenger = msg.replyTo;
setStartActivityRequested(false);
- if (mOnAttachDecrementTrigger != null) {
- mOnAttachDecrementTrigger.decrement();
- mOnAttachDecrementTrigger = null;
+ if (mOnAnimationEndRunnable != null) {
+ mOnAnimationEndRunnable.run();
+ mOnAnimationEndRunnable = null;
}
// Mark the menu as invisible once the activity finishes as well
if (mToActivityMessenger == null) {
@@ -188,9 +182,9 @@
private Runnable mStartActivityRequestedTimeoutRunnable = () -> {
setStartActivityRequested(false);
- if (mOnAttachDecrementTrigger != null) {
- mOnAttachDecrementTrigger.decrement();
- mOnAttachDecrementTrigger = null;
+ if (mOnAnimationEndRunnable != null) {
+ mOnAnimationEndRunnable.run();
+ mOnAnimationEndRunnable = null;
}
Log.e(TAG, "Expected start menu activity request timed out");
};
@@ -209,8 +203,6 @@
mActivityManager = activityManager;
mMediaController = mediaController;
mInputConsumerController = inputConsumerController;
-
- EventBus.getDefault().register(this);
}
public boolean isMenuActivityVisible() {
@@ -353,6 +345,36 @@
}
/**
+ * Hides the menu activity.
+ */
+ public void hideMenu(Runnable onStartCallback, Runnable onEndCallback) {
+ if (mStartActivityRequested) {
+ // If the menu has been start-requested, but not actually started, then we defer the
+ // trigger callback until the menu has started and called back to the controller.
+ mOnAnimationEndRunnable = onEndCallback;
+ onStartCallback.run();
+
+ // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
+ // callbacks. Don't continue to wait for the menu to show past some timeout.
+ mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
+ mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
+ START_ACTIVITY_REQUEST_TIMEOUT_MS);
+ } else if (mMenuState != MENU_STATE_NONE && mToActivityMessenger != null) {
+ // If the menu is visible in either the closed or full state, then hide the menu and
+ // trigger the animation trigger afterwards
+ onStartCallback.run();
+ Message m = Message.obtain();
+ m.what = PipMenuActivity.MESSAGE_HIDE_MENU;
+ m.obj = onEndCallback;
+ try {
+ mToActivityMessenger.send(m);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not notify hide menu", e);
+ }
+ }
+ }
+
+ /**
* Preemptively mark the menu as invisible, used when we are directly manipulating the pinned
* stack and don't want to trigger a resize which can animate the stack in a conflicting way
* (ie. when manually expanding or dismissing).
@@ -496,21 +518,6 @@
mStartActivityRequestedTime = requested ? SystemClock.uptimeMillis() : 0;
}
- public final void onBusEvent(HidePipMenuEvent event) {
- if (mStartActivityRequested) {
- // If the menu has been start-requested, but not actually started, then we defer the
- // trigger callback until the menu has started and called back to the controller.
- mOnAttachDecrementTrigger = event.getAnimationTrigger();
- mOnAttachDecrementTrigger.increment();
-
- // Fallback for b/63752800, we have started the PipMenuActivity but it has not made any
- // callbacks. Don't continue to wait for the menu to show past some timeout.
- mHandler.removeCallbacks(mStartActivityRequestedTimeoutRunnable);
- mHandler.postDelayed(mStartActivityRequestedTimeoutRunnable,
- START_ACTIVITY_REQUEST_TIMEOUT_MS);
- }
- }
-
public void dump(PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " ";
pw.println(prefix + TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 43e9db7..e17e0bc 100755
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -758,9 +758,4 @@
WindowManagerWrapper.getInstance().setPipVisibility(visible);
});
}
-
- @Override
- public void dump(PrintWriter pw) {
- // Do nothing
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
deleted file mode 100644
index 003379f..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-/**
- * Constants
- */
-public class Constants {
-
- // TODO: Move into RecentsMetrics
- public static class Metrics {
- // DO NOT MODIFY THE ORDER OF THESE METRICS
- public static final int DismissSourceKeyboard = 0;
- public static final int DismissSourceSwipeGesture = 1;
- public static final int DismissSourceHeaderButton = 2;
- @Deprecated
- public static final int DismissSourceHistorySwipeGesture = 3;
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
deleted file mode 100644
index 90c1099..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsNonSystemUserCallbacks.aidl
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import android.graphics.Rect;
-
-/**
- * Due to the fact that RecentsActivity is per-user, we need to establish an
- * interface (this) for the system user to callback to the secondary users in
- * response to UI events coming in from the system user's SystemUI.
- */
-oneway interface IRecentsNonSystemUserCallbacks {
- void preloadRecents();
- void cancelPreloadingRecents();
- void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate,
- int recentsGrowTarget);
- void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
- void toggleRecents(int recentsGrowTarget);
- void onConfigurationChanged();
- void splitPrimaryTask(int topTaskId, int stackCreateMode, in Rect initialBounds);
- void onDraggingInRecents(float distanceFromTop);
- void onDraggingInRecentsEnded(float velocity);
- void showCurrentUserToast(int msgResId, int msgLength);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
deleted file mode 100644
index e977144..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import android.graphics.Rect;
-
-/**
- * Due to the fact that RecentsActivity is per-user, we need to establish an
- * interface (this) for the non-system user to register itself for callbacks and to
- * callback to the system user to update internal state.
- */
-oneway interface IRecentsSystemUserCallbacks {
- void registerNonSystemUserCallbacks(IBinder nonSystemUserCallbacks, int userId);
-
- void updateRecentsVisibility(boolean visible);
- void startScreenPinning(int taskId);
- void sendRecentsDrawnEvent();
- void sendDockingTopTaskEvent(in Rect initialRect);
- void sendLaunchRecentsEvent();
- void sendDockedFirstAnimationFrameEvent();
- void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
new file mode 100644
index 0000000..661b958
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+
+import android.app.ActivityManager;
+import android.app.trust.TrustManager;
+import android.content.Context;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Display;
+import android.widget.Toast;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.shared.recents.IOverviewProxy;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.phone.StatusBar;
+
+/**
+ * An implementation of the Recents interface which proxies to the OverviewProxyService.
+ */
+public class OverviewProxyRecentsImpl implements RecentsImplementation {
+
+ private final static String TAG = "OverviewProxyRecentsImpl";
+
+ private SysUiServiceProvider mSysUiServiceProvider;
+ private Context mContext;
+ private Handler mHandler;
+ private TrustManager mTrustManager;
+ private OverviewProxyService mOverviewProxyService;
+
+ @Override
+ public void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {
+ mContext = context;
+ mSysUiServiceProvider = sysUiServiceProvider;
+ mHandler = new Handler();
+ mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
+ mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+ }
+
+ @Override
+ public void showRecentApps(boolean triggeredFromAltTab) {
+ IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+ if (overviewProxy != null) {
+ try {
+ overviewProxy.onOverviewShown(triggeredFromAltTab);
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send overview show event to launcher.", e);
+ }
+ } else {
+ // Do nothing
+ }
+ }
+
+ @Override
+ public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
+ IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+ if (overviewProxy != null) {
+ try {
+ overviewProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
+ return;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to send overview hide event to launcher.", e);
+ }
+ } else {
+ // Do nothing
+ }
+ }
+
+ @Override
+ public void toggleRecentApps() {
+ // If connected to launcher service, let it handle the toggle logic
+ IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
+ if (overviewProxy != null) {
+ final Runnable toggleRecents = () -> {
+ try {
+ if (mOverviewProxyService.getProxy() != null) {
+ mOverviewProxyService.getProxy().onOverviewToggle();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
+ }
+ };
+ // Preload only if device for current user is unlocked
+ final StatusBar statusBar = mSysUiServiceProvider.getComponent(StatusBar.class);
+ if (statusBar != null && statusBar.isKeyguardShowing()) {
+ statusBar.executeRunnableDismissingKeyguard(() -> {
+ // Flush trustmanager before checking device locked per user
+ mTrustManager.reportKeyguardShowingChanged();
+ mHandler.post(toggleRecents);
+ }, null, true /* dismissShade */, false /* afterKeyguardGone */,
+ true /* deferred */);
+ } else {
+ toggleRecents.run();
+ }
+ return;
+ } else {
+ // Do nothing
+ }
+ }
+
+ @Override
+ public boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
+ int metricsDockAction) {
+ Point realSize = new Point();
+ if (initialBounds == null) {
+ mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+ .getRealSize(realSize);
+ initialBounds = new Rect(0, 0, realSize.x, realSize.y);
+ }
+
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ final int activityType = runningTask != null
+ ? runningTask.configuration.windowConfiguration.getActivityType()
+ : ACTIVITY_TYPE_UNDEFINED;
+ boolean screenPinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
+ boolean isRunningTaskInHomeOrRecentsStack =
+ activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS;
+ if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
+ if (runningTask.supportsSplitScreenMultiWindow) {
+ if (ActivityManagerWrapper.getInstance().setTaskWindowingModeSplitScreenPrimary(
+ runningTask.id, stackCreateMode, initialBounds)) {
+ // The overview service is handling split screen, so just skip the wait for the
+ // first draw and notify the divider to start animating now
+ final Divider divider = mSysUiServiceProvider.getComponent(Divider.class);
+ if (divider != null) {
+ divider.onRecentsDrawn();
+ }
+ return true;
+ }
+ } else {
+ Toast.makeText(mContext, R.string.dock_non_resizeble_failed_to_dock_text,
+ Toast.LENGTH_SHORT).show();
+ }
+ }
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
rename to packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 1bf8750..19f7675 100644
--- a/packages/SystemUI/src/com/android/systemui/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package com.android.systemui;
+package com.android.systemui.recents;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.view.MotionEvent.ACTION_DOWN;
@@ -42,7 +42,11 @@
import android.provider.Settings;
import android.util.Log;
import android.view.MotionEvent;
-import com.android.systemui.OverviewProxyService.OverviewProxyListener;
+import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
+import com.android.systemui.Prefs;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 74f6c2d..de22d21 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -16,232 +16,29 @@
package com.android.systemui.recents;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
-
-import android.app.ActivityManager;
-import android.app.trust.TrustManager;
-import android.content.ComponentName;
import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Point;
import android.graphics.Rect;
-import android.hardware.display.DisplayManager;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.UserHandle;
import android.provider.Settings;
-import android.util.EventLog;
-import android.util.Log;
-import android.view.Display;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Dependency;
-import com.android.systemui.EventLogConstants;
-import com.android.systemui.EventLogTags;
-import com.android.systemui.OverviewProxyService;
import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SystemUIApplication;
-import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
-import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.SystemUI;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
-import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
-import com.android.systemui.recents.events.component.ShowUserToastEvent;
-import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.model.RecentsTaskLoader;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
-
-import com.android.systemui.statusbar.phone.StatusBar;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Set;
-
/**
- * An implementation of the SystemUI recents component, which supports both system and secondary
- * users.
+ * A proxy to a Recents implementation.
*/
-public class Recents extends SystemUI
- implements RecentsComponent, CommandQueue.Callbacks {
+public class Recents extends SystemUI implements CommandQueue.Callbacks {
- private final static String TAG = "Recents";
-
- public final static int EVENT_BUS_PRIORITY = 1;
- public final static int BIND_TO_SYSTEM_USER_RETRY_DELAY = 5000;
-
- public final static Set<String> RECENTS_ACTIVITIES = new HashSet<>();
- static {
- RECENTS_ACTIVITIES.add(RecentsImpl.RECENTS_ACTIVITY);
- }
-
- private static final String COUNTER_WINDOW_SUPPORTED = "window_enter_supported";
- private static final String COUNTER_WINDOW_UNSUPPORTED = "window_enter_unsupported";
- private static final String COUNTER_WINDOW_INCOMPATIBLE = "window_enter_incompatible";
-
- private static SystemServicesProxy sSystemServicesProxy;
- private static RecentsDebugFlags sDebugFlags;
- private static RecentsTaskLoader sTaskLoader;
- private static RecentsConfiguration sConfiguration;
-
- private OverviewProxyService mOverviewProxyService;
-
- private Handler mHandler;
- private RecentsImpl mImpl;
- private TrustManager mTrustManager;
- private int mDraggingInRecentsCurrentUser;
-
- // Only For system user, this is the callbacks instance we return to each secondary user
- private RecentsSystemUser mSystemToUserCallbacks;
-
- // Only for secondary users, this is the callbacks instance provided by the system user to make
- // calls back
- private IRecentsSystemUserCallbacks mUserToSystemCallbacks;
-
- // The set of runnables to run after binding to the system user's service.
- private final ArrayList<Runnable> mOnConnectRunnables = new ArrayList<>();
-
- // Only for secondary users, this is the death handler for the binder from the system user
- private final IBinder.DeathRecipient mUserToSystemCallbacksDeathRcpt = new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- mUserToSystemCallbacks = null;
- EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
- EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_UNBOUND,
- sSystemServicesProxy.getProcessUser());
-
- // Retry after a fixed duration
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- registerWithSystemUser();
- }
- }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
- }
- };
-
- // Only for secondary users, this is the service connection we use to connect to the system user
- private final ServiceConnection mUserToSystemServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (service != null) {
- mUserToSystemCallbacks = IRecentsSystemUserCallbacks.Stub.asInterface(
- service);
- EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
- EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_SYSTEM_BOUND,
- sSystemServicesProxy.getProcessUser());
-
- // Listen for system user's death, so that we can reconnect later
- try {
- service.linkToDeath(mUserToSystemCallbacksDeathRcpt, 0);
- } catch (RemoteException e) {
- Log.e(TAG, "Lost connection to (System) SystemUI", e);
- }
-
- // Run each of the queued runnables
- runAndFlushOnConnectRunnables();
- }
-
- // Unbind ourselves now that we've registered our callbacks. The
- // binder to the system user are still valid at this point.
- mContext.unbindService(this);
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // Do nothing
- }
- };
-
- /**
- * Returns the callbacks interface that non-system users can call.
- */
- public IBinder getSystemUserCallbacks() {
- return mSystemToUserCallbacks;
- }
-
- public static RecentsTaskLoader getTaskLoader() {
- return sTaskLoader;
- }
-
-
- public static SystemServicesProxy getSystemServices() {
- return sSystemServicesProxy;
- }
-
- public static RecentsConfiguration getConfiguration() {
- return sConfiguration;
- }
-
- public static RecentsDebugFlags getDebugFlags() {
- return sDebugFlags;
- }
+ private RecentsImplementation mImpl;
@Override
public void start() {
- final Resources res = mContext.getResources();
- final int defaultTaskBarBackgroundColor =
- mContext.getColor(R.color.recents_task_bar_default_background_color);
- final int defaultTaskViewBackgroundColor =
- mContext.getColor(R.color.recents_task_view_default_background_color);
- sDebugFlags = new RecentsDebugFlags();
- sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
- sConfiguration = new RecentsConfiguration(mContext);
- sTaskLoader = new RecentsTaskLoader(mContext,
- // TODO: Once we start building the AAR, move these into the loader
- res.getInteger(R.integer.config_recents_max_thumbnail_count),
- res.getInteger(R.integer.config_recents_max_icon_count),
- res.getInteger(R.integer.recents_svelte_level));
- sTaskLoader.setDefaultColors(defaultTaskBarBackgroundColor, defaultTaskViewBackgroundColor);
- mHandler = new Handler();
- mImpl = new RecentsImpl(mContext);
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
-
- // Register with the event bus
- EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
- EventBus.getDefault().register(sSystemServicesProxy, EVENT_BUS_PRIORITY);
- EventBus.getDefault().register(sTaskLoader, EVENT_BUS_PRIORITY);
-
- // Due to the fact that RecentsActivity is per-user, we need to establish and interface for
- // the system user's Recents component to pass events (like show/hide/toggleRecents) to the
- // secondary user, and vice versa (like visibility change, screen pinning).
- final int processUser = sSystemServicesProxy.getProcessUser();
- if (sSystemServicesProxy.isSystemUser(processUser)) {
- // For the system user, initialize an instance of the interface that we can pass to the
- // secondary user
- getComponent(CommandQueue.class).addCallbacks(this);
- mSystemToUserCallbacks = new RecentsSystemUser(mContext, mImpl);
- } else {
- // For the secondary user, bind to the primary user's service to get a persistent
- // interface to register its implementation and to later update its state
- registerWithSystemUser();
- }
+ getComponent(CommandQueue.class).addCallbacks(this);
putComponent(Recents.class, this);
-
- mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
+ mImpl = createRecentsImplementationFromConfig();
+ mImpl.onStart(mContext, this);
}
@Override
@@ -249,13 +46,20 @@
mImpl.onBootCompleted();
}
- public void growRecents() {
- EventBus.getDefault().send(new RecentsGrowingEvent());
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ mImpl.onConfigurationChanged(newConfig);
}
- /**
- * Shows the Recents.
- */
+ @Override
+ public void appTransitionFinished() {
+ mImpl.onAppTransitionFinished();
+ }
+
+ public void growRecents() {
+ mImpl.growRecents();
+ }
+
@Override
public void showRecentApps(boolean triggeredFromAltTab) {
// Ensure the device has been provisioned before allowing the user to interact with
@@ -264,43 +68,9 @@
return;
}
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
- try {
- overviewProxy.onOverviewShown(triggeredFromAltTab);
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send overview show event to launcher.", e);
- }
- }
-
- ActivityManagerWrapper.getInstance().closeSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
- int recentsGrowTarget = getComponent(Divider.class).getView().growsRecents();
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
- true /* animate */, recentsGrowTarget);
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.showRecents(triggeredFromAltTab, false /* draggingInRecents */,
- true /* animate */, recentsGrowTarget);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
+ mImpl.showRecentApps(triggeredFromAltTab);
}
- /**
- * Hides the Recents.
- */
@Override
public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
// Ensure the device has been provisioned before allowing the user to interact with
@@ -309,39 +79,9 @@
return;
}
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
- try {
- overviewProxy.onOverviewHidden(triggeredFromAltTab, triggeredFromHomeKey);
- return;
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to send overview hide event to launcher.", e);
- }
- }
-
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.hideRecents(triggeredFromAltTab, triggeredFromHomeKey);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
+ mImpl.hideRecentApps(triggeredFromAltTab, triggeredFromHomeKey);
}
- /**
- * Toggles the Recents activity.
- */
@Override
public void toggleRecentApps() {
// Ensure the device has been provisioned before allowing the user to interact with
@@ -350,57 +90,9 @@
return;
}
- // If connected to launcher service, let it handle the toggle logic
- IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();
- if (overviewProxy != null) {
- final Runnable toggleRecents = () -> {
- try {
- if (mOverviewProxyService.getProxy() != null) {
- mOverviewProxyService.getProxy().onOverviewToggle();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Cannot send toggle recents through proxy service.", e);
- }
- };
- // Preload only if device for current user is unlocked
- final StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && statusBar.isKeyguardShowing()) {
- statusBar.executeRunnableDismissingKeyguard(() -> {
- // Flush trustmanager before checking device locked per user
- mTrustManager.reportKeyguardShowingChanged();
- mHandler.post(toggleRecents);
- }, null, true /* dismissShade */, false /* afterKeyguardGone */,
- true /* deferred */);
- } else {
- toggleRecents.run();
- }
- return;
- }
-
- int growTarget = getComponent(Divider.class).getView().growsRecents();
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.toggleRecents(growTarget);
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.toggleRecents(growTarget);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
+ mImpl.toggleRecentApps();
}
- /**
- * Preloads info for the Recents activity.
- */
@Override
public void preloadRecentApps() {
// Ensure the device has been provisioned before allowing the user to interact with
@@ -409,29 +101,7 @@
return;
}
- if (mOverviewProxyService.getProxy() != null) {
- // TODO: Proxy to Launcher
- return;
- }
-
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.preloadRecents();
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.preloadRecents();
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
+ mImpl.preloadRecentApps();
}
@Override
@@ -442,32 +112,9 @@
return;
}
- if (mOverviewProxyService.getProxy() != null) {
- // TODO: Proxy to Launcher
- return;
- }
-
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.cancelPreloadingRecents();
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.cancelPreloadingRecents();
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
+ mImpl.cancelPreloadRecentApps();
}
- @Override
public boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
int metricsDockAction) {
// Ensure the device has been provisioned before allowing the user to interact with
@@ -476,380 +123,7 @@
return false;
}
- Point realSize = new Point();
- if (initialBounds == null) {
- mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
- .getRealSize(realSize);
- initialBounds = new Rect(0, 0, realSize.x, realSize.y);
- }
-
- int currentUser = sSystemServicesProxy.getCurrentUser();
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- final int activityType = runningTask != null
- ? runningTask.configuration.windowConfiguration.getActivityType()
- : ACTIVITY_TYPE_UNDEFINED;
- boolean screenPinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
- boolean isRunningTaskInHomeOrRecentsStack =
- activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS;
- if (runningTask != null && !isRunningTaskInHomeOrRecentsStack && !screenPinningActive) {
- logDockAttempt(mContext, runningTask.topActivity, runningTask.resizeMode);
- if (runningTask.supportsSplitScreenMultiWindow) {
- if (metricsDockAction != -1) {
- MetricsLogger.action(mContext, metricsDockAction,
- runningTask.topActivity.flattenToShortString());
- }
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.splitPrimaryTask(runningTask.id, stackCreateMode, initialBounds);
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.splitPrimaryTask(runningTask.id, stackCreateMode,
- initialBounds);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
- mDraggingInRecentsCurrentUser = currentUser;
-
- if (mOverviewProxyService.getProxy() != null) {
- // The overview service is handling split screen, so just skip the wait for the
- // first draw and notify the divider to start animating now
- EventBus.getDefault().post(new RecentsDrawnEvent());
- }
-
- return true;
- } else {
- EventBus.getDefault().send(new ShowUserToastEvent(
- R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT));
- return false;
- }
- } else {
- return false;
- }
- }
-
- public static void logDockAttempt(Context ctx, ComponentName activity, int resizeMode) {
- if (resizeMode == ActivityInfo.RESIZE_MODE_UNRESIZEABLE) {
- MetricsLogger.action(ctx, MetricsEvent.ACTION_WINDOW_DOCK_UNRESIZABLE,
- activity.flattenToShortString());
- }
- MetricsLogger.count(ctx, getMetricsCounterForResizeMode(resizeMode), 1);
- }
-
- private static String getMetricsCounterForResizeMode(int resizeMode) {
- switch (resizeMode) {
- case ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE:
- return COUNTER_WINDOW_UNSUPPORTED;
- case ActivityInfo.RESIZE_MODE_RESIZEABLE:
- case ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION:
- return COUNTER_WINDOW_SUPPORTED;
- default:
- return COUNTER_WINDOW_INCOMPATIBLE;
- }
- }
-
- public void showNextAffiliatedTask() {
- // Ensure the device has been provisioned before allowing the user to interact with
- // recents
- if (!isUserSetup()) {
- return;
- }
-
- mImpl.showNextAffiliatedTask();
- }
-
- public void showPrevAffiliatedTask() {
- // Ensure the device has been provisioned before allowing the user to interact with
- // recents
- if (!isUserSetup()) {
- return;
- }
-
- mImpl.showPrevAffiliatedTask();
- }
-
- @Override
- public void appTransitionFinished() {
- if (!Recents.getConfiguration().isLowRamDevice) {
- // Fallback, reset the flag once an app transition ends
- EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(
- false /* waitingForTransitionStart */));
- }
- }
-
- /**
- * Updates on configuration change.
- */
- public void onConfigurationChanged(Configuration newConfig) {
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.onConfigurationChanged();
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.onConfigurationChanged();
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
- }
-
- /**
- * Handle Recents activity visibility changed.
- */
- public final void onBusEvent(final RecentsVisibilityChangedEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- int processUser = ssp.getProcessUser();
- if (ssp.isSystemUser(processUser)) {
- mImpl.onVisibilityChanged(event.applicationContext, event.visible);
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.updateRecentsVisibility(event.visible);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
-
- // This will catch the cases when a user launches from recents to another app
- // (and vice versa) that is not in the recents stack (such as home or bugreport) and it
- // would not reset the wait for transition flag. This will catch it and make sure that the
- // flag is reset.
- if (!event.visible) {
- mImpl.setWaitingForTransitionStart(false);
- }
- }
-
- public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- int processUser = ssp.getProcessUser();
- if (ssp.isSystemUser(processUser)) {
- final Divider divider = getComponent(Divider.class);
- if (divider != null) {
- divider.onDockedFirstAnimationFrame();
- }
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.sendDockedFirstAnimationFrameEvent();
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
- }
-
- /**
- * Handle screen pinning request.
- */
- public final void onBusEvent(final ScreenPinningRequestEvent event) {
- int processUser = sSystemServicesProxy.getProcessUser();
- if (sSystemServicesProxy.isSystemUser(processUser)) {
- mImpl.onStartScreenPinning(event.applicationContext, event.taskId);
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.startScreenPinning(event.taskId);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
- }
-
- public final void onBusEvent(final RecentsDrawnEvent event) {
- int processUser = sSystemServicesProxy.getProcessUser();
- if (sSystemServicesProxy.isSystemUser(processUser)) {
- final Divider divider = getComponent(Divider.class);
- if (divider != null) {
- divider.onRecentsDrawn();
- }
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.sendRecentsDrawnEvent();
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
- }
-
- public final void onBusEvent(final DockedTopTaskEvent event) {
- int processUser = sSystemServicesProxy.getProcessUser();
- if (sSystemServicesProxy.isSystemUser(processUser)) {
- final Divider divider = getComponent(Divider.class);
- if (divider != null) {
- divider.onDockedTopTask();
- }
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.sendDockingTopTaskEvent(event.initialRect);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
- }
-
- public final void onBusEvent(final RecentsActivityStartingEvent event) {
- int processUser = sSystemServicesProxy.getProcessUser();
- if (sSystemServicesProxy.isSystemUser(processUser)) {
- final Divider divider = getComponent(Divider.class);
- if (divider != null) {
- divider.onRecentsActivityStarting();
- }
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.sendLaunchRecentsEvent();
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
- }
-
- public final void onBusEvent(LaunchTaskFailedEvent event) {
- // Reset the transition when tasks fail to launch
- mImpl.setWaitingForTransitionStart(false);
- }
-
- public final void onBusEvent(ConfigurationChangedEvent event) {
- // Update the configuration for the Recents component when the activity configuration
- // changes as well
- mImpl.onConfigurationChanged();
- }
-
- public final void onBusEvent(ShowUserToastEvent event) {
- int currentUser = sSystemServicesProxy.getCurrentUser();
- if (sSystemServicesProxy.isSystemUser(currentUser)) {
- mImpl.onShowCurrentUserToast(event.msgResId, event.msgLength);
- } else {
- if (mSystemToUserCallbacks != null) {
- IRecentsNonSystemUserCallbacks callbacks =
- mSystemToUserCallbacks.getNonSystemUserRecentsForUser(currentUser);
- if (callbacks != null) {
- try {
- callbacks.showCurrentUserToast(event.msgResId, event.msgLength);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- } else {
- Log.e(TAG, "No SystemUI callbacks found for user: " + currentUser);
- }
- }
- }
- }
-
- public final void onBusEvent(SetWaitingForTransitionStartEvent event) {
- int processUser = sSystemServicesProxy.getProcessUser();
- if (sSystemServicesProxy.isSystemUser(processUser)) {
- mImpl.setWaitingForTransitionStart(event.waitingForTransitionStart);
- } else {
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.setWaitingForTransitionStartEvent(
- event.waitingForTransitionStart);
- } catch (RemoteException e) {
- Log.e(TAG, "Callback failed", e);
- }
- }
- });
- }
- }
-
- /**
- * Attempts to register with the system user.
- */
- private void registerWithSystemUser() {
- final int processUser = sSystemServicesProxy.getProcessUser();
- postToSystemUser(new Runnable() {
- @Override
- public void run() {
- try {
- mUserToSystemCallbacks.registerNonSystemUserCallbacks(
- new RecentsImplProxy(mImpl), processUser);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register", e);
- }
- }
- });
- }
-
- /**
- * Runs the runnable in the system user's Recents context, connecting to the service if
- * necessary.
- */
- private void postToSystemUser(final Runnable onConnectRunnable) {
- mOnConnectRunnables.add(onConnectRunnable);
- if (mUserToSystemCallbacks == null) {
- Intent systemUserServiceIntent = new Intent();
- systemUserServiceIntent.setClass(mContext, RecentsSystemUserService.class);
- boolean bound = mContext.bindServiceAsUser(systemUserServiceIntent,
- mUserToSystemServiceConnection, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
- EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
- EventLogConstants.SYSUI_RECENTS_CONNECTION_USER_BIND_SERVICE,
- sSystemServicesProxy.getProcessUser());
- if (!bound) {
- // Retry after a fixed duration
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- registerWithSystemUser();
- }
- }, BIND_TO_SYSTEM_USER_RETRY_DELAY);
- }
- } else {
- runAndFlushOnConnectRunnables();
- }
- }
-
- /**
- * Runs all the queued runnables after a service connection is made.
- */
- private void runAndFlushOnConnectRunnables() {
- for (Runnable r : mOnConnectRunnables) {
- r.run();
- }
- mOnConnectRunnables.clear();
+ return mImpl.splitPrimaryTask(stackCreateMode, initialBounds, metricsDockAction);
}
/**
@@ -861,9 +135,30 @@
(Settings.Secure.getInt(cr, Settings.Secure.USER_SETUP_COMPLETE, 0) != 0);
}
+ /**
+ * @return The recents implementation from the config.
+ */
+ private RecentsImplementation createRecentsImplementationFromConfig() {
+ final String clsName = mContext.getString(R.string.config_recentsComponent);
+ if (clsName == null || clsName.length() == 0) {
+ throw new RuntimeException("No recents component configured", null);
+ }
+ Class<?> cls = null;
+ try {
+ cls = mContext.getClassLoader().loadClass(clsName);
+ } catch (Throwable t) {
+ throw new RuntimeException("Error loading recents component: " + clsName, t);
+ }
+ try {
+ RecentsImplementation impl = (RecentsImplementation) cls.newInstance();
+ return impl;
+ } catch (Throwable t) {
+ throw new RuntimeException("Error creating recents component: " + clsName, t);
+ }
+ }
+
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.println("Recents");
- pw.println(" currentUserId=" + SystemServicesProxy.getInstance(mContext).getCurrentUser());
+ mImpl.dump(pw);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
deleted file mode 100644
index 36a1255..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_HOME_KEY;
-
-import android.app.Activity;
-import android.app.ActivityOptions;
-import android.app.TaskStackBuilder;
-import android.app.WallpaperManager;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.res.Configuration;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.ViewTreeObserver.OnPreDrawListener;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams;
-
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.LatencyTracker;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.Dependency;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
-import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
-import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
-import com.android.systemui.recents.events.activity.PackagesChangedEvent;
-import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
-import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
-import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
-import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
-import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
-import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
-import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
-import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
-import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
-import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
-import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
-import com.android.systemui.recents.events.ui.UserInteractionEvent;
-import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
-import com.android.systemui.shared.recents.model.RecentsTaskLoader;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.recents.views.RecentsView;
-import com.android.systemui.recents.views.SystemBarScrimViews;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-
-import com.android.systemui.shared.system.WindowManagerWrapper;
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-/**
- * The main Recents activity that is started from RecentsComponent.
- */
-public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreDrawListener,
- ColorExtractor.OnColorsChangedListener {
-
- private final static String TAG = "RecentsActivity";
- private final static boolean DEBUG = false;
-
- public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
- public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150;
-
- private PackageMonitor mPackageMonitor = new PackageMonitor() {
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- RecentsActivity.this.onPackageChanged(packageName, getChangingUserId());
- }
-
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- RecentsActivity.this.onPackageChanged(packageName, getChangingUserId());
- return true;
- }
-
- @Override
- public void onPackageModified(String packageName) {
- RecentsActivity.this.onPackageChanged(packageName, getChangingUserId());
- }
- };
- private Handler mHandler = new Handler();
- private long mLastTabKeyEventTime;
- private boolean mFinishedOnStartup;
- private boolean mIgnoreAltTabRelease;
- private boolean mIsVisible;
- private boolean mRecentsStartRequested;
- private Configuration mLastConfig;
-
- // Top level views
- private RecentsView mRecentsView;
- private SystemBarScrimViews mScrimViews;
- private View mIncompatibleAppOverlay;
-
- // Runnables to finish the Recents activity
- private Intent mHomeIntent;
-
- // The trigger to automatically launch the current task
- private int mFocusTimerDuration;
- private final UserInteractionEvent mUserInteractionEvent = new UserInteractionEvent();
-
- // Theme and colors
- private SysuiColorExtractor mColorExtractor;
- private boolean mUsingDarkText;
-
- /**
- * A common Runnable to finish Recents by launching Home with an animation depending on the
- * last activity launch state. Generally we always launch home when we exit Recents rather than
- * just finishing the activity since we don't know what is behind Recents in the task stack.
- */
- class LaunchHomeRunnable implements Runnable {
-
- Intent mLaunchIntent;
- ActivityOptions mOpts;
-
- /**
- * Creates a finish runnable that starts the specified intent.
- */
- public LaunchHomeRunnable(Intent launchIntent, ActivityOptions opts) {
- mLaunchIntent = launchIntent;
- mOpts = opts;
- }
-
- @Override
- public void run() {
- try {
- mHandler.post(() -> {
- ActivityOptions opts = mOpts;
- if (opts == null) {
- opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
- R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
- }
- startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
- });
- } catch (Exception e) {
- Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
- }
- }
- }
-
- /**
- * Broadcast receiver to handle messages from the system
- */
- final BroadcastReceiver mSystemBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context ctx, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- // When the screen turns off, dismiss Recents to Home
- dismissRecentsToHomeIfVisible(false);
- } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
- // When switching users, dismiss Recents to Home similar to screen off
- finish();
- }
- }
- };
-
- private final OnPreDrawListener mRecentsDrawnEventListener =
- new ViewTreeObserver.OnPreDrawListener() {
- @Override
- public boolean onPreDraw() {
- mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- EventBus.getDefault().post(new RecentsDrawnEvent());
- if (LatencyTracker.isEnabled(getApplicationContext())) {
- DejankUtils.postAfterTraversal(() -> LatencyTracker.getInstance(
- getApplicationContext()).onActionEnd(
- LatencyTracker.ACTION_TOGGLE_RECENTS));
- }
- DejankUtils.postAfterTraversal(() -> {
- Recents.getTaskLoader().startLoader(RecentsActivity.this);
- Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(true);
- });
- return true;
- }
- };
-
- /**
- * Dismisses recents if we are already visible and the intent is to toggle the recents view.
- */
- boolean dismissRecentsToFocusedTask(int logCategory) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.isRecentsActivityVisible()) {
- // If we have a focused Task, launch that Task now
- if (mRecentsView.launchFocusedTask(logCategory)) return true;
- }
- return false;
- }
-
- /**
- * Dismisses recents back to the launch target task.
- */
- boolean dismissRecentsToLaunchTargetTaskOrHome() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.isRecentsActivityVisible()) {
- // If we have a focused Task, launch that Task now
- if (mRecentsView.launchPreviousTask()) return true;
- // If none of the other cases apply, then just go Home
- dismissRecentsToHome(true /* animateTaskViews */);
- }
- return false;
- }
-
- /**
- * Dismisses recents if we are already visible and the intent is to toggle the recents view.
- */
- boolean dismissRecentsToFocusedTaskOrHome() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.isRecentsActivityVisible()) {
- // If we have a focused Task, launch that Task now
- if (mRecentsView.launchFocusedTask(0 /* logCategory */)) return true;
- // If none of the other cases apply, then just go Home
- dismissRecentsToHome(true /* animateTaskViews */);
- return true;
- }
- return false;
- }
-
- /**
- * Dismisses Recents directly to Home without checking whether it is currently visible.
- */
- void dismissRecentsToHome(boolean animateTaskViews) {
- dismissRecentsToHome(animateTaskViews, null);
- }
-
- /**
- * Dismisses Recents directly to Home without checking whether it is currently visible.
- *
- * @param overrideAnimation If not null, will override the default animation that is based on
- * how Recents was launched.
- */
- void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
- DismissRecentsToHomeAnimationStarted dismissEvent =
- new DismissRecentsToHomeAnimationStarted(animateTaskViews);
- dismissEvent.addPostAnimationCallback(new LaunchHomeRunnable(mHomeIntent,
- overrideAnimation));
- ActivityManagerWrapper.getInstance().closeSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
- EventBus.getDefault().send(dismissEvent);
- }
-
- /** Dismisses Recents directly to Home if we currently aren't transitioning. */
- boolean dismissRecentsToHomeIfVisible(boolean animated) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.isRecentsActivityVisible()) {
- // Return to Home
- dismissRecentsToHome(animated);
- return true;
- }
- return false;
- }
-
- /** Called with the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- mFinishedOnStartup = false;
-
- // In the case that the activity starts up before the Recents component has initialized
- // (usually when debugging/pushing the SysUI apk), just finish this activity.
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp == null) {
- mFinishedOnStartup = true;
- finish();
- return;
- }
-
- // Register this activity with the event bus
- EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
-
- // Initialize the package monitor
- mPackageMonitor.register(this, Looper.getMainLooper(), UserHandle.ALL,
- true /* externalStorage */);
-
- // Select theme based on wallpaper colors
- mColorExtractor = Dependency.get(SysuiColorExtractor.class);
- mColorExtractor.addOnColorsChangedListener(this);
- mUsingDarkText = mColorExtractor.getColors(ColorExtractor.TYPE_DARK,
- WallpaperManager.FLAG_SYSTEM, true).supportsDarkText();
- setTheme(mUsingDarkText ? R.style.RecentsTheme_Wallpaper_Light
- : R.style.RecentsTheme_Wallpaper);
-
- // Set the Recents layout
- setContentView(R.layout.recents);
- takeKeyEvents(true);
- mRecentsView = findViewById(R.id.recents_view);
- mScrimViews = new SystemBarScrimViews(this);
- getWindow().getAttributes().privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
- if (Recents.getConfiguration().isLowRamDevice) {
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
- }
-
- mLastConfig = new Configuration(Utilities.getAppConfiguration(this));
-
- // Set the window background
- mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode());
-
- // Create the home intent runnable
- mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
- mHomeIntent.addCategory(Intent.CATEGORY_HOME);
- mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
- // Register the broadcast receiver to handle messages when the screen is turned off
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SCREEN_OFF);
- filter.addAction(Intent.ACTION_USER_SWITCHED);
- registerReceiver(mSystemBroadcastReceiver, filter);
-
- getWindow().addPrivateFlags(LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION);
- }
-
- @Override
- protected void onStart() {
- super.onStart();
-
- // Reload the stack view whenever we are made visible again
- reloadStackView();
-
- // Notify that recents is now visible
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
- MetricsLogger.visible(this, MetricsEvent.OVERVIEW_ACTIVITY);
-
- // Getting system scrim colors ignoring wallpaper visibility since it should never be grey.
- ColorExtractor.GradientColors systemColors = mColorExtractor.getColors(
- ColorExtractor.TYPE_DARK, WallpaperManager.FLAG_SYSTEM, true);
- // We don't want to interpolate colors because we're defining the initial state.
- // Gradient should be set/ready when you open "Recents".
- mRecentsView.setScrimColors(systemColors, false);
-
- // Notify of the next draw
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
-
- // If Recents was restarted, then it should complete the enter animation with partially
- // reset launch state with dock, app and home set to false
- Object isRelaunching = getLastNonConfigurationInstance();
- if (isRelaunching != null && isRelaunching instanceof Boolean && (boolean) isRelaunching) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- launchState.launchedViaDockGesture = false;
- launchState.launchedFromApp = false;
- launchState.launchedFromHome = false;
- onEnterAnimationComplete();
- }
- mRecentsStartRequested = false;
- }
-
- @Override
- public void onColorsChanged(ColorExtractor colorExtractor, int which) {
- if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
- // Recents doesn't care about the wallpaper being visible or not, it always
- // wants to scrim with wallpaper colors
- ColorExtractor.GradientColors colors = mColorExtractor.getColors(
- WallpaperManager.FLAG_SYSTEM,
- ColorExtractor.TYPE_DARK, true /* ignoreVis */);
- boolean darkText = colors.supportsDarkText();
- if (darkText != mUsingDarkText) {
- mUsingDarkText = darkText;
- setTheme(mUsingDarkText ? R.style.RecentsTheme_Wallpaper_Light
- : R.style.RecentsTheme_Wallpaper);
- mRecentsView.reevaluateStyles();
- }
- mRecentsView.setScrimColors(colors, true /* animated */);
- }
- }
-
- /**
- * Reloads the stack views upon launching Recents.
- */
- private void reloadStackView() {
- // If the Recents component has preloaded a load plan, then use that to prevent
- // reconstructing the task stack
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan loadPlan = RecentsImpl.consumeInstanceLoadPlan();
- if (loadPlan == null) {
- loadPlan = new RecentsTaskLoadPlan(this);
- }
-
- // Start loading tasks according to the load plan
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- if (!loadPlan.hasTasks()) {
- loader.preloadTasks(loadPlan, launchState.launchedToTaskId);
- }
-
- RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
- loadOpts.runningTaskId = launchState.launchedToTaskId;
- loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
- loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
- loader.loadTasks(loadPlan, loadOpts);
- TaskStack stack = loadPlan.getTaskStack();
- mRecentsView.onReload(stack, mIsVisible);
-
- // Update the nav bar scrim, but defer the animation until the enter-window event
- boolean animateNavBarScrim = !launchState.launchedViaDockGesture;
- mScrimViews.updateNavBarScrim(animateNavBarScrim, stack.getTaskCount() > 0, null);
-
- // If this is a new instance relaunched by AM, without going through the normal mechanisms,
- // then we have to manually trigger the enter animation state
- boolean wasLaunchedByAm = !launchState.launchedFromHome &&
- !launchState.launchedFromApp;
- if (wasLaunchedByAm) {
- EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
- }
-
- // Keep track of whether we launched from the nav bar button or via alt-tab
- if (launchState.launchedWithAltTab) {
- MetricsLogger.count(this, "overview_trigger_alttab", 1);
- } else {
- MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
- }
-
- // Keep track of whether we launched from an app or from home
- if (launchState.launchedFromApp) {
- Task launchTarget = stack.getLaunchTarget();
- int launchTaskIndexInStack = launchTarget != null
- ? stack.indexOfTask(launchTarget)
- : 0;
- MetricsLogger.count(this, "overview_source_app", 1);
- // If from an app, track the stack index of the app in the stack (for affiliated tasks)
- MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
- } else {
- MetricsLogger.count(this, "overview_source_home", 1);
- }
-
- // Keep track of the total stack task count
- int taskCount = mRecentsView.getStack().getTaskCount();
- MetricsLogger.histogram(this, "overview_task_count", taskCount);
-
- // After we have resumed, set the visible state until the next onStop() call
- mIsVisible = true;
- }
-
- @Override
- public void onEnterAnimationComplete() {
- super.onEnterAnimationComplete();
- EventBus.getDefault().send(new EnterRecentsWindowAnimationCompletedEvent());
-
- // Workaround for b/64694148: The animation started callback is not made (see
- // RecentsImpl.getThumbnailTransitionActivityOptions) so reset the transition-waiting state
- // once the enter animation has completed.
- EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
- }
-
- @Override
- public Object onRetainNonConfigurationInstance() {
- return true;
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- mIgnoreAltTabRelease = false;
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
-
- // Notify of the config change
- Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
- int numStackTasks = mRecentsView.getStack().getTaskCount();
- EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
- mLastConfig.orientation != newDeviceConfiguration.orientation,
- mLastConfig.densityDpi != newDeviceConfiguration.densityDpi, numStackTasks > 0));
-
- mLastConfig.updateFrom(newDeviceConfiguration);
- }
-
- @Override
- public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
- super.onMultiWindowModeChanged(isInMultiWindowMode);
-
- // Set the window background
- mRecentsView.updateBackgroundScrim(getWindow(), isInMultiWindowMode);
-
- // Reload the task stack view if we are still visible to pick up the change in tasks that
- // result from entering/exiting multi-window
- if (mIsVisible) {
- reloadTaskStack(isInMultiWindowMode, true /* sendConfigChangedEvent */);
- }
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- // Notify that recents is now hidden
- mIsVisible = false;
- EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
- MetricsLogger.hidden(this, MetricsEvent.OVERVIEW_ACTIVITY);
- Recents.getTaskLoader().getHighResThumbnailLoader().setVisible(false);
-
- // When recents starts again before onStop, do not reset launch flags so entrance animation
- // can run
- if (!isChangingConfigurations() && !mRecentsStartRequested) {
- // Workaround for b/22542869, if the RecentsActivity is started again, but without going
- // through SystemUI, we need to reset the config launch flags to ensure that we do not
- // wait on the system to send a signal that was never queued.
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- launchState.reset();
- }
-
- // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
- Recents.getSystemServices().gc();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
-
- // In the case that the activity finished on startup, just skip the unregistration below
- if (mFinishedOnStartup) {
- return;
- }
-
- // Unregister the system broadcast receivers
- unregisterReceiver(mSystemBroadcastReceiver);
-
- // Unregister any broadcast receivers for the task loader
- mPackageMonitor.unregister();
-
- EventBus.getDefault().unregister(this);
- }
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- EventBus.getDefault().register(mScrimViews, EVENT_BUS_PRIORITY);
- }
-
- @Override
- public void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- EventBus.getDefault().unregister(mScrimViews);
- }
-
- @Override
- public void onTrimMemory(int level) {
- RecentsTaskLoader loader = Recents.getTaskLoader();
- if (loader != null) {
- loader.onTrimMemory(level);
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_TAB: {
- int altTabKeyDelay = getResources().getInteger(R.integer.recents_alt_tab_key_delay);
- boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
- mLastTabKeyEventTime) > altTabKeyDelay;
- if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
- // Focus the next task in the stack
- final boolean backward = event.isShiftPressed();
- if (backward) {
- EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
- } else {
- EventBus.getDefault().send(new FocusNextTaskViewEvent());
- }
- mLastTabKeyEventTime = SystemClock.elapsedRealtime();
-
- // In the case of another ALT event, don't ignore the next release
- if (event.isAltPressed()) {
- mIgnoreAltTabRelease = false;
- }
- }
- return true;
- }
- case KeyEvent.KEYCODE_DPAD_UP:
- case KeyEvent.KEYCODE_DPAD_DOWN:
- case KeyEvent.KEYCODE_DPAD_LEFT:
- case KeyEvent.KEYCODE_DPAD_RIGHT: {
- final Direction direction = NavigateTaskViewEvent.getDirectionFromKeyCode(keyCode);
- EventBus.getDefault().send(new NavigateTaskViewEvent(direction));
- return true;
- }
- case KeyEvent.KEYCODE_DEL:
- case KeyEvent.KEYCODE_FORWARD_DEL: {
- if (event.getRepeatCount() <= 0) {
- EventBus.getDefault().send(new DismissFocusedTaskViewEvent());
-
- // Keep track of deletions by keyboard
- MetricsLogger.histogram(this, "overview_task_dismissed_source",
- Constants.Metrics.DismissSourceKeyboard);
- return true;
- }
- }
- default:
- break;
- }
- return super.onKeyDown(keyCode, event);
- }
-
- @Override
- public void onUserInteraction() {
- EventBus.getDefault().send(mUserInteractionEvent);
- }
-
- @Override
- public void onBackPressed() {
- // Back behaves like the recents button so just trigger a toggle event
- EventBus.getDefault().send(new ToggleRecentsEvent());
- }
-
- /**** EventBus events ****/
-
- public final void onBusEvent(ToggleRecentsEvent event) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (launchState.launchedFromHome) {
- dismissRecentsToHome(true /* animateTaskViews */);
- } else {
- dismissRecentsToLaunchTargetTaskOrHome();
- }
- }
-
- public final void onBusEvent(RecentsActivityStartingEvent event) {
- mRecentsStartRequested = true;
- }
-
- public final void onBusEvent(HideRecentsEvent event) {
- if (event.triggeredFromAltTab) {
- // If we are hiding from releasing Alt-Tab, dismiss Recents to the focused app
- if (!mIgnoreAltTabRelease) {
- dismissRecentsToFocusedTaskOrHome();
- }
- } else if (event.triggeredFromHomeKey) {
- dismissRecentsToHome(true /* animateTaskViews */);
-
- // Cancel any pending dozes
- EventBus.getDefault().send(mUserInteractionEvent);
- } else {
- // Do nothing
- }
- }
-
- public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- mRecentsView.invalidate();
- }
-
- public final void onBusEvent(ExitRecentsWindowFirstAnimationFrameEvent event) {
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- mRecentsView.invalidate();
- }
-
- public final void onBusEvent(DockedFirstAnimationFrameEvent event) {
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- mRecentsView.invalidate();
- }
-
- public final void onBusEvent(CancelEnterRecentsWindowAnimationEvent event) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- int launchToTaskId = launchState.launchedToTaskId;
- if (launchToTaskId != -1 &&
- (event.launchTask == null || launchToTaskId != event.launchTask.key.id)) {
- ActivityManagerWrapper am = ActivityManagerWrapper.getInstance();
- am.cancelWindowTransition(launchState.launchedToTaskId);
- }
- }
-
- public final void onBusEvent(ShowApplicationInfoEvent event) {
- // Create a new task stack with the application info details activity
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
- Uri.fromParts("package", event.task.key.getComponent().getPackageName(), null));
- intent.setComponent(intent.resolveActivity(getPackageManager()));
- TaskStackBuilder.create(this)
- .addNextIntentWithParentStack(intent).startActivities(null,
- new UserHandle(event.task.key.userId));
-
- // Keep track of app-info invocations
- MetricsLogger.count(this, "overview_app_info", 1);
- }
-
- public final void onBusEvent(ShowIncompatibleAppOverlayEvent event) {
- if (mIncompatibleAppOverlay == null) {
- mIncompatibleAppOverlay = Utilities.findViewStubById(this,
- R.id.incompatible_app_overlay_stub).inflate();
- mIncompatibleAppOverlay.setWillNotDraw(false);
- mIncompatibleAppOverlay.setVisibility(View.VISIBLE);
- }
- mIncompatibleAppOverlay.animate()
- .alpha(1f)
- .setDuration(INCOMPATIBLE_APP_ALPHA_DURATION)
- .setInterpolator(Interpolators.ALPHA_IN)
- .start();
- }
-
- public final void onBusEvent(HideIncompatibleAppOverlayEvent event) {
- if (mIncompatibleAppOverlay != null) {
- mIncompatibleAppOverlay.animate()
- .alpha(0f)
- .setDuration(INCOMPATIBLE_APP_ALPHA_DURATION)
- .setInterpolator(Interpolators.ALPHA_OUT)
- .start();
- }
- }
-
- public final void onBusEvent(DeleteTaskDataEvent event) {
- // Remove any stored data from the loader
- RecentsTaskLoader loader = Recents.getTaskLoader();
- loader.deleteTaskData(event.task, false);
-
- // Remove the task from activity manager
- ActivityManagerWrapper.getInstance().removeTask(event.task.key.id);
- }
-
- public final void onBusEvent(TaskViewDismissedEvent event) {
- mRecentsView.updateScrimOpacity();
- }
-
- public final void onBusEvent(AllTaskViewsDismissedEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.hasDockedTask()) {
- mRecentsView.showEmptyView(event.msgResId);
- } else {
- // Just go straight home (no animation necessary because there are no more task views)
- dismissRecentsToHome(false /* animateTaskViews */);
- }
-
- // Keep track of all-deletions
- MetricsLogger.count(this, "overview_task_all_dismissed", 1);
- }
-
- public final void onBusEvent(LaunchTaskSucceededEvent event) {
- MetricsLogger.histogram(this, "overview_task_launch_index", event.taskIndexFromStackFront);
- }
-
- public final void onBusEvent(LaunchTaskFailedEvent event) {
- // Return to Home
- dismissRecentsToHome(true /* animateTaskViews */);
-
- MetricsLogger.count(this, "overview_task_launch_failed", 1);
- }
-
- public final void onBusEvent(ScreenPinningRequestEvent event) {
- MetricsLogger.count(this, "overview_screen_pinned", 1);
- }
-
- public final void onBusEvent(StackViewScrolledEvent event) {
- // Once the user has scrolled while holding alt-tab, then we should ignore the release of
- // the key
- mIgnoreAltTabRelease = true;
- }
-
- public final void onBusEvent(final DockedTopTaskEvent event) {
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(mRecentsDrawnEventListener);
- mRecentsView.invalidate();
- }
-
- public final void onBusEvent(final ActivityUnpinnedEvent event) {
- if (mIsVisible) {
- // Skip the configuration change event as the PiP activity does not actually affect the
- // config of recents
- reloadTaskStack(isInMultiWindowMode(), false /* sendConfigChangedEvent */);
- }
- }
-
- private void reloadTaskStack(boolean isInMultiWindowMode, boolean sendConfigChangedEvent) {
- // Reload the task stack completely
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(this);
- loader.preloadTasks(loadPlan, -1 /* runningTaskId */);
-
- RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
- loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
- loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
- loader.loadTasks(loadPlan, loadOpts);
-
- TaskStack stack = loadPlan.getTaskStack();
- int numStackTasks = stack.getTaskCount();
- boolean showDeferredAnimation = numStackTasks > 0;
-
- if (sendConfigChangedEvent) {
- EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
- false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
- numStackTasks > 0));
- }
- EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
- showDeferredAnimation, stack));
- }
-
- @Override
- public boolean onPreDraw() {
- mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- return true;
- }
-
- public void onPackageChanged(String packageName, int userId) {
- Recents.getTaskLoader().onPackageChanged(packageName);
- EventBus.getDefault().send(new PackagesChangedEvent(packageName, userId));
- }
-
- @Override
- public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
- super.dump(prefix, fd, writer, args);
- EventBus.getDefault().dump(prefix, writer);
- Recents.getTaskLoader().dump(prefix, writer);
-
- String id = Integer.toHexString(System.identityHashCode(this));
-
- writer.print(prefix); writer.print(TAG);
- writer.print(" visible="); writer.print(mIsVisible ? "Y" : "N");
- writer.print(" currentTime="); writer.print(System.currentTimeMillis());
- writer.print(" [0x"); writer.print(id); writer.print("]");
- writer.println();
-
- if (mRecentsView != null) {
- mRecentsView.dump(prefix, writer);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
deleted file mode 100644
index 14fda95..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-/**
- * The launch state of the RecentsActivity.
- *
- * Current Constraints:
- * - needed in onStart() before onNewIntent()
- * - needs to be reset when Recents is hidden
- * - needs to be computed in Recents component
- * - needs to be accessible by views
- */
-public class RecentsActivityLaunchState {
-
- public boolean launchedWithAltTab;
- public boolean launchedFromApp;
- // Set if the activity that we launched from entered PiP during the transition into Recents
- public boolean launchedFromPipApp;
- // Set if the next activity that quick-switch will launch is the PiP activity
- public boolean launchedWithNextPipApp;
- public boolean launchedFromHome;
- public boolean launchedViaDragGesture;
- public boolean launchedViaDockGesture;
- public int launchedToTaskId;
- public int launchedNumVisibleTasks;
- public int launchedNumVisibleThumbnails;
-
- public void reset() {
- launchedFromHome = false;
- launchedFromApp = false;
- launchedFromPipApp = false;
- launchedWithNextPipApp = false;
- launchedToTaskId = -1;
- launchedWithAltTab = false;
- launchedViaDragGesture = false;
- launchedViaDockGesture = false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
deleted file mode 100644
index 68df1d5..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-
-import android.os.SystemProperties;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.views.DockState;
-import com.android.systemui.shared.recents.model.TaskStack;
-
-/**
- * Represents the dock regions for each orientation.
- */
-class DockRegion {
- public static DockState[] PHONE_LANDSCAPE = {
- // We only allow docking to the left in landscape for now on small devices
- DockState.LEFT
- };
- public static DockState[] PHONE_PORTRAIT = {
- // We only allow docking to the top for now on small devices
- DockState.TOP
- };
- public static DockState[] TABLET_LANDSCAPE = {
- DockState.LEFT,
- DockState.RIGHT
- };
- public static DockState[] TABLET_PORTRAIT = PHONE_PORTRAIT;
-}
-
-/**
- * Application resources that can be retrieved from the application context and are not specifically
- * tied to the current activity.
- */
-public class RecentsConfiguration {
-
- private static final int LARGE_SCREEN_MIN_DP = 600;
- private static final int XLARGE_SCREEN_MIN_DP = 720;
-
- // Launch states
- public RecentsActivityLaunchState mLaunchState = new RecentsActivityLaunchState();
-
- // Since the positions in Recents has to be calculated globally (before the RecentsActivity
- // starts), we need to calculate some resource values ourselves, instead of relying on framework
- // resources.
- public final boolean isLargeScreen;
- public final boolean isXLargeScreen;
- public final int smallestWidth;
-
- /** Misc **/
- public boolean fakeShadows;
- public int svelteLevel;
-
- // Whether this product supports Grid-based Recents. If this is field is set to true, then
- // Recents will layout task views in a grid mode when there's enough space in the screen.
- public boolean isGridEnabled;
-
- // Support for Android Recents for low ram devices. If this field is set to true, then Recents
- // will use the alternative layout.
- public boolean isLowRamDevice;
-
- // Enable drag and drop split from Recents. Disabled for low ram devices.
- public boolean dragToSplitEnabled;
-
- private final Context mAppContext;
-
- public RecentsConfiguration(Context context) {
- // Load only resources that can not change after the first load either through developer
- // settings or via multi window
- SystemServicesProxy ssp = Recents.getSystemServices();
- mAppContext = context.getApplicationContext();
- Resources res = mAppContext.getResources();
- fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
- svelteLevel = res.getInteger(R.integer.recents_svelte_level);
- isGridEnabled = SystemProperties.getBoolean("ro.recents.grid", false);
- isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
- dragToSplitEnabled = !isLowRamDevice;
-
- float screenDensity = context.getResources().getDisplayMetrics().density;
- smallestWidth = ssp.getDeviceSmallestWidth();
- isLargeScreen = smallestWidth >= (int) (screenDensity * LARGE_SCREEN_MIN_DP);
- isXLargeScreen = smallestWidth >= (int) (screenDensity * XLARGE_SCREEN_MIN_DP);
- }
-
- /**
- * Returns the activity launch state.
- * TODO: This will be refactored out of RecentsConfiguration.
- */
- public RecentsActivityLaunchState getLaunchState() {
- return mLaunchState;
- }
-
- /**
- * Returns the preferred dock states for the current orientation.
- * @return a list of dock states for device and its orientation
- */
- public DockState[] getDockStatesForCurrentOrientation() {
- boolean isLandscape = mAppContext.getResources().getConfiguration().orientation ==
- Configuration.ORIENTATION_LANDSCAPE;
- RecentsConfiguration config = Recents.getConfiguration();
- if (config.isLargeScreen) {
- return isLandscape ? DockRegion.TABLET_LANDSCAPE : DockRegion.TABLET_PORTRAIT;
- } else {
- return isLandscape ? DockRegion.PHONE_LANDSCAPE : DockRegion.PHONE_PORTRAIT;
- }
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
deleted file mode 100644
index 1918593..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-public class RecentsDebugFlags {
-
- public static class Static {
- // Enables debug drawing for the transition thumbnail
- public static final boolean EnableTransitionThumbnailDebugMode = false;
-
- // Disables enter and exit transitions for other tasks for low ram devices
- public static final boolean DisableRecentsLowRamEnterExitAnimation = false;
-
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
deleted file mode 100644
index d95c731..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ /dev/null
@@ -1,1132 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.view.View.MeasureSpec;
-
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
-
-import android.app.ActivityManager;
-import android.app.ActivityOptions;
-import android.app.trust.TrustManager;
-import android.content.ActivityNotFoundException;
-import android.content.ComponentCallbacks2;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.SystemClock;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.MutableBoolean;
-import android.util.Pair;
-import android.view.LayoutInflater;
-import android.view.ViewConfiguration;
-import android.view.WindowManager;
-
-import android.widget.Toast;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.pip.phone.ForegroundThread;
-import com.google.android.collect.Lists;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.policy.DockedDividerUtils;
-import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.activity.LaunchMostRecentTaskRequestEvent;
-import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
-import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
-import com.android.systemui.recents.events.component.ActivityPinnedEvent;
-import com.android.systemui.recents.events.component.ActivityUnpinnedEvent;
-import com.android.systemui.recents.events.component.HidePipMenuEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
-import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
-import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
-import com.android.systemui.recents.events.ui.TaskSnapshotChangedEvent;
-import com.android.systemui.recents.misc.DozeTrigger;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
-import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
-import com.android.systemui.shared.recents.model.RecentsTaskLoader;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.Task.TaskKey;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
-import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
-import com.android.systemui.recents.views.TaskStackView;
-import com.android.systemui.recents.views.TaskViewHeader;
-import com.android.systemui.recents.views.TaskViewTransform;
-import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
-import com.android.systemui.shared.recents.view.RecentsTransition;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.stackdivider.DividerView;
-import com.android.systemui.statusbar.phone.StatusBar;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * An implementation of the Recents component for the current user. For secondary users, this can
- * be called remotely from the system user.
- */
-public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener {
-
- private final static String TAG = "RecentsImpl";
-
- // The minimum amount of time between each recents button press that we will handle
- private final static int MIN_TOGGLE_DELAY_MS = 350;
-
- // The duration within which the user releasing the alt tab (from when they pressed alt tab)
- // that the fast alt-tab animation will run. If the user's alt-tab takes longer than this
- // duration, then we will toggle recents after this duration.
- private final static int FAST_ALT_TAB_DELAY_MS = 225;
-
- private final static ArraySet<TaskKey> EMPTY_SET = new ArraySet<>();
-
- public final static String RECENTS_PACKAGE = "com.android.systemui";
- public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
-
- /**
- * An implementation of SysUiTaskStackChangeListener, that allows us to listen for changes to the system
- * task stacks and update recents accordingly.
- */
- class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
-
- private OverviewProxyService mOverviewProxyService;
-
- public TaskStackListenerImpl() {
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
- }
-
- @Override
- public void onTaskStackChangedBackground() {
- // Skip background preloading recents in SystemUI if the overview services is bound
- if (mOverviewProxyService.isEnabled()) {
- return;
- }
-
- // Check this is for the right user
- if (!checkCurrentUserId(mContext, false /* debug */)) {
- return;
- }
-
- // Preloads the next task
- RecentsConfiguration config = Recents.getConfiguration();
- if (config.svelteLevel == RecentsTaskLoader.SVELTE_NONE) {
- Rect windowRect = getWindowRect(null /* windowRectOverride */);
- if (windowRect.isEmpty()) {
- return;
- }
-
- // Load the next task only if we aren't svelte
- ActivityManager.RunningTaskInfo runningTaskInfo =
- ActivityManagerWrapper.getInstance().getRunningTask();
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
- loader.preloadTasks(plan, -1);
- TaskStack stack = plan.getTaskStack();
- RecentsActivityLaunchState launchState = new RecentsActivityLaunchState();
- RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
-
- synchronized (mBackgroundLayoutAlgorithm) {
- // This callback is made when a new activity is launched and the old one is
- // paused so ignore the current activity and try and preload the thumbnail for
- // the previous one.
- updateDummyStackViewLayout(mBackgroundLayoutAlgorithm, stack, windowRect);
-
- // Launched from app is always the worst case (in terms of how many
- // thumbnails/tasks visible)
- launchState.launchedFromApp = true;
- mBackgroundLayoutAlgorithm.update(plan.getTaskStack(), EMPTY_SET, launchState,
- -1 /* lastScrollPPresent */);
- VisibilityReport visibilityReport =
- mBackgroundLayoutAlgorithm.computeStackVisibilityReport(
- stack.getTasks());
-
- launchOpts.runningTaskId = runningTaskInfo != null ? runningTaskInfo.id : -1;
- launchOpts.numVisibleTasks = visibilityReport.numVisibleTasks;
- launchOpts.numVisibleTaskThumbnails = visibilityReport.numVisibleThumbnails;
- launchOpts.onlyLoadForCache = true;
- launchOpts.onlyLoadPausedActivities = true;
- launchOpts.loadThumbnails = true;
- }
- loader.loadTasks(plan, launchOpts);
- }
- }
-
- @Override
- public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
- // Check this is for the right user
- if (!checkCurrentUserId(mContext, false /* debug */)) {
- return;
- }
-
- // This time needs to be fetched the same way the last active time is fetched in
- // {@link TaskRecord#touchActiveTime}
- Recents.getConfiguration().getLaunchState().launchedFromPipApp = true;
- Recents.getConfiguration().getLaunchState().launchedWithNextPipApp = false;
- EventBus.getDefault().send(new ActivityPinnedEvent(taskId));
- consumeInstanceLoadPlan();
- sLastPipTime = System.currentTimeMillis();
- }
-
- @Override
- public void onActivityUnpinned() {
- // Check this is for the right user
- if (!checkCurrentUserId(mContext, false /* debug */)) {
- return;
- }
-
- EventBus.getDefault().send(new ActivityUnpinnedEvent());
- sLastPipTime = -1;
- }
-
- @Override
- public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) {
- // Check this is for the right user
- if (!checkCurrentUserId(mContext, false /* debug */)) {
- return;
- }
-
- EventBus.getDefault().send(new TaskSnapshotChangedEvent(taskId, snapshot));
- }
- }
-
- protected static RecentsTaskLoadPlan sInstanceLoadPlan;
- // Stores the last pinned task time
- protected static long sLastPipTime = -1;
- // Stores whether we are waiting for a transition to/from recents to start. During this time,
- // we disallow the user from manually toggling recents until the transition has started.
- private static boolean mWaitingForTransitionStart = false;
- // Stores whether or not the user toggled while we were waiting for a transition to/from
- // recents. In this case, we defer the toggle state until then and apply it immediately after.
- private static boolean mToggleFollowingTransitionStart = true;
-
- private Runnable mResetToggleFlagListener = new Runnable() {
- @Override
- public void run() {
- setWaitingForTransitionStart(false);
- }
- };
-
- private TrustManager mTrustManager;
- protected Context mContext;
- protected Handler mHandler;
- TaskStackListenerImpl mTaskStackListener;
- boolean mDraggingInRecents;
- boolean mLaunchedWhileDocking;
-
- // Task launching
- Rect mTmpBounds = new Rect();
- TaskViewTransform mTmpTransform = new TaskViewTransform();
- int mTaskBarHeight;
-
- // Header (for transition)
- TaskViewHeader mHeaderBar;
- final Object mHeaderBarLock = new Object();
- private TaskStackView mDummyStackView;
- private TaskStackLayoutAlgorithm mBackgroundLayoutAlgorithm;
-
- // Variables to keep track of if we need to start recents after binding
- protected boolean mTriggeredFromAltTab;
- protected long mLastToggleTime;
- DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() {
- @Override
- public void run() {
- // When this fires, then the user has not released alt-tab for at least
- // FAST_ALT_TAB_DELAY_MS milliseconds
- showRecents(mTriggeredFromAltTab, false /* draggingInRecents */, true /* animate */,
- DividerView.INVALID_RECENTS_GROW_TARGET);
- }
- });
-
- private OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
- new OverviewProxyService.OverviewProxyListener() {
- @Override
- public void onConnectionChanged(boolean isConnected) {
- if (!isConnected) {
- // Clear everything when the connection to the overview service
- Recents.getTaskLoader().onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
- }
- }
- };
-
- // Used to reset the dummy stack view
- private final TaskStack mEmptyTaskStack = new TaskStack();
-
- public RecentsImpl(Context context) {
- mContext = context;
- mHandler = new Handler();
- mBackgroundLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, null);
-
- // Initialize the static foreground thread
- ForegroundThread.get();
-
- // Register the task stack listener
- mTaskStackListener = new TaskStackListenerImpl();
- ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
-
- // Initialize the static configuration resources
- mDummyStackView = new TaskStackView(mContext);
- reloadResources();
-
- mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
- }
-
- public void onBootCompleted() {
- // Skip preloading tasks if we are already bound to the service
- if (Dependency.get(OverviewProxyService.class).isEnabled()) {
- return;
- }
-
- // When we start, preload the data associated with the previous recent tasks.
- // We can use a new plan since the caches will be the same.
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
- loader.preloadTasks(plan, -1);
- RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
- launchOpts.numVisibleTasks = loader.getIconCacheSize();
- launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize();
- launchOpts.onlyLoadForCache = true;
- loader.loadTasks(plan, launchOpts);
- }
-
- public void onConfigurationChanged() {
- reloadResources();
- mDummyStackView.reloadOnConfigurationChange();
- synchronized (mBackgroundLayoutAlgorithm) {
- mBackgroundLayoutAlgorithm.reloadOnConfigurationChange(mContext);
- }
- }
-
- /**
- * This is only called from the system user's Recents. Secondary users will instead proxy their
- * visibility change events through to the system user via
- * {@link Recents#onBusEvent(RecentsVisibilityChangedEvent)}.
- */
- public void onVisibilityChanged(Context context, boolean visible) {
- Recents.getSystemServices().setRecentsVisibility(visible);
- }
-
- /**
- * This is only called from the system user's Recents. Secondary users will instead proxy their
- * visibility change events through to the system user via
- * {@link Recents#onBusEvent(ScreenPinningRequestEvent)}.
- */
- public void onStartScreenPinning(Context context, int taskId) {
- final StatusBar statusBar = getStatusBar();
- if (statusBar != null) {
- statusBar.showScreenPinningRequest(taskId, false);
- }
- }
-
- public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents,
- boolean animate, int growTarget) {
- final SystemServicesProxy ssp = Recents.getSystemServices();
- final MutableBoolean isHomeStackVisible = new MutableBoolean(true);
- final boolean isRecentsVisible = Recents.getSystemServices().isRecentsActivityVisible(
- isHomeStackVisible);
- final boolean fromHome = isHomeStackVisible.value;
- final boolean launchedWhileDockingTask =
- Recents.getSystemServices().getSplitScreenPrimaryStack() != null;
-
- mTriggeredFromAltTab = triggeredFromAltTab;
- mDraggingInRecents = draggingInRecents;
- mLaunchedWhileDocking = launchedWhileDockingTask;
- if (mFastAltTabTrigger.isAsleep()) {
- // Fast alt-tab duration has elapsed, fall through to showing Recents and reset
- mFastAltTabTrigger.stopDozing();
- } else if (mFastAltTabTrigger.isDozing()) {
- // Fast alt-tab duration has not elapsed. If this is triggered by a different
- // showRecents() call, then ignore that call for now.
- // TODO: We can not handle quick tabs that happen between the initial showRecents() call
- // that started the activity and the activity starting up. The severity of this
- // is inversely proportional to the FAST_ALT_TAB_DELAY_MS duration though.
- if (!triggeredFromAltTab) {
- return;
- }
- mFastAltTabTrigger.stopDozing();
- } else if (triggeredFromAltTab) {
- // The fast alt-tab detector is not yet running, so start the trigger and wait for the
- // hideRecents() call, or for the fast alt-tab duration to elapse
- mFastAltTabTrigger.startDozing();
- return;
- }
-
- try {
- // Check if the top task is in the home stack, and start the recents activity
- final boolean forceVisible = launchedWhileDockingTask || draggingInRecents;
- if (forceVisible || !isRecentsVisible) {
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- startRecentsActivityAndDismissKeyguardIfNeeded(runningTask,
- isHomeStackVisible.value || fromHome, animate, growTarget);
- }
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Failed to launch RecentsActivity", e);
- }
- }
-
- public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- if (triggeredFromAltTab && mFastAltTabTrigger.isDozing()) {
- // The user has released alt-tab before the trigger has run, so just show the next
- // task immediately
- showNextTask();
-
- // Cancel the fast alt-tab trigger
- mFastAltTabTrigger.stopDozing();
- return;
- }
-
- // Defer to the activity to handle hiding recents, if it handles it, then it must still
- // be visible
- EventBus.getDefault().post(new HideRecentsEvent(triggeredFromAltTab,
- triggeredFromHomeKey));
- }
-
- public void toggleRecents(int growTarget) {
- if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
- return;
- }
-
- // Skip this toggle if we are already waiting to trigger recents via alt-tab
- if (mFastAltTabTrigger.isDozing()) {
- return;
- }
-
- if (mWaitingForTransitionStart) {
- mToggleFollowingTransitionStart = true;
- return;
- }
-
- mDraggingInRecents = false;
- mLaunchedWhileDocking = false;
- mTriggeredFromAltTab = false;
-
- try {
- MutableBoolean isHomeStackVisible = new MutableBoolean(true);
- long elapsedTime = SystemClock.elapsedRealtime() - mLastToggleTime;
-
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (ssp.isRecentsActivityVisible(isHomeStackVisible)) {
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- if (!launchState.launchedWithAltTab) {
- if (Recents.getConfiguration().isGridEnabled) {
- // Has the user tapped quickly?
- boolean isQuickTap = elapsedTime < ViewConfiguration.getDoubleTapTimeout();
- if (isQuickTap) {
- EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
- } else {
- EventBus.getDefault().post(new LaunchMostRecentTaskRequestEvent());
- }
- } else {
- // Launch the next focused task
- EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
- }
- } else {
- // If the user has toggled it too quickly, then just eat up the event here (it's
- // better than showing a janky screenshot).
- // NOTE: Ideally, the screenshot mechanism would take the window transform into
- // account
- if (elapsedTime < MIN_TOGGLE_DELAY_MS) {
- return;
- }
-
- EventBus.getDefault().post(new ToggleRecentsEvent());
- mLastToggleTime = SystemClock.elapsedRealtime();
- }
- return;
- } else {
- // If the user has toggled it too quickly, then just eat up the event here (it's
- // better than showing a janky screenshot).
- // NOTE: Ideally, the screenshot mechanism would take the window transform into
- // account
- if (elapsedTime < MIN_TOGGLE_DELAY_MS) {
- return;
- }
-
- // Otherwise, start the recents activity
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- startRecentsActivityAndDismissKeyguardIfNeeded(runningTask,
- isHomeStackVisible.value, true /* animate */, growTarget);
-
- // Only close the other system windows if we are actually showing recents
- ActivityManagerWrapper.getInstance().closeSystemWindows(
- SYSTEM_DIALOG_REASON_RECENT_APPS);
- mLastToggleTime = SystemClock.elapsedRealtime();
- }
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Failed to launch RecentsActivity", e);
- }
- }
-
- public void preloadRecents() {
- if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
- return;
- }
-
- // Skip preloading recents when keyguard is showing
- final StatusBar statusBar = getStatusBar();
- if (statusBar != null && statusBar.isKeyguardShowing()) {
- return;
- }
-
- // Preload only the raw task list into a new load plan (which will be consumed by the
- // RecentsActivity) only if there is a task to animate to. Post this to ensure that we
- // don't block the touch feedback on the nav bar button which triggers this.
- mHandler.post(() -> {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (!ssp.isRecentsActivityVisible(null)) {
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- if (runningTask == null) {
- return;
- }
-
- RecentsTaskLoader loader = Recents.getTaskLoader();
- sInstanceLoadPlan = new RecentsTaskLoadPlan(mContext);
- loader.preloadTasks(sInstanceLoadPlan, runningTask.id);
- TaskStack stack = sInstanceLoadPlan.getTaskStack();
- if (stack.getTaskCount() > 0) {
- // Only preload the icon (but not the thumbnail since it may not have been taken
- // for the pausing activity)
- preloadIcon(runningTask.id);
-
- // At this point, we don't know anything about the stack state. So only
- // calculate the dimensions of the thumbnail that we need for the transition
- // into Recents, but do not draw it until we construct the activity options when
- // we start Recents
- updateHeaderBarLayout(stack, null /* window rect override*/);
- }
- }
- });
- }
-
- public void cancelPreloadingRecents() {
- // Do nothing
- }
-
- public void onDraggingInRecents(float distanceFromTop) {
- EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEvent(distanceFromTop));
- }
-
- public void onDraggingInRecentsEnded(float velocity) {
- EventBus.getDefault().sendOntoMainThread(new DraggingInRecentsEndedEvent(velocity));
- }
-
- public void onShowCurrentUserToast(int msgResId, int msgLength) {
- Toast.makeText(mContext, msgResId, msgLength).show();
- }
-
- /**
- * Transitions to the next recent task in the stack.
- */
- public void showNextTask() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
- loader.preloadTasks(plan, -1);
- TaskStack focusedStack = plan.getTaskStack();
-
- // Return early if there are no tasks in the focused stack
- if (focusedStack == null || focusedStack.getTaskCount() == 0) return;
-
- // Return early if there is no running task
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- if (runningTask == null) return;
-
- // Find the task in the recents list
- boolean isRunningTaskInHomeStack =
- runningTask.configuration.windowConfiguration.getActivityType()
- == ACTIVITY_TYPE_HOME;
- ArrayList<Task> tasks = focusedStack.getTasks();
- Task toTask = null;
- ActivityOptions launchOpts = null;
- int taskCount = tasks.size();
- for (int i = taskCount - 1; i >= 1; i--) {
- Task task = tasks.get(i);
- if (isRunningTaskInHomeStack) {
- toTask = tasks.get(i - 1);
- launchOpts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_next_affiliated_task_target,
- R.anim.recents_fast_toggle_app_home_exit);
- break;
- } else if (task.key.id == runningTask.id) {
- toTask = tasks.get(i - 1);
- launchOpts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_prev_affiliated_task_target,
- R.anim.recents_launch_prev_affiliated_task_source);
- break;
- }
- }
-
- // Return early if there is no next task
- if (toTask == null) {
- ssp.startInPlaceAnimationOnFrontMostApplication(
- ActivityOptions.makeCustomInPlaceAnimation(mContext,
- R.anim.recents_launch_prev_affiliated_task_bounce));
- return;
- }
-
- // Launch the task
- ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(toTask.key, launchOpts,
- null /* resultCallback */, null /* resultCallbackHandler */);
- }
-
- /**
- * Transitions to the next affiliated task.
- */
- public void showRelativeAffiliatedTask(boolean showNextTask) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsTaskLoadPlan plan = new RecentsTaskLoadPlan(mContext);
- loader.preloadTasks(plan, -1);
- TaskStack focusedStack = plan.getTaskStack();
-
- // Return early if there are no tasks in the focused stack
- if (focusedStack == null || focusedStack.getTaskCount() == 0) return;
-
- // Return early if there is no running task (can't determine affiliated tasks in this case)
- ActivityManager.RunningTaskInfo runningTask =
- ActivityManagerWrapper.getInstance().getRunningTask();
- final int activityType = runningTask.configuration.windowConfiguration.getActivityType();
- if (runningTask == null) return;
- // Return early if the running task is in the home/recents stack (optimization)
- if (activityType == ACTIVITY_TYPE_HOME || activityType == ACTIVITY_TYPE_RECENTS) return;
-
- // Find the task in the recents list
- ArrayList<Task> tasks = focusedStack.getTasks();
- Task toTask = null;
- ActivityOptions launchOpts = null;
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task task = tasks.get(i);
- if (task.key.id == runningTask.id) {
- if (showNextTask) {
- if ((i + 1) < taskCount) {
- toTask = tasks.get(i + 1);
- launchOpts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_next_affiliated_task_target,
- R.anim.recents_launch_next_affiliated_task_source);
- }
- } else {
- if ((i - 1) >= 0) {
- toTask = tasks.get(i - 1);
- launchOpts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_launch_prev_affiliated_task_target,
- R.anim.recents_launch_prev_affiliated_task_source);
- }
- }
- break;
- }
- }
-
- // Return early if there is no next task
- if (toTask == null) {
- if (showNextTask) {
- ssp.startInPlaceAnimationOnFrontMostApplication(
- ActivityOptions.makeCustomInPlaceAnimation(mContext,
- R.anim.recents_launch_next_affiliated_task_bounce));
- } else {
- ssp.startInPlaceAnimationOnFrontMostApplication(
- ActivityOptions.makeCustomInPlaceAnimation(mContext,
- R.anim.recents_launch_prev_affiliated_task_bounce));
- }
- return;
- }
-
- // Keep track of actually launched affiliated tasks
- MetricsLogger.count(mContext, "overview_affiliated_task_launch", 1);
-
- // Launch the task
- ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(toTask.key, launchOpts,
- null /* resultListener */, null /* resultCallbackHandler */);
- }
-
- public void showNextAffiliatedTask() {
- // Keep track of when the affiliated task is triggered
- MetricsLogger.count(mContext, "overview_affiliated_task_next", 1);
- showRelativeAffiliatedTask(true);
- }
-
- public void showPrevAffiliatedTask() {
- // Keep track of when the affiliated task is triggered
- MetricsLogger.count(mContext, "overview_affiliated_task_prev", 1);
- showRelativeAffiliatedTask(false);
- }
-
- public void splitPrimaryTask(int taskId, int stackCreateMode, Rect initialBounds) {
- SystemServicesProxy ssp = Recents.getSystemServices();
-
- // Make sure we inform DividerView before we actually start the activity so we can change
- // the resize mode already.
- if (ssp.setTaskWindowingModeSplitScreenPrimary(taskId, stackCreateMode, initialBounds)) {
- EventBus.getDefault().send(new DockedTopTaskEvent(initialBounds));
- }
- }
-
- public void setWaitingForTransitionStart(boolean waitingForTransitionStart) {
- if (mWaitingForTransitionStart == waitingForTransitionStart) {
- return;
- }
-
- mWaitingForTransitionStart = waitingForTransitionStart;
- if (!waitingForTransitionStart && mToggleFollowingTransitionStart) {
- mHandler.post(() -> toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET));
- }
- mToggleFollowingTransitionStart = false;
- }
-
- /**
- * Returns the preloaded load plan and invalidates it.
- */
- public static RecentsTaskLoadPlan consumeInstanceLoadPlan() {
- RecentsTaskLoadPlan plan = sInstanceLoadPlan;
- sInstanceLoadPlan = null;
- return plan;
- }
-
- /**
- * @return the time at which a task last entered picture-in-picture.
- */
- public static long getLastPipTime() {
- return sLastPipTime;
- }
-
- /**
- * Clears the time at which a task last entered picture-in-picture.
- */
- public static void clearLastPipTime() {
- sLastPipTime = -1;
- }
-
- /**
- * Reloads all the resources for the current configuration.
- */
- private void reloadResources() {
- Resources res = mContext.getResources();
-
- mTaskBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(mContext,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height_tablet_land,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height_tablet_land,
- R.dimen.recents_grid_task_view_header_height);
-
- LayoutInflater inflater = LayoutInflater.from(mContext);
- mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
- null, false);
- mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection());
- }
-
- private void updateDummyStackViewLayout(TaskStackLayoutAlgorithm stackLayout,
- TaskStack stack, Rect windowRect) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- Rect displayRect = ssp.getDisplayRect();
- Rect systemInsets = new Rect();
- ssp.getStableInsets(systemInsets);
-
- // When docked, the nav bar insets are consumed and the activity is measured without insets.
- // However, the window bounds include the insets, so we need to subtract them here to make
- // them identical.
- if (ssp.hasDockedTask()) {
- if (systemInsets.bottom < windowRect.height()) {
- // Only apply inset if it isn't going to cause the rect height to go negative.
- windowRect.bottom -= systemInsets.bottom;
- }
- systemInsets.bottom = 0;
- }
- calculateWindowStableInsets(systemInsets, windowRect, displayRect);
- windowRect.offsetTo(0, 0);
-
- // Rebind the header bar and draw it for the transition
- stackLayout.setSystemInsets(systemInsets);
- if (stack != null) {
- stackLayout.getTaskStackBounds(displayRect, windowRect, systemInsets.top,
- systemInsets.left, systemInsets.right, mTmpBounds);
- stackLayout.reset();
- stackLayout.initialize(displayRect, windowRect, mTmpBounds);
- }
- }
-
- private Rect getWindowRect(Rect windowRectOverride) {
- return windowRectOverride != null
- ? new Rect(windowRectOverride)
- : Recents.getSystemServices().getWindowRect();
- }
-
- /**
- * Prepares the header bar layout for the next transition, if the task view bounds has changed
- * since the last call, it will attempt to re-measure and layout the header bar to the new size.
- *
- * @param stack the stack to initialize the stack layout with
- * @param windowRectOverride the rectangle to use when calculating the stack state which can
- * be different from the current window rect if recents is resizing
- * while being launched
- */
- private void updateHeaderBarLayout(TaskStack stack, Rect windowRectOverride) {
- Rect windowRect = getWindowRect(windowRectOverride);
- int taskViewWidth = 0;
- boolean useGridLayout = mDummyStackView.useGridLayout();
- updateDummyStackViewLayout(mDummyStackView.getStackAlgorithm(), stack, windowRect);
- if (stack != null) {
- TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
- mDummyStackView.getStack().removeAllTasks(false /* notifyStackChanges */);
- mDummyStackView.setTasks(stack, false /* allowNotifyStackChanges */);
- // Get the width of a task view so that we know how wide to draw the header bar.
- if (useGridLayout) {
- TaskGridLayoutAlgorithm gridLayout = mDummyStackView.getGridAlgorithm();
- gridLayout.initialize(windowRect);
- taskViewWidth = (int) gridLayout.getTransform(0 /* taskIndex */,
- stack.getTaskCount(), new TaskViewTransform(),
- stackLayout).rect.width();
- } else {
- Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
- if (!taskViewBounds.isEmpty()) {
- taskViewWidth = taskViewBounds.width();
- }
- }
- }
-
- if (stack != null && taskViewWidth > 0) {
- synchronized (mHeaderBarLock) {
- if (mHeaderBar.getMeasuredWidth() != taskViewWidth ||
- mHeaderBar.getMeasuredHeight() != mTaskBarHeight) {
- if (useGridLayout) {
- mHeaderBar.setShouldDarkenBackgroundColor(true);
- mHeaderBar.setNoUserInteractionState();
- }
- mHeaderBar.forceLayout();
- mHeaderBar.measure(
- MeasureSpec.makeMeasureSpec(taskViewWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(mTaskBarHeight, MeasureSpec.EXACTLY));
- }
- mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
- }
- }
- }
-
- /**
- * Given the stable insets and the rect for our window, calculates the insets that affect our
- * window.
- */
- private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect, Rect displayRect) {
-
- // Display rect without insets - available app space
- Rect appRect = new Rect(displayRect);
- appRect.inset(inOutInsets);
-
- // Our window intersected with available app space
- Rect windowRectWithInsets = new Rect(windowRect);
- windowRectWithInsets.intersect(appRect);
- inOutInsets.left = windowRectWithInsets.left - windowRect.left;
- inOutInsets.top = windowRectWithInsets.top - windowRect.top;
- inOutInsets.right = windowRect.right - windowRectWithInsets.right;
- inOutInsets.bottom = windowRect.bottom - windowRectWithInsets.bottom;
- }
-
- /**
- * Preloads the icon of a task.
- */
- private void preloadIcon(int runningTaskId) {
- // Ensure that we load the running task's icon
- RecentsTaskLoadPlan.Options launchOpts = new RecentsTaskLoadPlan.Options();
- launchOpts.runningTaskId = runningTaskId;
- launchOpts.loadThumbnails = false;
- launchOpts.onlyLoadForCache = true;
- Recents.getTaskLoader().loadTasks(sInstanceLoadPlan, launchOpts);
- }
-
- /**
- * Creates the activity options for a unknown state->recents transition.
- */
- protected ActivityOptions getUnknownTransitionActivityOptions() {
- return ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_from_unknown_enter,
- R.anim.recents_from_unknown_exit,
- mHandler, null);
- }
-
- /**
- * Creates the activity options for a home->recents transition.
- */
- protected ActivityOptions getHomeTransitionActivityOptions() {
- return ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_from_launcher_enter,
- R.anim.recents_from_launcher_exit,
- mHandler, null);
- }
-
- /**
- * Creates the activity options for an app->recents transition.
- */
- private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture>
- getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask,
- Rect windowOverrideRect) {
- final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
-
- // Update the destination rect
- Task toTask = new Task();
- TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask,
- windowOverrideRect);
-
- RectF toTaskRect = toTransform.rect;
- AppTransitionAnimationSpecsFuture future = new AppTransitionAnimationSpecsFuture(mHandler) {
- @Override
- public List<AppTransitionAnimationSpecCompat> composeSpecs() {
- Rect rect = new Rect();
- toTaskRect.round(rect);
- Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform);
- return Lists.newArrayList(new AppTransitionAnimationSpecCompat(toTask.key.id,
- thumbnail, rect));
- }
- };
-
- // For low end ram devices, wait for transition flag is reset when Recents entrance
- // animation is complete instead of when the transition animation starts
- return new Pair<>(RecentsTransition.createAspectScaleAnimation(mContext, mHandler,
- false /* scaleUp */, future, isLowRamDevice ? null : mResetToggleFlagListener),
- future);
- }
-
- /**
- * Returns the transition rect for the given task id.
- */
- private TaskViewTransform getThumbnailTransitionTransform(TaskStackView stackView,
- Task runningTaskOut, Rect windowOverrideRect) {
- // Find the running task in the TaskStack
- TaskStack stack = stackView.getStack();
- Task launchTask = stack.getLaunchTarget();
- if (launchTask != null) {
- runningTaskOut.copyFrom(launchTask);
- } else {
- // If no task is specified or we can not find the task just use the front most one
- launchTask = stack.getFrontMostTask();
- runningTaskOut.copyFrom(launchTask);
- }
-
- // Get the transform for the running task
- stackView.updateLayoutAlgorithm(true /* boundScroll */);
- stackView.updateToInitialState();
- stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
- stackView.getScroller().getStackScroll(), mTmpTransform, null, windowOverrideRect);
- return mTmpTransform;
- }
-
- /**
- * Draws the header of a task used for the window animation into a bitmap.
- */
- private Bitmap drawThumbnailTransitionBitmap(Task toTask,
- TaskViewTransform toTransform) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- int width = (int) toTransform.rect.width();
- int height = (int) toTransform.rect.height();
- if (toTransform != null && toTask.key != null && width > 0 && height > 0) {
- synchronized (mHeaderBarLock) {
- boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode();
- mHeaderBar.onTaskViewSizeChanged(width, height);
- if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
- return RecentsTransition.drawViewIntoHardwareBitmap(width, mTaskBarHeight,
- null, 1f, 0xFFff0000);
- } else {
- // Workaround for b/27815919, reset the callback so that we do not trigger an
- // invalidate on the header bar as a result of updating the icon
- Drawable icon = mHeaderBar.getIconView().getDrawable();
- if (icon != null) {
- icon.setCallback(null);
- }
- mHeaderBar.bindToTask(toTask, false /* touchExplorationEnabled */,
- disabledInSafeMode);
- mHeaderBar.onTaskDataLoaded();
- mHeaderBar.setDimAlpha(toTransform.dimAlpha);
- return RecentsTransition.drawViewIntoHardwareBitmap(width, mTaskBarHeight,
- mHeaderBar, 1f, 0);
- }
- }
- }
- return null;
- }
-
- /**
- * Shows the recents activity after dismissing the keyguard if visible
- */
- protected void startRecentsActivityAndDismissKeyguardIfNeeded(
- final ActivityManager.RunningTaskInfo runningTask, final boolean isHomeStackVisible,
- final boolean animate, final int growTarget) {
- // Preload only if device for current user is unlocked
- final StatusBar statusBar = getStatusBar();
- if (statusBar != null && statusBar.isKeyguardShowing()) {
- statusBar.executeRunnableDismissingKeyguard(() -> {
- // Flush trustmanager before checking device locked per user when preloading
- mTrustManager.reportKeyguardShowingChanged();
- mHandler.post(() -> startRecentsActivity(runningTask, isHomeStackVisible,
- animate, growTarget));
- }, null, true /* dismissShade */, false /* afterKeyguardGone */,
- true /* deferred */);
- } else {
- startRecentsActivity(runningTask, isHomeStackVisible, animate, growTarget);
- }
- }
-
- private void startRecentsActivity(ActivityManager.RunningTaskInfo runningTask,
- boolean isHomeStackVisible, boolean animate, int growTarget) {
- RecentsTaskLoader loader = Recents.getTaskLoader();
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-
- int runningTaskId = !mLaunchedWhileDocking && (runningTask != null)
- ? runningTask.id
- : -1;
-
- // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
- // should always preload the tasks now. If we are dragging in recents, reload them as
- // the stacks might have changed.
- if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
- // Create a new load plan if preloadRecents() was never triggered
- sInstanceLoadPlan = new RecentsTaskLoadPlan(mContext);
- }
- if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
- loader.preloadTasks(sInstanceLoadPlan, runningTaskId);
- }
-
- TaskStack stack = sInstanceLoadPlan.getTaskStack();
- boolean hasRecentTasks = stack.getTaskCount() > 0;
- boolean useThumbnailTransition = (runningTask != null) && !isHomeStackVisible &&
- hasRecentTasks;
-
- // Update the launch state that we need in updateHeaderBarLayout()
- launchState.launchedFromHome = !useThumbnailTransition && !mLaunchedWhileDocking;
- launchState.launchedFromApp = useThumbnailTransition || mLaunchedWhileDocking;
- launchState.launchedFromPipApp = false;
- launchState.launchedWithNextPipApp =
- stack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime());
- launchState.launchedViaDockGesture = mLaunchedWhileDocking;
- launchState.launchedViaDragGesture = mDraggingInRecents;
- launchState.launchedToTaskId = runningTaskId;
- launchState.launchedWithAltTab = mTriggeredFromAltTab;
-
- // Disable toggling of recents between starting the activity and it is visible and the app
- // has started its transition into recents.
- setWaitingForTransitionStart(useThumbnailTransition);
-
- // Preload the icon (this will be a null-op if we have preloaded the icon already in
- // preloadRecents())
- preloadIcon(runningTaskId);
-
- // Update the header bar if necessary
- Rect windowOverrideRect = getWindowRectOverride(growTarget);
- updateHeaderBarLayout(stack, windowOverrideRect);
-
- // Prepare the dummy stack for the transition
- TaskStackLayoutAlgorithm.VisibilityReport stackVr =
- mDummyStackView.computeStackVisibilityReport();
-
- // Update the remaining launch state
- launchState.launchedNumVisibleTasks = stackVr.numVisibleTasks;
- launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails;
-
- if (!animate) {
- startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1),
- null /* future */);
- return;
- }
-
- Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> pair;
- if (useThumbnailTransition) {
- // Try starting with a thumbnail transition
- pair = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect);
- } else {
- // If there is no thumbnail transition, but is launching from home into recents, then
- // use a quick home transition
- pair = new Pair<>(hasRecentTasks
- ? getHomeTransitionActivityOptions()
- : getUnknownTransitionActivityOptions(), null);
- }
- startRecentsActivity(pair.first, pair.second);
- mLastToggleTime = SystemClock.elapsedRealtime();
- }
-
- private Rect getWindowRectOverride(int growTarget) {
- if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) {
- return SystemServicesProxy.getInstance(mContext).getWindowRect();
- }
- Rect result = new Rect();
- Rect displayRect = Recents.getSystemServices().getDisplayRect();
- DockedDividerUtils.calculateBoundsForPosition(growTarget, WindowManager.DOCKED_BOTTOM,
- result, displayRect.width(), displayRect.height(),
- Recents.getSystemServices().getDockedDividerSize(mContext));
- return result;
- }
-
- private StatusBar getStatusBar() {
- return SysUiServiceProvider.getComponent(mContext, StatusBar.class);
- }
-
- /**
- * Starts the recents activity.
- */
- private void startRecentsActivity(ActivityOptions opts,
- final AppTransitionAnimationSpecsFuture future) {
- Intent intent = new Intent();
- intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
- HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
- hideMenuEvent.addPostAnimationCallback(() -> {
- Recents.getSystemServices().startActivityAsUserAsync(intent, opts);
- EventBus.getDefault().send(new RecentsActivityStartingEvent());
- if (future != null) {
- future.composeSpecsSynchronous();
- }
- });
- EventBus.getDefault().send(hideMenuEvent);
-
- // Once we have launched the activity, reset the dummy stack view tasks so we don't hold
- // onto references to the same tasks consumed by the activity
- mDummyStackView.setTasks(mEmptyTaskStack, false /* notifyStackChanges */);
- }
-
- /**** OnAnimationFinishedListener Implementation ****/
-
- @Override
- public void onAnimationFinished() {
- EventBus.getDefault().post(new EnterRecentsWindowLastAnimationFrameEvent());
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
deleted file mode 100644
index a1da785..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplProxy.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents;
-
-import android.graphics.Rect;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-
-import com.android.internal.os.SomeArgs;
-
-/**
- * A proxy class which directs all methods from {@link IRecentsNonSystemUserCallbacks} to
- * {@link RecentsImpl} and makes sure they are called from the main thread.
- */
-public class RecentsImplProxy extends IRecentsNonSystemUserCallbacks.Stub {
-
- private static final int MSG_PRELOAD_RECENTS = 1;
- private static final int MSG_CANCEL_PRELOADING_RECENTS = 2;
- private static final int MSG_SHOW_RECENTS = 3;
- private static final int MSG_HIDE_RECENTS = 4;
- private static final int MSG_TOGGLE_RECENTS = 5;
- private static final int MSG_ON_CONFIGURATION_CHANGED = 6;
- private static final int MSG_DOCK_TOP_TASK = 7;
- private static final int MSG_ON_DRAGGING_IN_RECENTS = 8;
- private static final int MSG_ON_DRAGGING_IN_RECENTS_ENDED = 9;
- private static final int MSG_SHOW_USER_TOAST = 10;
-
- private RecentsImpl mImpl;
-
- public RecentsImplProxy(RecentsImpl recentsImpl) {
- mImpl = recentsImpl;
- }
-
- @Override
- public void preloadRecents() throws RemoteException {
- mHandler.sendEmptyMessage(MSG_PRELOAD_RECENTS);
- }
-
- @Override
- public void cancelPreloadingRecents() throws RemoteException {
- mHandler.sendEmptyMessage(MSG_CANCEL_PRELOADING_RECENTS);
- }
-
- @Override
- public void showRecents(boolean triggeredFromAltTab, boolean draggingInRecents, boolean animate,
- int growTarget) throws RemoteException {
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = triggeredFromAltTab ? 1 : 0;
- args.argi2 = draggingInRecents ? 1 : 0;
- args.argi3 = animate ? 1 : 0;
- args.argi4 = growTarget;
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_RECENTS, args));
- }
-
- @Override
- public void hideRecents(boolean triggeredFromAltTab, boolean triggeredFromHomeKey)
- throws RemoteException {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_HIDE_RECENTS, triggeredFromAltTab ? 1 :0,
- triggeredFromHomeKey ? 1 : 0));
- }
-
- @Override
- public void toggleRecents(int growTarget) throws RemoteException {
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = growTarget;
- mHandler.sendMessage(mHandler.obtainMessage(MSG_TOGGLE_RECENTS, args));
- }
-
- @Override
- public void onConfigurationChanged() throws RemoteException {
- mHandler.sendEmptyMessage(MSG_ON_CONFIGURATION_CHANGED);
- }
-
- @Override
- public void splitPrimaryTask(int topTaskId, int stackCreateMode, Rect initialBounds)
- throws RemoteException {
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = topTaskId;
- args.argi2 = stackCreateMode;
- args.arg1 = initialBounds;
- mHandler.sendMessage(mHandler.obtainMessage(MSG_DOCK_TOP_TASK, args));
- }
-
- @Override
- public void onDraggingInRecents(float distanceFromTop) throws RemoteException {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_DRAGGING_IN_RECENTS, distanceFromTop));
- }
-
- @Override
- public void onDraggingInRecentsEnded(float velocity) throws RemoteException {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_DRAGGING_IN_RECENTS_ENDED, velocity));
- }
-
- @Override
- public void showCurrentUserToast(int msgResId, int msgLength) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SHOW_USER_TOAST, msgResId, msgLength));
- }
-
- private final Handler mHandler = new Handler() {
-
- @Override
- public void handleMessage(Message msg) {
- SomeArgs args;
- switch (msg.what) {
- case MSG_PRELOAD_RECENTS:
- mImpl.preloadRecents();
- break;
- case MSG_CANCEL_PRELOADING_RECENTS:
- mImpl.cancelPreloadingRecents();
- break;
- case MSG_SHOW_RECENTS:
- args = (SomeArgs) msg.obj;
- mImpl.showRecents(args.argi1 != 0, args.argi2 != 0, args.argi3 != 0,
- args.argi4);
- break;
- case MSG_HIDE_RECENTS:
- mImpl.hideRecents(msg.arg1 != 0, msg.arg2 != 0);
- break;
- case MSG_TOGGLE_RECENTS:
- args = (SomeArgs) msg.obj;
- mImpl.toggleRecents(args.argi1);
- break;
- case MSG_ON_CONFIGURATION_CHANGED:
- mImpl.onConfigurationChanged();
- break;
- case MSG_DOCK_TOP_TASK:
- args = (SomeArgs) msg.obj;
- mImpl.splitPrimaryTask(args.argi1, args.argi2 = 0,
- (Rect) args.arg1);
- break;
- case MSG_ON_DRAGGING_IN_RECENTS:
- mImpl.onDraggingInRecents((Float) msg.obj);
- break;
- case MSG_ON_DRAGGING_IN_RECENTS_ENDED:
- mImpl.onDraggingInRecentsEnded((Float) msg.obj);
- break;
- case MSG_SHOW_USER_TOAST:
- mImpl.onShowCurrentUserToast(msg.arg1, msg.arg2);
- break;
- default:
- super.handleMessage(msg);
- }
- super.handleMessage(msg);
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
new file mode 100644
index 0000000..8a04c11
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.recents;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import com.android.systemui.SysUiServiceProvider;
+import java.io.PrintWriter;
+
+interface RecentsImplementation {
+ default void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {}
+ default void onBootCompleted() {}
+ default void onAppTransitionFinished() {}
+ default void onConfigurationChanged(Configuration newConfig) {}
+
+ default void preloadRecentApps() {}
+ default void cancelPreloadRecentApps() {}
+ default void showRecentApps(boolean triggeredFromAltTab) {}
+ default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {}
+ default void toggleRecentApps() {}
+ default void growRecents() {}
+ default boolean splitPrimaryTask(int stackCreateMode, Rect initialBounds,
+ int metricsDockAction) {
+ return false;
+ }
+
+ default void dump(PrintWriter pw) {}
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
index db2b69f..af0ebdc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsOnboarding.java
@@ -59,13 +59,11 @@
import android.widget.ImageView;
import android.widget.TextView;
-import com.android.systemui.OverviewProxyService;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
-
+import com.android.systemui.shared.system.TaskStackChangeListener;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashSet;
@@ -119,7 +117,7 @@
private int mNumAppsLaunchedSinceSwipeUpTipDismiss;
private int mOverviewOpenedCountSinceQuickScrubTipDismiss;
- private final SysUiTaskStackChangeListener mTaskListener = new SysUiTaskStackChangeListener() {
+ private final TaskStackChangeListener mTaskListener = new TaskStackChangeListener() {
private String mLastPackageName;
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
deleted file mode 100644
index c5e9f04..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.EventLog;
-import android.util.Log;
-import android.util.SparseArray;
-
-import com.android.systemui.EventLogConstants;
-import com.android.systemui.EventLogTags;
-import com.android.systemui.pip.phone.ForegroundThread;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
-import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
-import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
-import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
-
-/**
- * An implementation of the system user's Recents interface to be called remotely by secondary
- * users.
- */
-public class RecentsSystemUser extends IRecentsSystemUserCallbacks.Stub {
-
- private static final String TAG = "RecentsSystemUser";
-
- private Context mContext;
- private RecentsImpl mImpl;
- private final SparseArray<IRecentsNonSystemUserCallbacks> mNonSystemUserRecents =
- new SparseArray<>();
-
- public RecentsSystemUser(Context context, RecentsImpl impl) {
- mContext = context;
- mImpl = impl;
- }
-
- @Override
- public void registerNonSystemUserCallbacks(final IBinder nonSystemUserCallbacks,
- final int userId) {
- try {
- final IRecentsNonSystemUserCallbacks callback =
- IRecentsNonSystemUserCallbacks.Stub.asInterface(nonSystemUserCallbacks);
- nonSystemUserCallbacks.linkToDeath(new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- mNonSystemUserRecents.removeAt(mNonSystemUserRecents.indexOfValue(callback));
- EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
- EventLogConstants.SYSUI_RECENTS_CONNECTION_SYSTEM_UNREGISTER_USER,
- userId);
- }
- }, 0);
- mNonSystemUserRecents.put(userId, callback);
- EventLog.writeEvent(EventLogTags.SYSUI_RECENTS_CONNECTION,
- EventLogConstants.SYSUI_RECENTS_CONNECTION_SYSTEM_REGISTER_USER, userId);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register NonSystemUserCallbacks", e);
- }
- }
-
- public IRecentsNonSystemUserCallbacks getNonSystemUserRecentsForUser(int userId) {
- return mNonSystemUserRecents.get(userId);
- }
-
- @Override
- public void updateRecentsVisibility(boolean visible) {
- ForegroundThread.getHandler().post(() -> {
- mImpl.onVisibilityChanged(mContext, visible);
- });
- }
-
- @Override
- public void startScreenPinning(int taskId) {
- ForegroundThread.getHandler().post(() -> {
- mImpl.onStartScreenPinning(mContext, taskId);
- });
- }
-
- @Override
- public void sendRecentsDrawnEvent() {
- EventBus.getDefault().post(new RecentsDrawnEvent());
- }
-
- @Override
- public void sendDockingTopTaskEvent(Rect initialRect) throws RemoteException {
- EventBus.getDefault().post(new DockedTopTaskEvent(initialRect));
- }
-
- @Override
- public void sendLaunchRecentsEvent() throws RemoteException {
- EventBus.getDefault().post(new RecentsActivityStartingEvent());
- }
-
- @Override
- public void sendDockedFirstAnimationFrameEvent() throws RemoteException {
- EventBus.getDefault().post(new DockedFirstAnimationFrameEvent());
- }
-
- @Override
- public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) {
- EventBus.getDefault().post(new SetWaitingForTransitionStartEvent(
- waitingForTransitionStart));
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
deleted file mode 100644
index b4212d3..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUserService.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.systemui.SysUiServiceProvider;
-import com.android.systemui.SystemUIApplication;
-
-/**
- * A strictly system-user service that is started by the secondary user's Recents (with a limited
- * lifespan), to get the interface that the secondary user's Recents can call through to the system
- * user's Recents.
- */
-public class RecentsSystemUserService extends Service {
-
- private static final String TAG = "RecentsSystemUserService";
- private static final boolean DEBUG = false;
-
- @Override
- public void onCreate() {
- super.onCreate();
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- Recents recents = SysUiServiceProvider.getComponent(this, Recents.class);
- if (DEBUG) {
- Log.d(TAG, "onBind: " + recents);
- }
- if (recents != null) {
- return recents.getSystemUserCallbacks();
- }
- return null;
- }
-}
-
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index b7eee36..f92c50a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -29,7 +29,6 @@
import android.os.Binder;
import android.os.RemoteException;
import android.util.DisplayMetrics;
-import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
@@ -42,9 +41,9 @@
import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.statusbar.phone.NavigationBarView;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.leak.RotationUtils;
@@ -220,8 +219,7 @@
mLayout.findViewById(R.id.screen_pinning_text_area)
.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
- if (Recents.getSystemServices() != null &&
- Recents.getSystemServices().hasSoftNavigationBar()) {
+ if (WindowManagerWrapper.getInstance().hasSoftNavigationBar()) {
buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
swapChildrenIfRtlAndVertical(buttons);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
deleted file mode 100644
index 177362c..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java
+++ /dev/null
@@ -1,763 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.SystemClock;
-import android.os.UserHandle;
-import android.util.Log;
-
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
-
-import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Represents a subscriber, which implements various event bus handler methods.
- */
-class Subscriber {
- private WeakReference<Object> mSubscriber;
-
- long registrationTime;
-
- Subscriber(Object subscriber, long registrationTime) {
- mSubscriber = new WeakReference<>(subscriber);
- this.registrationTime = registrationTime;
- }
-
- public String toString(int priority) {
- Object sub = mSubscriber.get();
- String id = Integer.toHexString(System.identityHashCode(sub));
- return sub.getClass().getSimpleName() + " [0x" + id + ", P" + priority + "]";
- }
-
- public Object getReference() {
- return mSubscriber.get();
- }
-}
-
-/**
- * Represents an event handler with a priority.
- */
-class EventHandler {
- int priority;
- Subscriber subscriber;
- EventHandlerMethod method;
-
- EventHandler(Subscriber subscriber, EventHandlerMethod method, int priority) {
- this.subscriber = subscriber;
- this.method = method;
- this.priority = priority;
- }
-
- @Override
- public String toString() {
- return subscriber.toString(priority) + " " + method.toString();
- }
-}
-
-/**
- * Represents the low level method handling a particular event.
- */
-class EventHandlerMethod {
- private Method mMethod;
- Class<? extends EventBus.Event> eventType;
-
- EventHandlerMethod(Method method, Class<? extends EventBus.Event> eventType) {
- mMethod = method;
- mMethod.setAccessible(true);
- this.eventType = eventType;
- }
-
- public void invoke(Object target, EventBus.Event event)
- throws InvocationTargetException, IllegalAccessException {
- mMethod.invoke(target, event);
- }
-
- @Override
- public String toString() {
- return mMethod.getName() + "(" + eventType.getSimpleName() + ")";
- }
-}
-
-/**
- * A simple in-process event bus. It is simple because we can make assumptions about the state of
- * SystemUI and Recent's lifecycle.
- *
- * <p>
- * Currently, there is a single EventBus that handles {@link EventBus.Event}s for each subscriber
- * on the main application thread. Publishers can send() events to synchronously call subscribers
- * of that event, or post() events to be processed in the next run of the {@link Looper}.
- *
- * <p>
- * Subscribers must be registered with a particular EventBus before they will receive events, and
- * handler methods must match a specific signature.
- *
- * <p>
- * Event method signature:<ul>
- * <li>Methods must be public final
- * <li>Methods must return void
- * <li>Methods must be called "onBusEvent"
- * <li>Methods must take one parameter, of class type deriving from {@link EventBus.Event}
- * </ul>
- *
- * </p>
- * Each subscriber can be registered with a given priority (default 1), and events will be dispatch
- * in decreasing order of priority. For subscribers with the same priority, events will be
- * dispatched by latest registration time to earliest.
- *
- * <p>
- * Caveats:<ul>
- * <li>The EventBus keeps a {@link WeakReference} to the publisher to prevent memory leaks, so
- * there must be another strong reference to the publisher for it to not get garbage-collected and
- * continue receiving events.
- * <li>Because the event handlers are called back using reflection, the EventBus is not intended
- * for use in tight, performance criticial loops. For most user input/system callback events, this
- * is generally of low enough frequency to use the EventBus.
- * <li>Because the event handlers are called back using reflection, there will often be no
- * references to them from actual code. The proguard configuration will be need to be updated to
- * keep these extra methods:
- *
- * -keepclassmembers class ** {
- * public void onBusEvent(**);
- * public void onInterprocessBusEvent(**);
- * }
- * -keepclassmembers class ** extends **.EventBus$InterprocessEvent {
- * public <init>(android.os.Bundle);
- * }
- *
- * <li>Subscriber registration can be expensive depending on the subscriber's {@link Class}. This
- * is only done once per class type, but if possible, it is best to pre-register an instance of
- * that class beforehand or when idle.
- * <li>Each event should be sent once. Events may hold internal information about the current
- * dispatch, or may be queued to be dispatched on another thread (if posted from a non-main thread),
- * so it may be unsafe to edit, change, or re-send the event again.
- * <li>Events should follow a pattern of public-final POD (plain old data) objects, where they are
- * initialized by the constructor and read by each subscriber of that event. Subscribers should
- * never alter events as they are processed, and this enforces that pattern.
- * </ul>
- *
- * <p>
- * Future optimizations:
- * <li>throw exception/log when a subscriber loses the reference
- * <li>trace cost per registration & invocation
- * <li>trace cross-process invocation
- * <li>register(subscriber, Class<?>...) -- pass in exact class types you want registered
- * <li>setSubscriberEventHandlerPriority(subscriber, Class<Event>, priority)
- * <li>allow subscribers to implement interface, ie. EventBus.Subscriber, which lets then test a
- * message before invocation (ie. check if task id == this task id)
- * <li>add postOnce() which automatically debounces
- * <li>add postDelayed() which delays / postDelayedOnce() which delays and bounces
- * <li>consolidate register() and registerInterprocess()
- * <li>sendForResult<ReturnType>(Event) to send and get a result, but who will send the
- * result?
- * </p>
- */
-public class EventBus {
-
- private static final String TAG = "EventBus";
- private static final boolean DEBUG_TRACE_ALL = false;
-
- /**
- * An event super class that allows us to track internal event state across subscriber
- * invocations.
- *
- * Events should not be edited by subscribers.
- */
- public static class Event implements Cloneable {
- // Indicates that this event's dispatch should be traced and logged to logcat
- boolean trace;
- // Indicates that this event must be posted on the EventBus's looper thread before invocation
- boolean requiresPost;
- // Not currently exposed, allows a subscriber to cancel further dispatch of this event
- boolean cancelled;
-
- // Only accessible from derived events
- protected Event() {}
-
- /**
- * Called by the EventBus prior to dispatching this event to any subscriber of this event.
- */
- void onPreDispatch() {
- // Do nothing
- }
-
- /**
- * Called by the EventBus after dispatching this event to every subscriber of this event.
- */
- void onPostDispatch() {
- // Do nothing
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- Event evt = (Event) super.clone();
- // When cloning an event, reset the cancelled-dispatch state
- evt.cancelled = false;
- return evt;
- }
- }
-
- /**
- * An event that represents an animated state change, which allows subscribers to coordinate
- * callbacks which happen after the animation has taken place.
- *
- * Internally, it is guaranteed that increment() and decrement() will be called before and the
- * after the event is dispatched.
- */
- public static class AnimatedEvent extends Event {
-
- private final ReferenceCountedTrigger mTrigger = new ReferenceCountedTrigger();
-
- // Only accessible from derived events
- protected AnimatedEvent() {}
-
- /**
- * Returns the reference counted trigger that coordinates the animations for this event.
- */
- public ReferenceCountedTrigger getAnimationTrigger() {
- return mTrigger;
- }
-
- /**
- * Adds a callback that is guaranteed to be called after the state has changed regardless of
- * whether an actual animation took place.
- */
- public void addPostAnimationCallback(Runnable r) {
- mTrigger.addLastDecrementRunnable(r);
- }
-
- @Override
- void onPreDispatch() {
- mTrigger.increment();
- }
-
- @Override
- void onPostDispatch() {
- mTrigger.decrement();
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- throw new CloneNotSupportedException();
- }
- }
-
- /**
- * An event that can be reusable, only used for situations where we want to reduce memory
- * allocations when events are sent frequently (ie. on scroll).
- */
- public static class ReusableEvent extends Event {
-
- private int mDispatchCount;
-
- protected ReusableEvent() {}
-
- @Override
- void onPostDispatch() {
- super.onPostDispatch();
- mDispatchCount++;
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- throw new CloneNotSupportedException();
- }
- }
-
- /**
- * Proguard must also know, and keep, all methods matching this signature.
- *
- * -keepclassmembers class ** {
- * public void onBusEvent(**);
- * public void onInterprocessBusEvent(**);
- * }
- */
- private static final String METHOD_PREFIX = "onBusEvent";
-
- // The default priority of all subscribers
- private static final int DEFAULT_SUBSCRIBER_PRIORITY = 1;
-
- // Orders the handlers by priority and registration time
- private static final Comparator<EventHandler> EVENT_HANDLER_COMPARATOR = new Comparator<EventHandler>() {
- @Override
- public int compare(EventHandler h1, EventHandler h2) {
- // Rank the handlers by priority descending, followed by registration time descending.
- // aka. the later registered
- if (h1.priority != h2.priority) {
- return h2.priority - h1.priority;
- } else {
- return Long.compare(h2.subscriber.registrationTime, h1.subscriber.registrationTime);
- }
- }
- };
-
- // Used for initializing the default bus
- private static final Object sLock = new Object();
- private static volatile EventBus sDefaultBus;
-
- // The handler to post all events
- private Handler mHandler;
-
- /**
- * Map from event class -> event handler list. Keeps track of the actual mapping from event
- * to subscriber method.
- */
- private HashMap<Class<? extends Event>, ArrayList<EventHandler>> mEventTypeMap = new HashMap<>();
-
- /**
- * Map from subscriber class -> event handler method lists. Used to determine upon registration
- * of a new subscriber whether we need to read all the subscriber's methods again using
- * reflection or whether we can just add the subscriber to the event type map.
- */
- private HashMap<Class<? extends Object>, ArrayList<EventHandlerMethod>> mSubscriberTypeMap = new HashMap<>();
-
- /**
- * Set of all currently registered subscribers
- */
- private ArrayList<Subscriber> mSubscribers = new ArrayList<>();
-
- // For tracing
- private int mCallCount;
- private long mCallDurationMicros;
-
- /**
- * Private constructor to create an event bus for a given looper.
- */
- private EventBus(Looper looper) {
- mHandler = new Handler(looper);
- }
-
- /**
- * @return the default event bus for the application's main thread.
- */
- public static EventBus getDefault() {
- if (sDefaultBus == null)
- synchronized (sLock) {
- if (sDefaultBus == null) {
- if (DEBUG_TRACE_ALL) {
- logWithPid("New EventBus");
- }
- sDefaultBus = new EventBus(Looper.getMainLooper());
- }
- }
- return sDefaultBus;
- }
-
- /**
- * Registers a subscriber to receive events with the default priority.
- *
- * @param subscriber the subscriber to handle events. If this is the first instance of the
- * subscriber's class type that has been registered, the class's methods will
- * be scanned for appropriate event handler methods.
- */
- public void register(Object subscriber) {
- registerSubscriber(subscriber, DEFAULT_SUBSCRIBER_PRIORITY);
- }
-
- /**
- * Registers a subscriber to receive events with the given priority.
- *
- * @param subscriber the subscriber to handle events. If this is the first instance of the
- * subscriber's class type that has been registered, the class's methods will
- * be scanned for appropriate event handler methods.
- * @param priority the priority that this subscriber will receive events relative to other
- * subscribers
- */
- public void register(Object subscriber, int priority) {
- registerSubscriber(subscriber, priority);
- }
-
- /**
- * Remove all EventHandlers pointing to the specified subscriber. This does not remove the
- * mapping of subscriber type to event handler method, in case new instances of this subscriber
- * are registered.
- */
- public void unregister(Object subscriber) {
- if (DEBUG_TRACE_ALL) {
- logWithPid("unregister()");
- }
-
- // Fail immediately if we are being called from the non-main thread
- long callingThreadId = Thread.currentThread().getId();
- if (callingThreadId != mHandler.getLooper().getThread().getId()) {
- throw new RuntimeException("Can not unregister() a subscriber from a non-main thread.");
- }
-
- // Return early if this is not a registered subscriber
- if (!findRegisteredSubscriber(subscriber, true /* removeFoundSubscriber */)) {
- return;
- }
-
- Class<?> subscriberType = subscriber.getClass();
- ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType);
- if (subscriberMethods != null) {
- // For each of the event handlers the subscriber handles, remove all references of that
- // handler
- for (EventHandlerMethod method : subscriberMethods) {
- ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(method.eventType);
- for (int i = eventHandlers.size() - 1; i >= 0; i--) {
- if (eventHandlers.get(i).subscriber.getReference() == subscriber) {
- eventHandlers.remove(i);
- }
- }
- }
- }
- }
-
- /**
- * Sends an event to the subscribers of the given event type immediately. This can only be
- * called from the same thread as the EventBus's looper thread (for the default EventBus, this
- * is the main application thread).
- */
- public void send(Event event) {
- // Fail immediately if we are being called from the non-main thread
- long callingThreadId = Thread.currentThread().getId();
- if (callingThreadId != mHandler.getLooper().getThread().getId()) {
- throw new RuntimeException("Can not send() a message from a non-main thread.");
- }
-
- if (DEBUG_TRACE_ALL) {
- logWithPid("send(" + event.getClass().getSimpleName() + ")");
- }
-
- // Reset the event's cancelled state
- event.requiresPost = false;
- event.cancelled = false;
- queueEvent(event);
- }
-
- /**
- * Post a message to the subscribers of the given event type. The messages will be posted on
- * the EventBus's looper thread (for the default EventBus, this is the main application thread).
- */
- public void post(Event event) {
- if (DEBUG_TRACE_ALL) {
- logWithPid("post(" + event.getClass().getSimpleName() + ")");
- }
-
- // Reset the event's cancelled state
- event.requiresPost = true;
- event.cancelled = false;
- queueEvent(event);
- }
-
- /**
- * If this method is called from the main thread, it will be handled directly. If this method
- * is not called from the main thread, it will be posted onto the main thread.
- */
- public void sendOntoMainThread(Event event) {
- long callingThreadId = Thread.currentThread().getId();
- if (callingThreadId != mHandler.getLooper().getThread().getId()) {
- post(event);
- } else {
- send(event);
- }
- }
-
- /**
- * @return a dump of the current state of the EventBus
- */
- public void dump(String prefix, PrintWriter writer) {
- writer.println(dumpInternal(prefix));
- }
-
- public String dumpInternal(String prefix) {
- String innerPrefix = prefix + " ";
- String innerInnerPrefix = innerPrefix + " ";
- StringBuilder output = new StringBuilder();
- output.append(prefix);
- output.append("Registered class types:");
- output.append("\n");
- ArrayList<Class<?>> subsciberTypes = new ArrayList<>(mSubscriberTypeMap.keySet());
- Collections.sort(subsciberTypes, new Comparator<Class<?>>() {
- @Override
- public int compare(Class<?> o1, Class<?> o2) {
- return o1.getSimpleName().compareTo(o2.getSimpleName());
- }
- });
- for (int i = 0; i < subsciberTypes.size(); i++) {
- Class<?> clz = subsciberTypes.get(i);
- output.append(innerPrefix);
- output.append(clz.getSimpleName());
- output.append("\n");
- }
- output.append(prefix);
- output.append("Event map:");
- output.append("\n");
- ArrayList<Class<?>> classes = new ArrayList<>(mEventTypeMap.keySet());
- Collections.sort(classes, new Comparator<Class<?>>() {
- @Override
- public int compare(Class<?> o1, Class<?> o2) {
- return o1.getSimpleName().compareTo(o2.getSimpleName());
- }
- });
- for (int i = 0; i < classes.size(); i++) {
- Class<?> clz = classes.get(i);
- output.append(innerPrefix);
- output.append(clz.getSimpleName());
- output.append(" -> ");
- output.append("\n");
- ArrayList<EventHandler> handlers = mEventTypeMap.get(clz);
- for (EventHandler handler : handlers) {
- Object subscriber = handler.subscriber.getReference();
- if (subscriber != null) {
- String id = Integer.toHexString(System.identityHashCode(subscriber));
- output.append(innerInnerPrefix);
- output.append(subscriber.getClass().getSimpleName());
- output.append(" [0x" + id + ", #" + handler.priority + "]");
- output.append("\n");
- }
- }
- }
- return output.toString();
- }
-
- /**
- * Registers a new subscriber.
- */
- private void registerSubscriber(Object subscriber, int priority) {
- // Fail immediately if we are being called from the non-main thread
- long callingThreadId = Thread.currentThread().getId();
- if (callingThreadId != mHandler.getLooper().getThread().getId()) {
- throw new RuntimeException("Can not register() a subscriber from a non-main thread.");
- }
-
- // Return immediately if this exact subscriber is already registered
- if (findRegisteredSubscriber(subscriber, false /* removeFoundSubscriber */)) {
- return;
- }
-
- long t1 = 0;
- if (DEBUG_TRACE_ALL) {
- t1 = SystemClock.currentTimeMicro();
- logWithPid("registerSubscriber(" + subscriber.getClass().getSimpleName() + ")");
- }
- Subscriber sub = new Subscriber(subscriber, SystemClock.uptimeMillis());
- Class<?> subscriberType = subscriber.getClass();
- ArrayList<EventHandlerMethod> subscriberMethods = mSubscriberTypeMap.get(subscriberType);
- if (subscriberMethods != null) {
- if (DEBUG_TRACE_ALL) {
- logWithPid("Subscriber class type already registered");
- }
-
- // If we've parsed this subscriber type before, just add to the set for all the known
- // events
- for (EventHandlerMethod method : subscriberMethods) {
- ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(method.eventType);
- eventTypeHandlers.add(new EventHandler(sub, method, priority));
- sortEventHandlersByPriority(eventTypeHandlers);
- }
- mSubscribers.add(sub);
- return;
- } else {
- if (DEBUG_TRACE_ALL) {
- logWithPid("Subscriber class type requires registration");
- }
-
- // If we are parsing this type from scratch, ensure we add it to the subscriber type
- // map, and pull out he handler methods below
- subscriberMethods = new ArrayList<>();
- mSubscriberTypeMap.put(subscriberType, subscriberMethods);
- mSubscribers.add(sub);
- }
-
- // Find all the valid event bus handler methods of the subscriber
- Method[] methods = subscriberType.getDeclaredMethods();
- for (Method m : methods) {
- Class<?>[] parameterTypes = m.getParameterTypes();
- if (isValidEventBusHandlerMethod(m, parameterTypes)) {
- Class<? extends Event> eventType = (Class<? extends Event>) parameterTypes[0];
- ArrayList<EventHandler> eventTypeHandlers = mEventTypeMap.get(eventType);
- if (eventTypeHandlers == null) {
- eventTypeHandlers = new ArrayList<>();
- mEventTypeMap.put(eventType, eventTypeHandlers);
- }
- EventHandlerMethod method = new EventHandlerMethod(m, eventType);
- EventHandler handler = new EventHandler(sub, method, priority);
- eventTypeHandlers.add(handler);
- subscriberMethods.add(method);
- sortEventHandlersByPriority(eventTypeHandlers);
-
- if (DEBUG_TRACE_ALL) {
- logWithPid(" * Method: " + m.getName() +
- " event: " + parameterTypes[0].getSimpleName());
- }
- }
- }
- if (DEBUG_TRACE_ALL) {
- logWithPid("Registered " + subscriber.getClass().getSimpleName() + " in " +
- (SystemClock.currentTimeMicro() - t1) + " microseconds");
- }
- }
-
- /**
- * Adds a new message.
- */
- private void queueEvent(final Event event) {
- ArrayList<EventHandler> eventHandlers = mEventTypeMap.get(event.getClass());
- if (eventHandlers == null) {
- // This is just an optimization to return early if there are no handlers. However, we
- // should still ensure that we call pre/post dispatch callbacks so that AnimatedEvents
- // are still cleaned up correctly if a listener has not been registered to handle them
- event.onPreDispatch();
- event.onPostDispatch();
- return;
- }
-
- // Prepare this event
- boolean hasPostedEvent = false;
- event.onPreDispatch();
-
- // We need to clone the list in case a subscriber unregisters itself during traversal
- // TODO: Investigate whether we can skip the object creation here
- eventHandlers = (ArrayList<EventHandler>) eventHandlers.clone();
- int eventHandlerCount = eventHandlers.size();
- for (int i = 0; i < eventHandlerCount; i++) {
- final EventHandler eventHandler = eventHandlers.get(i);
- if (eventHandler.subscriber.getReference() != null) {
- if (event.requiresPost) {
- mHandler.post(() -> processEvent(eventHandler, event));
- hasPostedEvent = true;
- } else {
- processEvent(eventHandler, event);
- }
- }
- }
-
- // Clean up after this event, deferring until all subscribers have been called
- if (hasPostedEvent) {
- mHandler.post(event::onPostDispatch);
- } else {
- event.onPostDispatch();
- }
- }
-
- /**
- * Processes and dispatches the given event to the given event handler, on the thread of whoever
- * calls this method.
- */
- private void processEvent(final EventHandler eventHandler, final Event event) {
- // Skip if the event was already cancelled
- if (event.cancelled) {
- if (event.trace || DEBUG_TRACE_ALL) {
- logWithPid("Event dispatch cancelled");
- }
- return;
- }
-
- try {
- if (event.trace || DEBUG_TRACE_ALL) {
- logWithPid(" -> " + eventHandler.toString());
- }
- Object sub = eventHandler.subscriber.getReference();
- if (sub != null) {
- long t1 = 0;
- if (DEBUG_TRACE_ALL) {
- t1 = SystemClock.currentTimeMicro();
- }
- eventHandler.method.invoke(sub, event);
- if (DEBUG_TRACE_ALL) {
- long duration = (SystemClock.currentTimeMicro() - t1);
- mCallDurationMicros += duration;
- mCallCount++;
- logWithPid(eventHandler.method.toString() + " duration: " + duration +
- " microseconds, avg: " + (mCallDurationMicros / mCallCount));
- }
- } else {
- Log.e(TAG, "Failed to deliver event to null subscriber");
- }
- } catch (IllegalAccessException e) {
- Log.e(TAG, "Failed to invoke method", e.getCause());
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e.getCause());
- }
- }
-
- /**
- * Returns whether this subscriber is currently registered. If {@param removeFoundSubscriber}
- * is true, then remove the subscriber before returning.
- */
- private boolean findRegisteredSubscriber(Object subscriber, boolean removeFoundSubscriber) {
- for (int i = mSubscribers.size() - 1; i >= 0; i--) {
- Subscriber sub = mSubscribers.get(i);
- if (sub.getReference() == subscriber) {
- if (removeFoundSubscriber) {
- mSubscribers.remove(i);
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * @return whether {@param method} is a valid (normal or interprocess) event bus handler method
- */
- private boolean isValidEventBusHandlerMethod(Method method, Class<?>[] parameterTypes) {
- int modifiers = method.getModifiers();
- if (Modifier.isPublic(modifiers) &&
- Modifier.isFinal(modifiers) &&
- method.getReturnType().equals(Void.TYPE) &&
- parameterTypes.length == 1) {
- if (EventBus.Event.class.isAssignableFrom(parameterTypes[0]) &&
- method.getName().startsWith(METHOD_PREFIX)) {
- return true;
- } else {
- if (DEBUG_TRACE_ALL) {
- if (!EventBus.Event.class.isAssignableFrom(parameterTypes[0])) {
- logWithPid(" Expected method take an Event-based parameter: " + method.getName());
- }
- }
- }
- } else {
- if (DEBUG_TRACE_ALL) {
- if (!Modifier.isPublic(modifiers)) {
- logWithPid(" Expected method to be public: " + method.getName());
- } else if (!Modifier.isFinal(modifiers)) {
- logWithPid(" Expected method to be final: " + method.getName());
- } else if (!method.getReturnType().equals(Void.TYPE)) {
- logWithPid(" Expected method to return null: " + method.getName());
- }
- }
- }
- return false;
- }
-
- /**
- * Sorts the event handlers by priority and registration time.
- */
- private void sortEventHandlersByPriority(List<EventHandler> eventHandlers) {
- Collections.sort(eventHandlers, EVENT_HANDLER_COMPARATOR);
- }
-
- /**
- * Helper method to log the given {@param text} with the current process and user id.
- */
- private static void logWithPid(String text) {
- Log.d(TAG, "[" + android.os.Process.myPid() + ", u" + UserHandle.myUserId() + "] " + text);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java
deleted file mode 100644
index 4738eed..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppTransitionFinishedEvent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Sent when an app transition has finished playing.
- */
-public class AppTransitionFinishedEvent extends EventBus.Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
deleted file mode 100644
index fec34e3..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/CancelEnterRecentsWindowAnimationEvent.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-
-/**
- * This is sent when we want to cancel the enter-recents window animation for the launch task.
- */
-public class CancelEnterRecentsWindowAnimationEvent extends EventBus.Event {
-
- // This is set for the task that is launching, which allows us to ensure that we are not
- // cancelling the same task animation (it will just be overwritten instead)
- public final Task launchTask;
-
- public CancelEnterRecentsWindowAnimationEvent(Task launchTask) {
- this.launchTask = launchTask;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
deleted file mode 100644
index 294c1e7..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the Recents activity configuration has changed.
- */
-public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
-
- public final boolean fromMultiWindow;
- public final boolean fromDeviceOrientationChange;
- public final boolean fromDisplayDensityChange;
- public final boolean hasStackTasks;
-
- public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromDeviceOrientationChange,
- boolean fromDisplayDensityChange, boolean hasStackTasks) {
- this.fromMultiWindow = fromMultiWindow;
- this.fromDeviceOrientationChange = fromDeviceOrientationChange;
- this.fromDisplayDensityChange = fromDisplayDensityChange;
- this.hasStackTasks = hasStackTasks;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java
deleted file mode 100644
index e7be858..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DismissRecentsToHomeAnimationStarted.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the task animation when dismissing Recents starts.
- */
-public class DismissRecentsToHomeAnimationStarted extends EventBus.AnimatedEvent {
-
- public final boolean animated;
-
- public DismissRecentsToHomeAnimationStarted(boolean animated) {
- this.animated = animated;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java
deleted file mode 100644
index 32d9a70..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedFirstAnimationFrameEvent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus.Event;
-
-/**
- * Sent when the window animation has started when docking a task
- */
-public class DockedFirstAnimationFrameEvent extends Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
deleted file mode 100644
index 9e3ced3..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/DockedTopTaskEvent.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.activity;
-
-import android.graphics.Rect;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Fires when the user invoked the gesture to dock the top/left task after we called into window
- * manager and before we start recents.
- */
-public class DockedTopTaskEvent extends EventBus.Event {
-
- public Rect initialRect;
-
- public DockedTopTaskEvent(Rect initialRect) {
- this.initialRect = initialRect;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
deleted file mode 100644
index b31f320..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowAnimationCompletedEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the window animation into Recents completes. We use this signal to know when
- * we can start in-app animations so that they don't conflict with the window transition into
- * Recents.
- */
-public class EnterRecentsWindowAnimationCompletedEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java
deleted file mode 100644
index fd023d8..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/EnterRecentsWindowLastAnimationFrameEvent.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-public class EnterRecentsWindowLastAnimationFrameEvent extends EventBus.Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java
deleted file mode 100644
index fa806eb..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ExitRecentsWindowFirstAnimationFrameEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Event sent when the exit animation is started.
- *
- * This is sent so parts of UI can synchronize on this event and adjust their appearance. An example
- * of that is hiding the tasks when the launched application window becomes visible.
- */
-public class ExitRecentsWindowFirstAnimationFrameEvent extends EventBus.Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java
deleted file mode 100644
index bf9b421..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideRecentsEvent.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the user taps on the Home button or finishes alt-tabbing to hide the Recents
- * activity.
- */
-public class HideRecentsEvent extends EventBus.Event {
-
- public final boolean triggeredFromAltTab;
- public final boolean triggeredFromHomeKey;
-
- public HideRecentsEvent(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
- this.triggeredFromAltTab = triggeredFromAltTab;
- this.triggeredFromHomeKey = triggeredFromHomeKey;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
deleted file mode 100644
index e4a4f59..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the stack action button should be hidden.
- */
-public class HideStackActionButtonEvent extends EventBus.Event {
-
- // Whether or not to translate the stack action button when hiding it
- public final boolean translate;
-
- public HideStackActionButtonEvent() {
- this(true);
- }
-
- public HideStackActionButtonEvent(boolean translate) {
- this.translate = translate;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
deleted file mode 100644
index 24913a4..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchMostRecentTaskRequestEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This event is sent to request that the most recent task is launched.
- */
-public class LaunchMostRecentTaskRequestEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
deleted file mode 100644
index 11604b5..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchNextTaskRequestEvent.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This event is sent to request that the next task is launched after a double-tap on the Recents
- * button.
- */
-public class LaunchNextTaskRequestEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
deleted file mode 100644
index 2409f39..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskEvent.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
-import android.graphics.Rect;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent to request that a particular task is launched.
- */
-public class LaunchTaskEvent extends EventBus.Event {
-
- public final TaskView taskView;
- public final Task task;
- public final Rect targetTaskBounds;
- public final int targetWindowingMode;
- public final int targetActivityType;
- public final boolean screenPinningRequested;
-
- public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds,
- boolean screenPinningRequested) {
- this(taskView, task, targetTaskBounds, screenPinningRequested,
- WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED);
- }
-
- public LaunchTaskEvent(TaskView taskView, Task task, Rect targetTaskBounds,
- boolean screenPinningRequested, int windowingMode, int activityType) {
- this.taskView = taskView;
- this.task = task;
- this.targetTaskBounds = targetTaskBounds;
- this.targetWindowingMode = windowingMode;
- this.targetActivityType = activityType;
- this.screenPinningRequested = screenPinningRequested;
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
deleted file mode 100644
index 3a2d58c..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskFailedEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when we fail to launch a task.
- */
-public class LaunchTaskFailedEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java
deleted file mode 100644
index 3925ab1..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskStartedEvent.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent following {@link LaunchTaskEvent} after the call to the system is made to
- * start the task.
- */
-public class LaunchTaskStartedEvent extends EventBus.AnimatedEvent {
-
- public final TaskView taskView;
- public final boolean screenPinningRequested;
-
- public LaunchTaskStartedEvent(TaskView taskView, boolean screenPinningRequested) {
- this.taskView = taskView;
- this.screenPinningRequested = screenPinningRequested;
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
deleted file mode 100644
index ec5089f..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/LaunchTaskSucceededEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when we successfully launch a task.
- */
-public class LaunchTaskSucceededEvent extends EventBus.Event {
-
- public final int taskIndexFromStackFront;
-
- public LaunchTaskSucceededEvent(int taskIndexFromStackFront) {
- this.taskIndexFromStackFront = taskIndexFromStackFront;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
deleted file mode 100644
index e4972b1..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.TaskStack;
-
-/**
- * This is sent by the activity whenever the multi-window state has changed.
- */
-public class MultiWindowStateChangedEvent extends EventBus.AnimatedEvent {
-
- public final boolean inMultiWindow;
- // This flag is only used when undocking a task
- public final boolean showDeferredAnimation;
- public final TaskStack stack;
-
- public MultiWindowStateChangedEvent(boolean inMultiWindow, boolean showDeferredAnimation,
- TaskStack stack) {
- this.inMultiWindow = inMultiWindow;
- this.showDeferredAnimation = showDeferredAnimation;
- this.stack = stack;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
deleted file mode 100644
index 47670e0..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/PackagesChangedEvent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.views.TaskStackView;
-import com.android.systemui.recents.RecentsActivity;
-
-/**
- * This event is sent by {@link RecentsActivity} when a package on the the system changes.
- * {@link TaskStackView}s listen for this event, and remove the tasks associated with the removed
- * packages.
- */
-public class PackagesChangedEvent extends EventBus.Event {
-
- public final String packageName;
- public final int userId;
-
- public PackagesChangedEvent(String packageName, int userId) {
- this.packageName = packageName;
- this.userId = userId;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java
deleted file mode 100644
index a2ecfe2..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/RecentsActivityStartingEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Called after recents activity is being started, i.e. startActivity has just been called.
- */
-public class RecentsActivityStartingEvent extends EventBus.Event{
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
deleted file mode 100644
index 75bfd7b..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowEmptyViewEvent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Sent when the stack should be hidden and the empty view shown.
- */
-public class ShowEmptyViewEvent extends EventBus.Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
deleted file mode 100644
index d81f89c..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the stack action view button should be shown.
- */
-public class ShowStackActionButtonEvent extends EventBus.Event {
-
- // Whether or not to translate the stack action button when showing it
- public final boolean translate;
-
- public ShowStackActionButtonEvent(boolean translate) {
- this.translate = translate;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
deleted file mode 100644
index 51d02b5..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/TaskStackUpdatedEvent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.TaskStack;
-
-/**
- * This is sent by the activity whenever the task stach has changed.
- */
-public class TaskStackUpdatedEvent extends EventBus.AnimatedEvent {
-
- /**
- * A new TaskStack instance representing the latest stack state.
- */
- public final TaskStack stack;
- public final boolean inMultiWindow;
-
- public TaskStackUpdatedEvent(TaskStack stack, boolean inMultiWindow) {
- this.stack = stack;
- this.inMultiWindow = inMultiWindow;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java
deleted file mode 100644
index 49655b4..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleRecentsEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the user taps on the Overview button to toggle the Recents activity.
- */
-public class ToggleRecentsEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
deleted file mode 100644
index d5083a8..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/UndockingTaskEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Fires when the user invoked the gesture to undock the task in the docked stack.
- */
-public class UndockingTaskEvent extends EventBus.Event {
-
- public UndockingTaskEvent() {
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
deleted file mode 100644
index f4d2fcf..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityPinnedEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when an activity is pinned.
- */
-public class ActivityPinnedEvent extends EventBus.Event {
-
- public final int taskId;
-
- public ActivityPinnedEvent(int taskId) {
- this.taskId = taskId;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
deleted file mode 100644
index 48c5f0b..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/ActivityUnpinnedEvent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when an activity is unpinned.
- */
-public class ActivityUnpinnedEvent extends EventBus.Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
deleted file mode 100644
index 37266f6..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/ExpandPipEvent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the PiP should be expanded due to being relaunched.
- */
-public class ExpandPipEvent extends EventBus.Event {
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
deleted file mode 100644
index ce4f207..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/HidePipMenuEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the PiP menu should be hidden.
- */
-public class HidePipMenuEvent extends EventBus.AnimatedEvent {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
deleted file mode 100644
index 8843eb4..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/RecentsVisibilityChangedEvent.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import android.content.Context;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the visibility of the RecentsActivity for the current user changes. Handlers
- * of this event should not alter the UI, as the activity may still be visible.
- */
-public class RecentsVisibilityChangedEvent extends EventBus.Event {
-
- public final Context applicationContext;
- public final boolean visible;
-
- public RecentsVisibilityChangedEvent(Context context, boolean visible) {
- this.applicationContext = context.getApplicationContext();
- this.visible = visible;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
deleted file mode 100644
index d460917..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/ScreenPinningRequestEvent.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import android.content.Context;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when we want to start screen pinning.
- */
-public class ScreenPinningRequestEvent extends EventBus.Event {
-
- public final Context applicationContext;
- public final int taskId;
-
- public ScreenPinningRequestEvent(Context context, int taskId) {
- this.applicationContext = context.getApplicationContext();
- this.taskId = taskId;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
deleted file mode 100644
index d9cf5fb..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when we are setting/resetting the flag to wait for the transition to start.
- */
-public class SetWaitingForTransitionStartEvent extends EventBus.Event {
-
- public final boolean waitingForTransitionStart;
-
- public SetWaitingForTransitionStartEvent(boolean waitingForTransitionStart) {
- this.waitingForTransitionStart = waitingForTransitionStart;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java
deleted file mode 100644
index e2b39c3..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/component/ShowUserToastEvent.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.component;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when we want to show a toast for the current user.
- */
-public class ShowUserToastEvent extends EventBus.Event {
-
- public final int msgResId;
- public final int msgLength;
-
- public ShowUserToastEvent(int msgResId, int msgLength) {
- this.msgResId = msgResId;
- this.msgLength = msgLength;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
deleted file mode 100644
index 0352161..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/AllTaskViewsDismissedEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent whenever all the task views in a stack have been dismissed.
- */
-public class AllTaskViewsDismissedEvent extends EventBus.Event {
-
- public final int msgResId;
-
- public AllTaskViewsDismissedEvent(int msgResId) {
- this.msgResId = msgResId;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java
deleted file mode 100644
index b52e83b..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DeleteTaskDataEvent.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-
-/**
- * This is sent when the data associated with a given {@link Task} should be deleted from the
- * system.
- */
-public class DeleteTaskDataEvent extends EventBus.Event {
-
- public final Task task;
-
- public DeleteTaskDataEvent(Task task) {
- this.task = task;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
deleted file mode 100644
index f8b59c7..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent to request that all the {@link TaskView}s are dismissed.
- */
-public class DismissAllTaskViewsEvent extends EventBus.AnimatedEvent {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
deleted file mode 100644
index 1f8c644..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent to request that the given {@link TaskView} is dismissed.
- */
-public class DismissTaskViewEvent extends EventBus.AnimatedEvent {
-
- public final TaskView taskView;
-
- public DismissTaskViewEvent(TaskView taskView) {
- this.taskView = taskView;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java
deleted file mode 100644
index 9be8eb1..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEndedEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus.Event;
-
-/**
- * This event is sent when the user finished dragging in recents.
- */
-public class DraggingInRecentsEndedEvent extends Event {
-
- public final float velocity;
-
- public DraggingInRecentsEndedEvent(float velocity) {
- this.velocity = velocity;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java
deleted file mode 100644
index 5e8bfd4..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DraggingInRecentsEvent.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus.Event;
-
-/**
- * This event is sent when the user changed how far they are dragging in recents.
- */
-public class DraggingInRecentsEvent extends Event {
-
- public final float distanceFromTop;
-
- public DraggingInRecentsEvent(float distanceFromTop) {
- this.distanceFromTop = distanceFromTop;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
deleted file mode 100644
index d6ef636..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/HideIncompatibleAppOverlayEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when a user stops draggin an incompatible app task.
- */
-public class HideIncompatibleAppOverlayEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java
deleted file mode 100644
index 5483166..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsDrawnEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Fired when recents was launched and has drawn its first frame.
- */
-public class RecentsDrawnEvent extends EventBus.Event {
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
deleted file mode 100644
index d9b0027..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/RecentsGrowingEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Sent when recents is about to grow in multi-window mode when entering recents.
- */
-public class RecentsGrowingEvent extends EventBus.Event {
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
deleted file mode 100644
index da19384..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowApplicationInfoEvent.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-
-/**
- * This is sent when a user wants to show the application info for a {@link Task}.
- */
-public class ShowApplicationInfoEvent extends EventBus.Event {
-
- public final Task task;
-
- public ShowApplicationInfoEvent(Task task) {
- this.task = task;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
deleted file mode 100644
index 3a4350e..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ShowIncompatibleAppOverlayEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when a user starts dragging an incompatible app task.
- */
-public class ShowIncompatibleAppOverlayEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java
deleted file mode 100644
index c4b47c0..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/StackViewScrolledEvent.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import android.util.MutableInt;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent whenever a new scroll gesture happens on a stack view.
- */
-public class StackViewScrolledEvent extends EventBus.ReusableEvent {
-
- public final MutableInt yMovement;
-
- public StackViewScrolledEvent() {
- yMovement = new MutableInt(0);
- }
-
- public void updateY(int y) {
- yMovement.value = y;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java
deleted file mode 100644
index f082928..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskSnapshotChangedEvent.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-
-/**
- * Sent when a task snapshot has changed.
- */
-public class TaskSnapshotChangedEvent extends EventBus.Event {
-
- public final int taskId;
- public final ThumbnailData thumbnailData;
-
- public TaskSnapshotChangedEvent(int taskId, ThumbnailData thumbnailData) {
- this.taskId = taskId;
- this.thumbnailData = thumbnailData;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
deleted file mode 100644
index 881a64a..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/TaskViewDismissedEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent when a {@link TaskView} has been dismissed and is no longer visible.
- */
-public class TaskViewDismissedEvent extends EventBus.Event {
-
- public final Task task;
- public final TaskView taskView;
- public final AnimationProps animation;
-
- public TaskViewDismissedEvent(Task task, TaskView taskView, AnimationProps animation) {
- this.task = task;
- this.taskView = taskView;
- this.animation = animation;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java
deleted file mode 100644
index 39e4c1d..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UserInteractionEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent whenever the user interacts with the activity.
- */
-public class UserInteractionEvent extends EventBus.ReusableEvent {
- // Simple Event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
deleted file mode 100644
index cf61b1e..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragDropTargetChangedEvent.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.dragndrop;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.DropTarget;
-
-/**
- * This event is sent when a user drags in/out of a drop target.
- */
-public class DragDropTargetChangedEvent extends EventBus.AnimatedEvent {
-
- // The task that is currently being dragged
- public final Task task;
- public final DropTarget dropTarget;
-
- public DragDropTargetChangedEvent(Task task, DropTarget dropTarget) {
- this.task = task;
- this.dropTarget = dropTarget;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
deleted file mode 100644
index 297afc5..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndCancelledEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.dragndrop;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent whenever a drag end is cancelled because of an error.
- */
-public class DragEndCancelledEvent extends EventBus.AnimatedEvent {
-
- public final TaskStack stack;
- public final Task task;
- public final TaskView taskView;
-
- public DragEndCancelledEvent(TaskStack stack, Task task, TaskView taskView) {
- this.stack = stack;
- this.task = task;
- this.taskView = taskView;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
deleted file mode 100644
index 73cbde9..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragEndEvent.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.dragndrop;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.DropTarget;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent whenever a drag ends.
- */
-public class DragEndEvent extends EventBus.AnimatedEvent {
-
- public final Task task;
- public final TaskView taskView;
- public final DropTarget dropTarget;
-
- public DragEndEvent(Task task, TaskView taskView, DropTarget dropTarget) {
- this.task = task;
- this.taskView = taskView;
- this.dropTarget = dropTarget;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
deleted file mode 100644
index 021be77..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartEvent.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.dragndrop;
-
-import android.graphics.Point;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent whenever a drag starts.
- */
-public class DragStartEvent extends EventBus.Event {
-
- public final Task task;
- public final TaskView taskView;
- public final Point tlOffset;
- public final boolean isUserTouchInitiated;
-
- public DragStartEvent(Task task, TaskView taskView, Point tlOffset) {
- this(task, taskView, tlOffset, true);
- }
-
- public DragStartEvent(Task task, TaskView taskView, Point tlOffset,
- boolean isUserTouchInitiated) {
- this.task = task;
- this.taskView = taskView;
- this.tlOffset = tlOffset;
- this.isUserTouchInitiated = isUserTouchInitiated;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java
deleted file mode 100644
index 64ba574..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/dragndrop/DragStartInitializeDropTargetsEvent.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.dragndrop;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.RecentsViewTouchHandler;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent by the drag manager when it requires drop targets to register themselves for
- * the current drag gesture.
- */
-public class DragStartInitializeDropTargetsEvent extends EventBus.Event {
-
- public final Task task;
- public final TaskView taskView;
- public final RecentsViewTouchHandler handler;
-
- public DragStartInitializeDropTargetsEvent(Task task, TaskView taskView,
- RecentsViewTouchHandler handler) {
- this.task = task;
- this.taskView = taskView;
- this.handler = handler;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
deleted file mode 100644
index df74018..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/DismissFocusedTaskViewEvent.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.focus;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.views.TaskView;
-
-/**
- * This event is sent to request that the currently focused {@link TaskView} is dismissed.
- */
-public class DismissFocusedTaskViewEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
deleted file mode 100644
index 171ab5e..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusNextTaskViewEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.focus;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Focuses the next task view in the stack.
- */
-public class FocusNextTaskViewEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
deleted file mode 100644
index 22469e7..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/FocusPreviousTaskViewEvent.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.focus;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Focuses the previous task view in the stack.
- */
-public class FocusPreviousTaskViewEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
deleted file mode 100644
index 5508d26..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/focus/NavigateTaskViewEvent.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.ui.focus;
-
-import android.view.KeyEvent;
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * Navigates the task view by arrow keys.
- */
-public class NavigateTaskViewEvent extends EventBus.Event {
- public enum Direction {
- UNDEFINED, UP, DOWN, LEFT, RIGHT;
- }
-
- public Direction direction;
- public NavigateTaskViewEvent(Direction direction) {
- this.direction = direction;
- }
-
- public static Direction getDirectionFromKeyCode(int keyCode) {
- switch (keyCode) {
- case KeyEvent.KEYCODE_DPAD_UP:
- return Direction.UP;
- case KeyEvent.KEYCODE_DPAD_DOWN:
- return Direction.DOWN;
- case KeyEvent.KEYCODE_DPAD_LEFT:
- return Direction.LEFT;
- case KeyEvent.KEYCODE_DPAD_RIGHT:
- return Direction.RIGHT;
- default:
- return Direction.UNDEFINED;
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
deleted file mode 100644
index 574ea03..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/DozeTrigger.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-import android.os.Handler;
-import android.view.ViewDebug;
-
-/**
- * A dozer is a class that fires a trigger after it falls asleep.
- * You can occasionally poke the trigger to wake it up, but it will fall asleep if left untouched.
- */
-public class DozeTrigger {
-
- Handler mHandler;
-
- @ViewDebug.ExportedProperty(category="recents")
- boolean mIsDozing;
- @ViewDebug.ExportedProperty(category="recents")
- boolean mIsAsleep;
- @ViewDebug.ExportedProperty(category="recents")
- int mDozeDurationMilliseconds;
- Runnable mOnSleepRunnable;
-
- // Sleep-runnable
- Runnable mDozeRunnable = new Runnable() {
- @Override
- public void run() {
- mIsDozing = false;
- mIsAsleep = true;
- mOnSleepRunnable.run();
- }
- };
-
- public DozeTrigger(int dozeDurationMilliseconds, Runnable onSleepRunnable) {
- mHandler = new Handler();
- mDozeDurationMilliseconds = dozeDurationMilliseconds;
- mOnSleepRunnable = onSleepRunnable;
- }
-
- /**
- * Starts dozing and queues the onSleepRunnable to be called. This also resets the trigger flag.
- */
- public void startDozing() {
- forcePoke();
- mIsAsleep = false;
- }
-
- /**
- * Stops dozing and prevents the onSleepRunnable from being called.
- */
- public void stopDozing() {
- mHandler.removeCallbacks(mDozeRunnable);
- mIsDozing = false;
- mIsAsleep = false;
- }
-
- /**
- * Updates the duration that we have to wait until dozing triggers.
- */
- public void setDozeDuration(int duration) {
- mDozeDurationMilliseconds = duration;
- }
-
- /**
- * Poke this dozer to wake it up if it is dozing, delaying the onSleepRunnable from being
- * called for a for the doze duration.
- */
- public void poke() {
- if (mIsDozing) {
- forcePoke();
- }
- }
-
- /**
- * Poke this dozer to wake it up even if it is not currently dozing.
- */
- void forcePoke() {
- mHandler.removeCallbacks(mDozeRunnable);
- mHandler.postDelayed(mDozeRunnable, mDozeDurationMilliseconds);
- mIsDozing = true;
- }
-
- /** Returns whether we are dozing or not. */
- public boolean isDozing() {
- return mIsDozing;
- }
-
- /** Returns whether the trigger has fired at least once. */
- public boolean isAsleep() {
- return mIsAsleep;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/FreePathInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/misc/FreePathInterpolator.java
deleted file mode 100644
index 720c952..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/FreePathInterpolator.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-import android.graphics.Path;
-import android.view.animation.BaseInterpolator;
-import android.view.animation.Interpolator;
-
-/**
- * An interpolator that can traverse a Path. The x coordinate along the <code>Path</code>
- * is the input value and the output is the y coordinate of the line at that point.
- * This means that the Path must conform to a function <code>y = f(x)</code>.
- *
- * <p>The <code>Path</code> must not have gaps in the x direction and must not
- * loop back on itself such that there can be two points sharing the same x coordinate.
- * It is alright to have a disjoint line in the vertical direction:</p>
- * <p><blockquote><pre>
- * Path path = new Path();
- * path.lineTo(0.25f, 0.25f);
- * path.moveTo(0.25f, 0.5f);
- * path.lineTo(1f, 1f);
- * </pre></blockquote></p>
- */
-public class FreePathInterpolator extends BaseInterpolator {
-
- // This governs how accurate the approximation of the Path is.
- private static final float PRECISION = 0.002f;
-
- private float[] mX;
- private float[] mY;
- private float mArcLength;
-
- /**
- * Create an interpolator for an arbitrary <code>Path</code>.
- *
- * @param path The <code>Path</code> to use to make the line representing the interpolator.
- */
- public FreePathInterpolator(Path path) {
- initPath(path);
- }
-
- private void initPath(Path path) {
- float[] pointComponents = path.approximate(PRECISION);
-
- int numPoints = pointComponents.length / 3;
-
- mX = new float[numPoints];
- mY = new float[numPoints];
- mArcLength = 0;
- float prevX = 0;
- float prevY = 0;
- float prevFraction = 0;
- int componentIndex = 0;
- for (int i = 0; i < numPoints; i++) {
- float fraction = pointComponents[componentIndex++];
- float x = pointComponents[componentIndex++];
- float y = pointComponents[componentIndex++];
- if (fraction == prevFraction && x != prevX) {
- throw new IllegalArgumentException(
- "The Path cannot have discontinuity in the X axis.");
- }
- if (x < prevX) {
- throw new IllegalArgumentException("The Path cannot loop back on itself.");
- }
- mX[i] = x;
- mY[i] = y;
- mArcLength += Math.hypot(x - prevX, y - prevY);
- prevX = x;
- prevY = y;
- prevFraction = fraction;
- }
- }
-
- /**
- * Using the line in the Path in this interpolator that can be described as
- * <code>y = f(x)</code>, finds the y coordinate of the line given <code>t</code>
- * as the x coordinate.
- *
- * @param t Treated as the x coordinate along the line.
- * @return The y coordinate of the Path along the line where x = <code>t</code>.
- * @see Interpolator#getInterpolation(float)
- */
- @Override
- public float getInterpolation(float t) {
- int startIndex = 0;
- int endIndex = mX.length - 1;
-
- // Return early if out of bounds
- if (t <= 0) {
- return mY[startIndex];
- } else if (t >= 1) {
- return mY[endIndex];
- }
-
- // Do a binary search for the correct x to interpolate between.
- while (endIndex - startIndex > 1) {
- int midIndex = (startIndex + endIndex) / 2;
- if (t < mX[midIndex]) {
- endIndex = midIndex;
- } else {
- startIndex = midIndex;
- }
- }
-
- float xRange = mX[endIndex] - mX[startIndex];
- if (xRange == 0) {
- return mY[startIndex];
- }
-
- float tInRange = t - mX[startIndex];
- float fraction = tInRange / xRange;
-
- float startY = mY[startIndex];
- float endY = mY[endIndex];
- return startY + (fraction * (endY - startY));
- }
-
- /**
- * Finds the x that provides the given <code>y = f(x)</code>.
- *
- * @param y a value from (0,1) that is in this path.
- */
- public float getX(float y) {
- int startIndex = 0;
- int endIndex = mY.length - 1;
-
- // Return early if out of bounds
- if (y <= 0) {
- return mX[endIndex];
- } else if (y >= 1) {
- return mX[startIndex];
- }
-
- // Do a binary search for index that bounds the y
- while (endIndex - startIndex > 1) {
- int midIndex = (startIndex + endIndex) / 2;
- if (y < mY[midIndex]) {
- startIndex = midIndex;
- } else {
- endIndex = midIndex;
- }
- }
-
- float yRange = mY[endIndex] - mY[startIndex];
- if (yRange == 0) {
- return mX[startIndex];
- }
-
- float tInRange = y - mY[startIndex];
- float fraction = tInRange / yRange;
-
- float startX = mX[startIndex];
- float endX = mX[endIndex];
- return startX + (fraction * (endX - startX));
- }
-
- /**
- * Returns the arclength of the path we are interpolating.
- */
- public float getArcLength() {
- return mArcLength;
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
deleted file mode 100644
index 2637d88..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-
-import java.util.ArrayList;
-
-/**
- * A ref counted trigger that does some logic when the count is first incremented, or last
- * decremented. Not thread safe as it's not currently needed.
- */
-public class ReferenceCountedTrigger {
-
- int mCount;
- ArrayList<Runnable> mFirstIncRunnables = new ArrayList<>();
- ArrayList<Runnable> mLastDecRunnables = new ArrayList<>();
- Runnable mErrorRunnable;
-
- // Convenience runnables
- Runnable mIncrementRunnable = new Runnable() {
- @Override
- public void run() {
- increment();
- }
- };
- Runnable mDecrementRunnable = new Runnable() {
- @Override
- public void run() {
- decrement();
- }
- };
-
- public ReferenceCountedTrigger() {
- this(null, null, null);
- }
-
- public ReferenceCountedTrigger(Runnable firstIncRunnable, Runnable lastDecRunnable,
- Runnable errorRunanable) {
- if (firstIncRunnable != null) mFirstIncRunnables.add(firstIncRunnable);
- if (lastDecRunnable != null) mLastDecRunnables.add(lastDecRunnable);
- mErrorRunnable = errorRunanable;
- }
-
- /** Increments the ref count */
- public void increment() {
- if (mCount == 0 && !mFirstIncRunnables.isEmpty()) {
- int numRunnables = mFirstIncRunnables.size();
- for (int i = 0; i < numRunnables; i++) {
- mFirstIncRunnables.get(i).run();
- }
- }
- mCount++;
- }
-
- /** Convenience method to increment this trigger as a runnable */
- public Runnable incrementAsRunnable() {
- return mIncrementRunnable;
- }
-
- /** Adds a runnable to the last-decrement runnables list. */
- public void addLastDecrementRunnable(Runnable r) {
- mLastDecRunnables.add(r);
- }
-
- /** Decrements the ref count */
- public void decrement() {
- mCount--;
- if (mCount == 0) {
- flushLastDecrementRunnables();
- } else if (mCount < 0) {
- if (mErrorRunnable != null) {
- mErrorRunnable.run();
- } else {
- throw new RuntimeException("Invalid ref count");
- }
- }
- }
-
- /**
- * Runs and clears all the last-decrement runnables now.
- */
- public void flushLastDecrementRunnables() {
- if (!mLastDecRunnables.isEmpty()) {
- int numRunnables = mLastDecRunnables.size();
- for (int i = 0; i < numRunnables; i++) {
- mLastDecRunnables.get(i).run();
- }
- }
- mLastDecRunnables.clear();
- }
-
- /**
- * Convenience method to decrement this trigger as a animator listener. This listener is
- * guarded to prevent being called back multiple times, and will trigger a decrement once and
- * only once.
- */
- public Animator.AnimatorListener decrementOnAnimationEnd() {
- return new AnimatorListenerAdapter() {
- private boolean hasEnded;
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (hasEnded) return;
- decrement();
- hasEnded = true;
- }
- };
- }
-
- /** Returns the current ref count */
- public int getCount() {
- return mCount;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java
deleted file mode 100644
index 5d7f1ba..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SysUiTaskStackChangeListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-import android.content.Context;
-
-import com.android.systemui.shared.system.TaskStackChangeListener;
-
-/**
- * An implementation of {@link TaskStackChangeListener}.
- */
-public abstract class SysUiTaskStackChangeListener extends TaskStackChangeListener {
-
- /**
- * Checks that the current user matches the user's SystemUI process.
- */
- protected final boolean checkCurrentUserId(Context context, boolean debug) {
- int currentUserId = SystemServicesProxy.getInstance(context).getCurrentUser();
- return checkCurrentUserId(currentUserId, debug);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
deleted file mode 100644
index 350fe78..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.misc;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.StackInfo;
-import android.app.ActivityOptions;
-import android.app.ActivityTaskManager;
-import android.app.AppGlobals;
-import android.app.IActivityManager;
-import android.app.IActivityTaskManager;
-import android.app.WindowConfiguration;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
-import android.util.Log;
-import android.util.MutableBoolean;
-import android.view.Display;
-import android.view.IDockedStackListener;
-import android.view.IWindowManager;
-import android.view.WindowManager;
-import android.view.WindowManager.KeyboardShortcutsReceiver;
-import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.internal.app.AssistUtils;
-import com.android.internal.os.BackgroundThread;
-import com.android.systemui.Dependency;
-import com.android.systemui.UiOffloadThread;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsImpl;
-import com.android.systemui.statusbar.policy.UserInfoController;
-
-import java.util.List;
-
-/**
- * Acts as a shim around the real system services that we need to access data from, and provides
- * a point of injection when testing UI.
- */
-public class SystemServicesProxy {
- final static String TAG = "SystemServicesProxy";
-
- final static BitmapFactory.Options sBitmapOptions;
- static {
- sBitmapOptions = new BitmapFactory.Options();
- sBitmapOptions.inMutable = true;
- sBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565;
- }
-
- private static SystemServicesProxy sSystemServicesProxy;
-
- AccessibilityManager mAccm;
- ActivityManager mAm;
- IActivityManager mIam;
- IActivityTaskManager mIatm;
- PackageManager mPm;
- IPackageManager mIpm;
- private final IDreamManager mDreamManager;
- private final Context mContext;
- AssistUtils mAssistUtils;
- WindowManager mWm;
- IWindowManager mIwm;
- UserManager mUm;
- Display mDisplay;
- String mRecentsPackage;
- private int mCurrentUserId;
-
- boolean mIsSafeMode;
-
- int mDummyThumbnailWidth;
- int mDummyThumbnailHeight;
- Paint mBgProtectionPaint;
- Canvas mBgProtectionCanvas;
-
- private final Runnable mGcRunnable = new Runnable() {
- @Override
- public void run() {
- System.gc();
- System.runFinalization();
- }
- };
-
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
-
- private final UserInfoController.OnUserInfoChangedListener mOnUserInfoChangedListener =
- (String name, Drawable picture, String userAccount) ->
- mCurrentUserId = mAm.getCurrentUser();
-
- /** Private constructor */
- private SystemServicesProxy(Context context) {
- mContext = context.getApplicationContext();
- mAccm = AccessibilityManager.getInstance(context);
- mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
- mIam = ActivityManager.getService();
- mIatm = ActivityTaskManager.getService();
- mPm = context.getPackageManager();
- mIpm = AppGlobals.getPackageManager();
- mAssistUtils = new AssistUtils(context);
- mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- mIwm = WindowManagerGlobal.getWindowManagerService();
- mUm = UserManager.get(context);
- mDreamManager = IDreamManager.Stub.asInterface(
- ServiceManager.checkService(DreamService.DREAM_SERVICE));
- mDisplay = mWm.getDefaultDisplay();
- mRecentsPackage = context.getPackageName();
- mIsSafeMode = mPm.isSafeMode();
- mCurrentUserId = mAm.getCurrentUser();
-
- // Get the dummy thumbnail width/heights
- Resources res = context.getResources();
- int wId = com.android.internal.R.dimen.thumbnail_width;
- int hId = com.android.internal.R.dimen.thumbnail_height;
- mDummyThumbnailWidth = res.getDimensionPixelSize(wId);
- mDummyThumbnailHeight = res.getDimensionPixelSize(hId);
-
- // Create the protection paints
- mBgProtectionPaint = new Paint();
- mBgProtectionPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
- mBgProtectionPaint.setColor(0xFFffffff);
- mBgProtectionCanvas = new Canvas();
-
- // Since SystemServicesProxy can be accessed from a per-SysUI process component, create a
- // per-process listener to keep track of the current user id to reduce the number of binder
- // calls to fetch it.
- UserInfoController userInfoController = Dependency.get(UserInfoController.class);
- userInfoController.addCallback(mOnUserInfoChangedListener);
- }
-
- /**
- * Returns the single instance of the {@link SystemServicesProxy}.
- * This should only be called on the main thread.
- */
- public static synchronized SystemServicesProxy getInstance(Context context) {
- if (sSystemServicesProxy == null) {
- sSystemServicesProxy = new SystemServicesProxy(context);
- }
- return sSystemServicesProxy;
- }
-
- /**
- * Requests a gc() from the background thread.
- */
- public void gc() {
- BackgroundThread.getHandler().post(mGcRunnable);
- }
-
- /**
- * Returns whether the recents activity is currently visible.
- */
- public boolean isRecentsActivityVisible() {
- return isRecentsActivityVisible(null);
- }
-
- /**
- * Returns whether the recents activity is currently visible.
- *
- * @param isHomeStackVisible if provided, will return whether the home stack is visible
- * regardless of the recents visibility
- *
- * TODO(winsonc): Refactor this check to just use the recents activity lifecycle
- */
- public boolean isRecentsActivityVisible(MutableBoolean isHomeStackVisible) {
- if (mIam == null) return false;
-
- try {
- List<StackInfo> stackInfos = mIatm.getAllStackInfos();
- ActivityManager.StackInfo homeStackInfo = null;
- ActivityManager.StackInfo fullscreenStackInfo = null;
- ActivityManager.StackInfo recentsStackInfo = null;
- for (int i = 0; i < stackInfos.size(); i++) {
- final StackInfo stackInfo = stackInfos.get(i);
- final WindowConfiguration winConfig = stackInfo.configuration.windowConfiguration;
- final int activityType = winConfig.getActivityType();
- final int windowingMode = winConfig.getWindowingMode();
- if (homeStackInfo == null && activityType == ACTIVITY_TYPE_HOME) {
- homeStackInfo = stackInfo;
- } else if (fullscreenStackInfo == null && activityType == ACTIVITY_TYPE_STANDARD
- && (windowingMode == WINDOWING_MODE_FULLSCREEN
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)) {
- fullscreenStackInfo = stackInfo;
- } else if (recentsStackInfo == null && activityType == ACTIVITY_TYPE_RECENTS) {
- recentsStackInfo = stackInfo;
- }
- }
- boolean homeStackVisibleNotOccluded = isStackNotOccluded(homeStackInfo,
- fullscreenStackInfo);
- boolean recentsStackVisibleNotOccluded = isStackNotOccluded(recentsStackInfo,
- fullscreenStackInfo);
- if (isHomeStackVisible != null) {
- isHomeStackVisible.value = homeStackVisibleNotOccluded;
- }
- ComponentName topActivity = recentsStackInfo != null ?
- recentsStackInfo.topActivity : null;
- return (recentsStackVisibleNotOccluded && topActivity != null
- && topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE)
- && Recents.RECENTS_ACTIVITIES.contains(topActivity.getClassName()));
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- return false;
- }
-
- private boolean isStackNotOccluded(ActivityManager.StackInfo stackInfo,
- ActivityManager.StackInfo fullscreenStackInfo) {
- boolean stackVisibleNotOccluded = stackInfo == null || stackInfo.visible;
- if (fullscreenStackInfo != null && stackInfo != null) {
- boolean isFullscreenStackOccludingg = fullscreenStackInfo.visible &&
- fullscreenStackInfo.position > stackInfo.position;
- stackVisibleNotOccluded &= !isFullscreenStackOccludingg;
- }
- return stackVisibleNotOccluded;
- }
-
- /**
- * Returns whether this device is in the safe mode.
- */
- public boolean isInSafeMode() {
- return mIsSafeMode;
- }
-
- /** Moves an already resumed task to the side of the screen to initiate split screen. */
- public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
- Rect initialBounds) {
- if (mIatm == null) {
- return false;
- }
-
- try {
- return mIatm.setTaskWindowingModeSplitScreenPrimary(taskId, createMode,
- true /* onTop */, false /* animate */, initialBounds, true /* showRecents */);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- return false;
- }
-
- public ActivityManager.StackInfo getSplitScreenPrimaryStack() {
- try {
- return mIatm.getStackInfo(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
- } catch (RemoteException e) {
- return null;
- }
- }
-
- /**
- * @return whether there are any docked tasks for the current user.
- */
- public boolean hasDockedTask() {
- if (mIam == null) return false;
-
- ActivityManager.StackInfo stackInfo = getSplitScreenPrimaryStack();
- if (stackInfo != null) {
- int userId = getCurrentUser();
- boolean hasUserTask = false;
- for (int i = stackInfo.taskUserIds.length - 1; i >= 0 && !hasUserTask; i--) {
- hasUserTask = (stackInfo.taskUserIds[i] == userId);
- }
- return hasUserTask;
- }
- return false;
- }
-
- /**
- * Returns whether there is a soft nav bar.
- */
- public boolean hasSoftNavigationBar() {
- try {
- return mIwm.hasNavigationBar();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- return false;
- }
-
- /**
- * Returns whether the device has a transposed nav bar (on the right of the screen) in the
- * current display orientation.
- */
- public boolean hasTransposedNavigationBar() {
- Rect insets = new Rect();
- getStableInsets(insets);
- return insets.right > 0;
- }
-
- /** Set the task's windowing mode. */
- public void setTaskWindowingMode(int taskId, int windowingMode) {
- if (mIatm == null) return;
-
- try {
- mIatm.setTaskWindowingMode(taskId, windowingMode, false /* onTop */);
- } catch (RemoteException | IllegalArgumentException e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Returns whether the provided {@param userId} represents the system user.
- */
- public boolean isSystemUser(int userId) {
- return userId == UserHandle.USER_SYSTEM;
- }
-
- /**
- * Returns the current user id. Used instead of KeyguardUpdateMonitor in SystemUI components
- * that run in the non-primary SystemUI process.
- */
- public int getCurrentUser() {
- return mCurrentUserId;
- }
-
- /**
- * Returns the processes user id.
- */
- public int getProcessUser() {
- if (mUm == null) return 0;
- return mUm.getUserHandle();
- }
-
- /**
- * Returns whether touch exploration is currently enabled.
- */
- public boolean isTouchExplorationEnabled() {
- if (mAccm == null) return false;
-
- return mAccm.isEnabled() && mAccm.isTouchExplorationEnabled();
- }
-
- /**
- * Returns whether the current task is in screen-pinning mode.
- */
- public boolean isScreenPinningActive() {
- if (mIam == null) return false;
-
- try {
- return mIatm.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_PINNED;
- } catch (RemoteException e) {
- return false;
- }
- }
-
- /**
- * Returns the smallest width/height.
- */
- public int getDeviceSmallestWidth() {
- if (mDisplay == null) return 0;
-
- Point smallestSizeRange = new Point();
- Point largestSizeRange = new Point();
- mDisplay.getCurrentSizeRange(smallestSizeRange, largestSizeRange);
- return smallestSizeRange.x;
- }
-
- /**
- * Returns the current display rect in the current display orientation.
- */
- public Rect getDisplayRect() {
- Rect displayRect = new Rect();
- if (mDisplay == null) return displayRect;
-
- Point p = new Point();
- mDisplay.getRealSize(p);
- displayRect.set(0, 0, p.x, p.y);
- return displayRect;
- }
-
- /**
- * Returns the window rect for the RecentsActivity, based on the dimensions of the recents stack
- */
- public Rect getWindowRect() {
- Rect windowRect = new Rect();
- if (mIam == null) return windowRect;
-
- try {
- // Use the recents stack bounds, fallback to fullscreen stack if it is null
- ActivityManager.StackInfo stackInfo =
- mIatm.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS);
- if (stackInfo == null) {
- stackInfo = mIatm.getStackInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- }
- if (stackInfo != null) {
- windowRect.set(stackInfo.bounds);
- }
- } catch (RemoteException e) {
- e.printStackTrace();
- } finally {
- return windowRect;
- }
- }
-
- public void startActivityAsUserAsync(Intent intent, ActivityOptions opts) {
- mUiOffloadThread.submit(() -> mContext.startActivityAsUser(intent,
- opts != null ? opts.toBundle() : null, UserHandle.CURRENT));
- }
-
- /** Starts an in-place animation on the front most application windows. */
- public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) {
- if (mIam == null) return;
-
- try {
- mIatm.startInPlaceAnimationOnFrontMostApplication(
- opts == null ? null : opts.toBundle());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void registerDockedStackListener(IDockedStackListener listener) {
- if (mWm == null) return;
-
- try {
- mIwm.registerDockedStackListener(listener);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Calculates the size of the dock divider in the current orientation.
- */
- public int getDockedDividerSize(Context context) {
- Resources res = context.getResources();
- int dividerWindowWidth = res.getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_thickness);
- int dividerInsets = res.getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_divider_insets);
- return dividerWindowWidth - 2 * dividerInsets;
- }
-
- public void requestKeyboardShortcuts(
- Context context, KeyboardShortcutsReceiver receiver, int deviceId) {
- mWm.requestAppKeyboardShortcuts(receiver, deviceId);
- }
-
- public void getStableInsets(Rect outStableInsets) {
- if (mWm == null) return;
-
- try {
- mIwm.getStableInsets(Display.DEFAULT_DISPLAY, outStableInsets);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- /**
- * Updates the visibility of recents.
- */
- public void setRecentsVisibility(final boolean visible) {
- mUiOffloadThread.submit(() -> {
- try {
- mIwm.setRecentsVisibility(visible);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to reach window manager", e);
- }
- });
- }
-
- /**
- * Updates the visibility of the picture-in-picture.
- */
- public void setPipVisibility(final boolean visible) {
- mUiOffloadThread.submit(() -> {
- try {
- mIwm.setPipVisibility(visible);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to reach window manager", e);
- }
- });
- }
-
- public boolean isDreaming() {
- try {
- return mDreamManager.isDreaming();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to query dream manager.", e);
- }
- return false;
- }
-
- public void awakenDreamsAsync() {
- mUiOffloadThread.submit(() -> {
- try {
- mDreamManager.awaken();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- });
- }
-
- public interface StartActivityFromRecentsResultListener {
- void onStartActivityResult(boolean succeeded);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DockState.java b/packages/SystemUI/src/com/android/systemui/recents/views/DockState.java
deleted file mode 100644
index a246141..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/DockState.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.annotation.IntDef;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.drawable.ColorDrawable;
-import android.util.IntProperty;
-import android.view.animation.Interpolator;
-
-import com.android.internal.policy.DockedDividerUtils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.shared.recents.utilities.Utilities;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-
-/**
- * The various possible dock states when dragging and dropping a task.
- */
-public class DockState implements DropTarget {
-
- public static final int DOCK_AREA_BG_COLOR = 0xFFffffff;
- public static final int DOCK_AREA_GRID_BG_COLOR = 0xFF000000;
-
- // The rotation to apply to the hint text
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({HORIZONTAL, VERTICAL})
- public @interface TextOrientation {}
- private static final int HORIZONTAL = 0;
- private static final int VERTICAL = 1;
-
- private static final int DOCK_AREA_ALPHA = 80;
- public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, 255, HORIZONTAL,
- null, null, null);
- public static final DockState LEFT = new DockState(DOCKED_LEFT,
- SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, VERTICAL,
- new RectF(0, 0, 0.125f, 1), new RectF(0, 0, 0.125f, 1),
- new RectF(0, 0, 0.5f, 1));
- public static final DockState TOP = new DockState(DOCKED_TOP,
- SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, DOCK_AREA_ALPHA, 0, HORIZONTAL,
- new RectF(0, 0, 1, 0.125f), new RectF(0, 0, 1, 0.125f),
- new RectF(0, 0, 1, 0.5f));
- public static final DockState RIGHT = new DockState(DOCKED_RIGHT,
- SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, VERTICAL,
- new RectF(0.875f, 0, 1, 1), new RectF(0.875f, 0, 1, 1),
- new RectF(0.5f, 0, 1, 1));
- public static final DockState BOTTOM = new DockState(DOCKED_BOTTOM,
- SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, DOCK_AREA_ALPHA, 0, HORIZONTAL,
- new RectF(0, 0.875f, 1, 1), new RectF(0, 0.875f, 1, 1),
- new RectF(0, 0.5f, 1, 1));
-
- @Override
- public boolean acceptsDrop(int x, int y, int width, int height, Rect insets,
- boolean isCurrentTarget) {
- if (isCurrentTarget) {
- getMappedRect(expandedTouchDockArea, width, height, mTmpRect);
- return mTmpRect.contains(x, y);
- } else {
- getMappedRect(touchArea, width, height, mTmpRect);
- updateBoundsWithSystemInsets(mTmpRect, insets);
- return mTmpRect.contains(x, y);
- }
- }
-
- // Represents the view state of this dock state
- public static class ViewState {
- private static final IntProperty<ViewState> HINT_ALPHA =
- new IntProperty<ViewState>("drawableAlpha") {
- @Override
- public void setValue(ViewState object, int alpha) {
- object.mHintTextAlpha = alpha;
- object.dockAreaOverlay.invalidateSelf();
- }
-
- @Override
- public Integer get(ViewState object) {
- return object.mHintTextAlpha;
- }
- };
-
- public final int dockAreaAlpha;
- public final ColorDrawable dockAreaOverlay;
- public final int hintTextAlpha;
- public final int hintTextOrientation;
-
- private final int mHintTextResId;
- private String mHintText;
- private Paint mHintTextPaint;
- private Point mHintTextBounds = new Point();
- private int mHintTextAlpha = 255;
- private AnimatorSet mDockAreaOverlayAnimator;
- private Rect mTmpRect = new Rect();
-
- private ViewState(int areaAlpha, int hintAlpha, @TextOrientation int hintOrientation,
- int hintTextResId) {
- dockAreaAlpha = areaAlpha;
- dockAreaOverlay = new ColorDrawable(Recents.getConfiguration().isGridEnabled
- ? DOCK_AREA_GRID_BG_COLOR : DOCK_AREA_BG_COLOR);
- dockAreaOverlay.setAlpha(0);
- hintTextAlpha = hintAlpha;
- hintTextOrientation = hintOrientation;
- mHintTextResId = hintTextResId;
- mHintTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mHintTextPaint.setColor(Color.WHITE);
- }
-
- /**
- * Updates the view state with the given context.
- */
- public void update(Context context) {
- Resources res = context.getResources();
- mHintText = context.getString(mHintTextResId);
- mHintTextPaint.setTextSize(res.getDimensionPixelSize(
- R.dimen.recents_drag_hint_text_size));
- mHintTextPaint.getTextBounds(mHintText, 0, mHintText.length(), mTmpRect);
- mHintTextBounds.set((int) mHintTextPaint.measureText(mHintText), mTmpRect.height());
- }
-
- /**
- * Draws the current view state.
- */
- public void draw(Canvas canvas) {
- // Draw the overlay background
- if (dockAreaOverlay.getAlpha() > 0) {
- dockAreaOverlay.draw(canvas);
- }
-
- // Draw the hint text
- if (mHintTextAlpha > 0) {
- Rect bounds = dockAreaOverlay.getBounds();
- int x = bounds.left + (bounds.width() - mHintTextBounds.x) / 2;
- int y = bounds.top + (bounds.height() + mHintTextBounds.y) / 2;
- mHintTextPaint.setAlpha(mHintTextAlpha);
- if (hintTextOrientation == VERTICAL) {
- canvas.save();
- canvas.rotate(-90f, bounds.centerX(), bounds.centerY());
- }
- canvas.drawText(mHintText, x, y, mHintTextPaint);
- if (hintTextOrientation == VERTICAL) {
- canvas.restore();
- }
- }
- }
-
- /**
- * Creates a new bounds and alpha animation.
- */
- public void startAnimation(Rect bounds, int areaAlpha, int hintAlpha, int duration,
- Interpolator interpolator, boolean animateAlpha, boolean animateBounds) {
- if (mDockAreaOverlayAnimator != null) {
- mDockAreaOverlayAnimator.cancel();
- }
-
- ObjectAnimator anim;
- ArrayList<Animator> animators = new ArrayList<>();
- if (dockAreaOverlay.getAlpha() != areaAlpha) {
- if (animateAlpha) {
- anim = ObjectAnimator.ofInt(dockAreaOverlay,
- Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha);
- anim.setDuration(duration);
- anim.setInterpolator(interpolator);
- animators.add(anim);
- } else {
- dockAreaOverlay.setAlpha(areaAlpha);
- }
- }
- if (mHintTextAlpha != hintAlpha) {
- if (animateAlpha) {
- anim = ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha,
- hintAlpha);
- anim.setDuration(150);
- anim.setInterpolator(hintAlpha > mHintTextAlpha
- ? Interpolators.ALPHA_IN
- : Interpolators.ALPHA_OUT);
- animators.add(anim);
- } else {
- mHintTextAlpha = hintAlpha;
- dockAreaOverlay.invalidateSelf();
- }
- }
- if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) {
- if (animateBounds) {
- PropertyValuesHolder prop = PropertyValuesHolder.ofObject(
- Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR,
- new Rect(dockAreaOverlay.getBounds()), bounds);
- anim = ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop);
- anim.setDuration(duration);
- anim.setInterpolator(interpolator);
- animators.add(anim);
- } else {
- dockAreaOverlay.setBounds(bounds);
- }
- }
- if (!animators.isEmpty()) {
- mDockAreaOverlayAnimator = new AnimatorSet();
- mDockAreaOverlayAnimator.playTogether(animators);
- mDockAreaOverlayAnimator.start();
- }
- }
- }
-
- public final int dockSide;
- public final int createMode;
- public final ViewState viewState;
- private final RectF touchArea;
- private final RectF dockArea;
- private final RectF expandedTouchDockArea;
- private static final Rect mTmpRect = new Rect();
-
- /**
- * @param createMode used to pass to ActivityManager to dock the task
- * @param touchArea the area in which touch will initiate this dock state
- * @param dockArea the visible dock area
- * @param expandedTouchDockArea the area in which touch will continue to dock after entering
- * the initial touch area. This is also the new dock area to
- * draw.
- */
- DockState(int dockSide, int createMode, int dockAreaAlpha, int hintTextAlpha,
- @TextOrientation int hintTextOrientation, RectF touchArea, RectF dockArea,
- RectF expandedTouchDockArea) {
- this.dockSide = dockSide;
- this.createMode = createMode;
- this.viewState = new ViewState(dockAreaAlpha, hintTextAlpha, hintTextOrientation,
- R.string.recents_drag_hint_message);
- this.dockArea = dockArea;
- this.touchArea = touchArea;
- this.expandedTouchDockArea = expandedTouchDockArea;
- }
-
- /**
- * Updates the dock state with the given context.
- */
- public void update(Context context) {
- viewState.update(context);
- }
-
- /**
- * Returns the docked task bounds with the given {@param width} and {@param height}.
- */
- public Rect getPreDockedBounds(int width, int height, Rect insets) {
- getMappedRect(dockArea, width, height, mTmpRect);
- return updateBoundsWithSystemInsets(mTmpRect, insets);
- }
-
- /**
- * Returns the expanded docked task bounds with the given {@param width} and
- * {@param height}.
- */
- public Rect getDockedBounds(int width, int height, int dividerSize, Rect insets,
- Resources res) {
- // Calculate the docked task bounds
- boolean isHorizontalDivision =
- res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
- int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
- insets, width, height, dividerSize);
- Rect newWindowBounds = new Rect();
- DockedDividerUtils.calculateBoundsForPosition(position, dockSide, newWindowBounds,
- width, height, dividerSize);
- return newWindowBounds;
- }
-
- /**
- * Returns the task stack bounds with the given {@param width} and
- * {@param height}.
- */
- public Rect getDockedTaskStackBounds(Rect displayRect, int width, int height,
- int dividerSize, Rect insets, TaskStackLayoutAlgorithm layoutAlgorithm,
- Resources res, Rect windowRectOut) {
- // Calculate the inverse docked task bounds
- boolean isHorizontalDivision =
- res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
- int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
- insets, width, height, dividerSize);
- DockedDividerUtils.calculateBoundsForPosition(position,
- DockedDividerUtils.invertDockSide(dockSide), windowRectOut, width, height,
- dividerSize);
-
- // Calculate the task stack bounds from the new window bounds
- Rect taskStackBounds = new Rect();
- // If the task stack bounds is specifically under the dock area, then ignore the top
- // inset
- int top = dockArea.bottom < 1f
- ? 0
- : insets.top;
- // For now, ignore the left insets since we always dock on the left and show Recents
- // on the right
- layoutAlgorithm.getTaskStackBounds(displayRect, windowRectOut, top, 0, insets.right,
- taskStackBounds);
- return taskStackBounds;
- }
-
- /**
- * Returns the expanded bounds in certain dock sides such that the bounds account for the
- * system insets (namely the vertical nav bar). This call modifies and returns the given
- * {@param bounds}.
- */
- private Rect updateBoundsWithSystemInsets(Rect bounds, Rect insets) {
- if (dockSide == DOCKED_LEFT) {
- bounds.right += insets.left;
- } else if (dockSide == DOCKED_RIGHT) {
- bounds.left -= insets.right;
- }
- return bounds;
- }
-
- /**
- * Returns the mapped rect to the given dimensions.
- */
- private void getMappedRect(RectF bounds, int width, int height, Rect out) {
- out.set((int) (bounds.left * width), (int) (bounds.top * height),
- (int) (bounds.right * width), (int) (bounds.bottom * height));
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java b/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java
deleted file mode 100644
index f2a6310..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/DropTarget.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.graphics.Rect;
-
-/**
- * Represents a drop target for a drag gesture.
- */
-public interface DropTarget {
-
- /**
- * Returns whether this target can accept this drop. The x,y are relative to the top level
- * RecentsView, and the width/height are of the RecentsView.
- */
- boolean acceptsDrop(int x, int y, int width, int height, Rect insets, boolean isCurrentTarget);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java b/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
deleted file mode 100644
index 79a774f..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FakeShadowDrawable.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.systemui.recents.views;
-
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.PixelFormat;
-import android.graphics.RadialGradient;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Shader;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsConfiguration;
-
-/**
- * A rounded rectangle drawable which also includes a shadow around. This is mostly copied from
- * frameworks/support/v7/cardview/eclair-mr1/android/support/v7/widget/
- * RoundRectDrawableWithShadow.java revision c42ba8c000d1e6ce85e152dfc17089a0a69e739f with a few
- * modifications to suit our needs in SystemUI.
- */
-class FakeShadowDrawable extends Drawable {
- // used to calculate content padding
- final static double COS_45 = Math.cos(Math.toRadians(45));
-
- final static float SHADOW_MULTIPLIER = 1.5f;
-
- final float mInsetShadow; // extra shadow to avoid gaps between card and shadow
-
- Paint mCornerShadowPaint;
-
- Paint mEdgeShadowPaint;
-
- final RectF mCardBounds;
-
- float mCornerRadius;
-
- Path mCornerShadowPath;
-
- // updated value with inset
- float mMaxShadowSize;
-
- // actual value set by developer
- float mRawMaxShadowSize;
-
- // multiplied value to account for shadow offset
- float mShadowSize;
-
- // actual value set by developer
- float mRawShadowSize;
-
- private boolean mDirty = true;
-
- private final int mShadowStartColor;
-
- private final int mShadowEndColor;
-
- private boolean mAddPaddingForCorners = true;
-
- /**
- * If shadow size is set to a value above max shadow, we print a warning
- */
- private boolean mPrintedShadowClipWarning = false;
-
- public FakeShadowDrawable(Resources resources, RecentsConfiguration config) {
- mShadowStartColor = resources.getColor(R.color.fake_shadow_start_color);
- mShadowEndColor = resources.getColor(R.color.fake_shadow_end_color);
- mInsetShadow = resources.getDimension(R.dimen.fake_shadow_inset);
- setShadowSize(resources.getDimensionPixelSize(R.dimen.fake_shadow_size),
- resources.getDimensionPixelSize(R.dimen.fake_shadow_size));
- mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
- mCornerShadowPaint.setStyle(Paint.Style.FILL);
- mCornerShadowPaint.setDither(true);
- mCornerRadius = Recents.getConfiguration().isGridEnabled ?
- resources.getDimensionPixelSize(
- R.dimen.recents_grid_task_view_rounded_corners_radius) :
- resources.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
- mCardBounds = new RectF();
- mEdgeShadowPaint = new Paint(mCornerShadowPaint);
- }
-
- @Override
- public void setAlpha(int alpha) {
- mCornerShadowPaint.setAlpha(alpha);
- mEdgeShadowPaint.setAlpha(alpha);
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- super.onBoundsChange(bounds);
- mDirty = true;
- }
-
- void setShadowSize(float shadowSize, float maxShadowSize) {
- if (shadowSize < 0 || maxShadowSize < 0) {
- throw new IllegalArgumentException("invalid shadow size");
- }
- if (shadowSize > maxShadowSize) {
- shadowSize = maxShadowSize;
- if (!mPrintedShadowClipWarning) {
- Log.w("CardView", "Shadow size is being clipped by the max shadow size. See "
- + "{CardView#setMaxCardElevation}.");
- mPrintedShadowClipWarning = true;
- }
- }
- if (mRawShadowSize == shadowSize && mRawMaxShadowSize == maxShadowSize) {
- return;
- }
- mRawShadowSize = shadowSize;
- mRawMaxShadowSize = maxShadowSize;
- mShadowSize = shadowSize * SHADOW_MULTIPLIER + mInsetShadow;
- mMaxShadowSize = maxShadowSize + mInsetShadow;
- mDirty = true;
- invalidateSelf();
- }
-
- @Override
- public boolean getPadding(Rect padding) {
- int vOffset = (int) Math.ceil(calculateVerticalPadding(mRawMaxShadowSize, mCornerRadius,
- mAddPaddingForCorners));
- int hOffset = (int) Math.ceil(calculateHorizontalPadding(mRawMaxShadowSize, mCornerRadius,
- mAddPaddingForCorners));
- padding.set(hOffset, vOffset, hOffset, vOffset);
- return true;
- }
-
- static float calculateVerticalPadding(float maxShadowSize, float cornerRadius,
- boolean addPaddingForCorners) {
- if (addPaddingForCorners) {
- return (float) (maxShadowSize * SHADOW_MULTIPLIER + (1 - COS_45) * cornerRadius);
- } else {
- return maxShadowSize * SHADOW_MULTIPLIER;
- }
- }
-
- static float calculateHorizontalPadding(float maxShadowSize, float cornerRadius,
- boolean addPaddingForCorners) {
- if (addPaddingForCorners) {
- return (float) (maxShadowSize + (1 - COS_45) * cornerRadius);
- } else {
- return maxShadowSize;
- }
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
- mCornerShadowPaint.setColorFilter(colorFilter);
- mEdgeShadowPaint.setColorFilter(colorFilter);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.OPAQUE;
- }
-
- @Override
- public void draw(Canvas canvas) {
- if (mDirty) {
- buildComponents(getBounds());
- mDirty = false;
- }
- canvas.translate(0, mRawShadowSize / 4);
- drawShadow(canvas);
- canvas.translate(0, -mRawShadowSize / 4);
- }
-
- private void drawShadow(Canvas canvas) {
- final float edgeShadowTop = -mCornerRadius - mShadowSize;
- final float inset = mCornerRadius + mInsetShadow + mRawShadowSize / 2;
- final boolean drawHorizontalEdges = mCardBounds.width() - 2 * inset > 0;
- final boolean drawVerticalEdges = mCardBounds.height() - 2 * inset > 0;
- // LT
- int saved = canvas.save();
- canvas.translate(mCardBounds.left + inset, mCardBounds.top + inset);
- canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
- if (drawHorizontalEdges) {
- canvas.drawRect(0, edgeShadowTop,
- mCardBounds.width() - 2 * inset, -mCornerRadius,
- mEdgeShadowPaint);
- }
- canvas.restoreToCount(saved);
- // RB
- saved = canvas.save();
- canvas.translate(mCardBounds.right - inset, mCardBounds.bottom - inset);
- canvas.rotate(180f);
- canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
- if (drawHorizontalEdges) {
- canvas.drawRect(0, edgeShadowTop,
- mCardBounds.width() - 2 * inset, -mCornerRadius + mShadowSize,
- mEdgeShadowPaint);
- }
- canvas.restoreToCount(saved);
- // LB
- saved = canvas.save();
- canvas.translate(mCardBounds.left + inset, mCardBounds.bottom - inset);
- canvas.rotate(270f);
- canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
- if (drawVerticalEdges) {
- canvas.drawRect(0, edgeShadowTop,
- mCardBounds.height() - 2 * inset, -mCornerRadius, mEdgeShadowPaint);
- }
- canvas.restoreToCount(saved);
- // RT
- saved = canvas.save();
- canvas.translate(mCardBounds.right - inset, mCardBounds.top + inset);
- canvas.rotate(90f);
- canvas.drawPath(mCornerShadowPath, mCornerShadowPaint);
- if (drawVerticalEdges) {
- canvas.drawRect(0, edgeShadowTop,
- mCardBounds.height() - 2 * inset, -mCornerRadius, mEdgeShadowPaint);
- }
- canvas.restoreToCount(saved);
- }
-
- private void buildShadowCorners() {
- RectF innerBounds = new RectF(-mCornerRadius, -mCornerRadius, mCornerRadius, mCornerRadius);
- RectF outerBounds = new RectF(innerBounds);
- outerBounds.inset(-mShadowSize, -mShadowSize);
-
- if (mCornerShadowPath == null) {
- mCornerShadowPath = new Path();
- } else {
- mCornerShadowPath.reset();
- }
- mCornerShadowPath.setFillType(Path.FillType.EVEN_ODD);
- mCornerShadowPath.moveTo(-mCornerRadius, 0);
- mCornerShadowPath.rLineTo(-mShadowSize, 0);
- // outer arc
- mCornerShadowPath.arcTo(outerBounds, 180f, 90f, false);
- // inner arc
- mCornerShadowPath.arcTo(innerBounds, 270f, -90f, false);
- mCornerShadowPath.close();
-
- float startRatio = mCornerRadius / (mCornerRadius + mShadowSize);
- mCornerShadowPaint.setShader(new RadialGradient(0, 0, mCornerRadius + mShadowSize,
- new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
- new float[]{0f, startRatio, 1f}
- , Shader.TileMode.CLAMP));
-
- // we offset the content shadowSize/2 pixels up to make it more realistic.
- // this is why edge shadow shader has some extra space
- // When drawing bottom edge shadow, we use that extra space.
- mEdgeShadowPaint.setShader(new LinearGradient(0, -mCornerRadius + mShadowSize, 0,
- -mCornerRadius - mShadowSize,
- new int[]{mShadowStartColor, mShadowStartColor, mShadowEndColor},
- new float[]{0f, .5f, 1f}, Shader.TileMode.CLAMP));
- }
-
- private void buildComponents(Rect bounds) {
- // Card is offset SHADOW_MULTIPLIER * maxShadowSize to account for the shadow shift.
- // We could have different top-bottom offsets to avoid extra gap above but in that case
- // center aligning Views inside the CardView would be problematic.
- final float verticalOffset = mMaxShadowSize * SHADOW_MULTIPLIER;
- mCardBounds.set(bounds.left + mMaxShadowSize, bounds.top + verticalOffset,
- bounds.right - mMaxShadowSize, bounds.bottom - verticalOffset);
- buildShadowCorners();
- }
-
- float getMinWidth() {
- final float content = 2 *
- Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow + mRawMaxShadowSize / 2);
- return content + (mRawMaxShadowSize + mInsetShadow) * 2;
- }
-
- float getMinHeight() {
- final float content = 2 * Math.max(mRawMaxShadowSize, mCornerRadius + mInsetShadow
- + mRawMaxShadowSize * SHADOW_MULTIPLIER / 2);
- return content + (mRawMaxShadowSize * SHADOW_MULTIPLIER + mInsetShadow) * 2;
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
deleted file mode 100644
index 471df6a..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-/**
- * This is an optimized FrameLayout whose layout is completely directed by its parent, and as a
- * result, does not propagate <code>requestLayout()</code> up the view hierarchy. Instead, it will
- * relayout its children with the last known layout bounds when a layout is requested from a child
- * view.
- */
-public class FixedSizeFrameLayout extends FrameLayout {
-
- private final Rect mLayoutBounds = new Rect();
-
- public FixedSizeFrameLayout(Context context) {
- super(context);
- }
-
- public FixedSizeFrameLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public FixedSizeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public FixedSizeFrameLayout(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @Override
- protected final void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- measureContents(MeasureSpec.getSize(widthMeasureSpec),
- MeasureSpec.getSize(heightMeasureSpec));
- }
-
- @Override
- protected final void onLayout(boolean changed, int left, int top, int right, int bottom) {
- mLayoutBounds.set(left, top, right, bottom);
- layoutContents(mLayoutBounds, changed);
- }
-
- @Override
- public final void requestLayout() {
- // The base ViewGroup constructor attempts to call requestLayout() before this class's
- // members are initialized so we should just propagate in that case
- if (mLayoutBounds == null || mLayoutBounds.isEmpty()) {
- super.requestLayout();
- } else {
- // If we are already laid out, then just reuse the same bounds to layout the children
- // (but not itself)
- // TODO: Investigate whether we should coalesce these to the next frame if needed
- measureContents(getMeasuredWidth(), getMeasuredHeight());
- layoutContents(mLayoutBounds, false);
- }
- }
-
- /**
- * Measures the contents of this fixed layout.
- */
- protected void measureContents(int width, int height) {
- super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
- }
-
- /**
- * Lays out the contents of this fixed layout.
- */
- protected void layoutContents(Rect bounds, boolean changed) {
- super.onLayout(changed, bounds.left, bounds.top, bounds.right, bounds.bottom);
-
- int width = getMeasuredWidth();
- int height = getMeasuredHeight();
- onSizeChanged(width, height, width, height);
- }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
deleted file mode 100644
index d3b5e47..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-
-import com.android.systemui.statusbar.AlphaOptimizedImageView;
-
-/**
- * This is an optimized ImageView that does not trigger a <code>requestLayout()</code> or
- * <code>invalidate()</code> when setting the image to <code>null</code>.
- */
-public class FixedSizeImageView extends AlphaOptimizedImageView {
-
- private boolean mAllowRelayout = true;
- private boolean mAllowInvalidate = true;
-
- public FixedSizeImageView(Context context) {
- this(context, null);
- }
-
- public FixedSizeImageView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public FixedSizeImageView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public FixedSizeImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- }
-
- @Override
- public void requestLayout() {
- if (mAllowRelayout) {
- super.requestLayout();
- }
- }
-
- @Override
- public void invalidate() {
- if (mAllowInvalidate) {
- super.invalidate();
- }
- }
-
- @Override
- public void setImageDrawable(Drawable drawable) {
- boolean isNullBitmapDrawable = (drawable instanceof BitmapDrawable) &&
- (((BitmapDrawable) drawable).getBitmap() == null);
- if (drawable == null || isNullBitmapDrawable) {
- mAllowRelayout = false;
- mAllowInvalidate = false;
- }
- super.setImageDrawable(drawable);
- mAllowRelayout = true;
- mAllowInvalidate = true;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
deleted file mode 100644
index e32da2d..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.view.animation.PathInterpolator;
-
-/**
- * A helper interpolator to stagger the entrance animation in recents by offsetting the start time
- */
-public class RecentsEntrancePathInterpolator extends PathInterpolator {
- final float mStartOffsetFraction;
-
- /**
- * Create an interpolator for a cubic Bezier curve with an offset play time. The end points
- * <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
- *
- * @param controlX1 The x coordinate of the first control point of the cubic Bezier.
- * @param controlY1 The y coordinate of the first control point of the cubic Bezier.
- * @param controlX2 The x coordinate of the second control point of the cubic Bezier.
- * @param controlY2 The y coordinate of the second control point of the cubic Bezier.
- * @param startOffsetFraction The fraction from 0 to 1 to start the animation from
- */
- public RecentsEntrancePathInterpolator(float controlX1, float controlY1, float controlX2,
- float controlY2, float startOffsetFraction) {
- super(controlX1, controlY1, controlX2, controlY2);
- mStartOffsetFraction = startOffsetFraction;
- }
-
- @Override
- public float getInterpolation(float t) {
- return super.getInterpolation(t + mStartOffsetFraction);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
deleted file mode 100644
index 1c47430..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionComposer.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.GraphicBuffer;
-import android.graphics.Rect;
-import android.util.Log;
-
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsDebugFlags;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
-import com.android.systemui.shared.recents.view.RecentsTransition;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A helper class to create the transition app animation specs to/from Recents
- */
-public class RecentsTransitionComposer {
-
- private static final String TAG = "RecentsTransitionComposer";
-
- private Context mContext;
- private TaskViewTransform mTmpTransform = new TaskViewTransform();
-
- public RecentsTransitionComposer(Context context) {
- mContext = context;
- }
-
- /**
- * Composes a single animation spec for the given {@link TaskView}
- */
- private static AppTransitionAnimationSpecCompat composeAnimationSpec(TaskStackView stackView,
- TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) {
- Bitmap b = null;
- if (addHeaderBitmap) {
- b = composeHeaderBitmap(taskView, transform);
- if (b == null) {
- return null;
- }
- }
-
- Rect taskRect = new Rect();
- transform.rect.round(taskRect);
- // Disable in for low ram devices because each task does in Recents does not have fullscreen
- // height (stackView height) and when transitioning to fullscreen app, the code below would
- // force the task thumbnail to full stackView height immediately causing the transition
- // jarring.
- if (!Recents.getConfiguration().isLowRamDevice && taskView.getTask() !=
- stackView.getStack().getFrontMostTask()) {
- taskRect.bottom = taskRect.top + stackView.getMeasuredHeight();
- }
- return new AppTransitionAnimationSpecCompat(taskView.getTask().key.id, b, taskRect);
- }
-
- /**
- * Composes the transition spec when docking a task, which includes a full task bitmap.
- */
- public List<AppTransitionAnimationSpecCompat> composeDockAnimationSpec(TaskView taskView,
- Rect bounds) {
- mTmpTransform.fillIn(taskView);
- Task task = taskView.getTask();
- Bitmap buffer = RecentsTransitionComposer.composeTaskBitmap(taskView, mTmpTransform);
- return Collections.singletonList(new AppTransitionAnimationSpecCompat(task.key.id, buffer,
- bounds));
- }
-
- /**
- * Composes the animation specs for all the tasks in the target stack.
- */
- public List<AppTransitionAnimationSpecCompat> composeAnimationSpecs(final Task task,
- final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) {
- // Calculate the offscreen task rect (for tasks that are not backed by views)
- TaskView taskView = stackView.getChildViewForTask(task);
- TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
- Rect offscreenTaskRect = new Rect();
- stackLayout.getFrontOfStackTransform().rect.round(offscreenTaskRect);
-
- // If this is a full screen stack, the transition will be towards the single, full screen
- // task. We only need the transition spec for this task.
-
- // TODO: Sometimes targetStackId is not initialized after reboot, so we also have to
- // check for INVALID_STACK_ID (now WINDOWING_MODE_UNDEFINED)
- if (windowingMode == WINDOWING_MODE_FULLSCREEN
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
- || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
- || activityType == ACTIVITY_TYPE_ASSISTANT
- || windowingMode == WINDOWING_MODE_UNDEFINED) {
- List<AppTransitionAnimationSpecCompat> specs = new ArrayList<>();
- if (taskView == null) {
- specs.add(composeOffscreenAnimationSpec(task, offscreenTaskRect));
- } else {
- mTmpTransform.fillIn(taskView);
- stackLayout.transformToScreenCoordinates(mTmpTransform, windowRect);
- AppTransitionAnimationSpecCompat spec = composeAnimationSpec(stackView, taskView,
- mTmpTransform, true /* addHeaderBitmap */);
- if (spec != null) {
- specs.add(spec);
- }
- }
- return specs;
- }
- return Collections.emptyList();
- }
-
- /**
- * Composes a single animation spec for the given {@link Task}
- */
- private static AppTransitionAnimationSpecCompat composeOffscreenAnimationSpec(Task task,
- Rect taskRect) {
- return new AppTransitionAnimationSpecCompat(task.key.id, null, taskRect);
- }
-
- public static Bitmap composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
- float scale = transform.scale;
- int fromWidth = (int) (transform.rect.width() * scale);
- int fromHeight = (int) (transform.rect.height() * scale);
- if (fromWidth == 0 || fromHeight == 0) {
- Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() +
- " at transform: " + transform);
-
- return RecentsTransition.drawViewIntoHardwareBitmap(1, 1, null, 1f, 0x00ffffff);
- } else {
- if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
- return RecentsTransition.drawViewIntoHardwareBitmap(fromWidth, fromHeight, null, 1f,
- 0xFFff0000);
- } else {
- return RecentsTransition.drawViewIntoHardwareBitmap(fromWidth, fromHeight, taskView,
- scale, 0);
- }
- }
- }
-
- private static Bitmap composeHeaderBitmap(TaskView taskView,
- TaskViewTransform transform) {
- float scale = transform.scale;
- int headerWidth = (int) (transform.rect.width());
- int headerHeight = (int) (taskView.mHeaderView.getMeasuredHeight() * scale);
- if (headerWidth == 0 || headerHeight == 0) {
- return null;
- }
-
- if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
- return RecentsTransition.drawViewIntoHardwareBitmap(headerWidth, headerHeight, null, 1f,
- 0xFFff0000);
- } else {
- return RecentsTransition.drawViewIntoHardwareBitmap(headerWidth, headerHeight,
- taskView.mHeaderView, scale, 0);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
deleted file mode 100644
index 5c925fd..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ /dev/null
@@ -1,1078 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
-
-import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_RECENT_APPS;
-
-import android.animation.ValueAnimator;
-import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.Nullable;
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.os.Handler;
-import android.os.IRemoteCallback;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.MathUtils;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewPropertyAnimator;
-import android.view.Window;
-import android.view.WindowInsets;
-import android.widget.FrameLayout;
-import android.widget.TextView;
-
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.internal.colorextraction.drawable.GradientDrawable;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settingslib.Utils;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivity;
-import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
-import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
-import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
-import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
-import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
-import com.android.systemui.recents.events.component.ExpandPipEvent;
-import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
-import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
-import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
-import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
-import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
-import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
-import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
-import com.android.systemui.shared.recents.view.RecentsTransition;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.ActivityOptionsCompat;
-import com.android.systemui.shared.system.WindowManagerWrapper;
-import com.android.systemui.stackdivider.WindowManagerProxy;
-import com.android.systemui.statusbar.FlingAnimationUtils;
-import com.android.systemui.statusbar.phone.ScrimController;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * This view is the the top level layout that contains TaskStacks (which are laid out according
- * to their SpaceNode bounds.
- */
-public class RecentsView extends FrameLayout {
-
- private static final String TAG = "RecentsView";
-
- private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
-
- private static final int SHOW_STACK_ACTION_BUTTON_DURATION = 134;
- private static final int HIDE_STACK_ACTION_BUTTON_DURATION = 100;
-
- private static final int BUSY_RECENTS_TASK_COUNT = 3;
-
- private Handler mHandler;
- private TaskStackView mTaskStackView;
- private TextView mStackActionButton;
- private TextView mEmptyView;
- private final float mStackButtonShadowRadius;
- private final PointF mStackButtonShadowDistance;
- private final int mStackButtonShadowColor;
-
- private boolean mAwaitingFirstLayout = true;
-
- @ViewDebug.ExportedProperty(category="recents")
- Rect mSystemInsets = new Rect();
- private int mDividerSize;
-
- private float mBusynessFactor;
- private GradientDrawable mBackgroundScrim;
- private ColorDrawable mMultiWindowBackgroundScrim;
- private ValueAnimator mBackgroundScrimAnimator;
- private Point mTmpDisplaySize = new Point();
-
- private final AnimatorUpdateListener mUpdateBackgroundScrimAlpha = (animation) -> {
- int alpha = (Integer) animation.getAnimatedValue();
- mBackgroundScrim.setAlpha(alpha);
- mMultiWindowBackgroundScrim.setAlpha(alpha);
- };
-
- private RecentsTransitionComposer mTransitionHelper;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="touch_")
- private RecentsViewTouchHandler mTouchHandler;
- private final FlingAnimationUtils mFlingAnimationUtils;
-
- public RecentsView(Context context) {
- this(context, null);
- }
-
- public RecentsView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- setWillNotDraw(false);
-
- SystemServicesProxy ssp = Recents.getSystemServices();
- mHandler = new Handler();
- mTransitionHelper = new RecentsTransitionComposer(getContext());
- mDividerSize = ssp.getDockedDividerSize(context);
- mTouchHandler = new RecentsViewTouchHandler(this);
- mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
- mBackgroundScrim = new GradientDrawable(context);
- mMultiWindowBackgroundScrim = new ColorDrawable();
-
- LayoutInflater inflater = LayoutInflater.from(context);
- mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
- addView(mEmptyView);
-
- if (mStackActionButton != null) {
- removeView(mStackActionButton);
- }
- mStackActionButton = (TextView) inflater.inflate(Recents.getConfiguration()
- .isLowRamDevice
- ? R.layout.recents_low_ram_stack_action_button
- : R.layout.recents_stack_action_button,
- this, false);
-
- mStackButtonShadowRadius = mStackActionButton.getShadowRadius();
- mStackButtonShadowDistance = new PointF(mStackActionButton.getShadowDx(),
- mStackActionButton.getShadowDy());
- mStackButtonShadowColor = mStackActionButton.getShadowColor();
- addView(mStackActionButton);
-
- reevaluateStyles();
- }
-
- public void reevaluateStyles() {
- int textColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
- boolean usingDarkText = Color.luminance(textColor) < 0.5f;
-
- mEmptyView.setTextColor(textColor);
- mEmptyView.setCompoundDrawableTintList(new ColorStateList(new int[][]{
- {android.R.attr.state_enabled}}, new int[]{textColor}));
-
- if (mStackActionButton != null) {
- mStackActionButton.setTextColor(textColor);
- // Enable/disable shadow if text color is already dark.
- if (usingDarkText) {
- mStackActionButton.setShadowLayer(0, 0, 0, 0);
- } else {
- mStackActionButton.setShadowLayer(mStackButtonShadowRadius,
- mStackButtonShadowDistance.x, mStackButtonShadowDistance.y,
- mStackButtonShadowColor);
- }
- }
-
- // Let's also require dark status and nav bars if the text is dark
- int systemBarsStyle = usingDarkText ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
- View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0;
-
- setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
- systemBarsStyle);
- }
-
- /**
- * Called from RecentsActivity when it is relaunched.
- */
- public void onReload(TaskStack stack, boolean isResumingFromVisible) {
- final RecentsConfiguration config = Recents.getConfiguration();
- final RecentsActivityLaunchState launchState = config.getLaunchState();
- final boolean isTaskStackEmpty = stack.getTaskCount() == 0;
-
- if (mTaskStackView == null) {
- isResumingFromVisible = false;
- mTaskStackView = new TaskStackView(getContext());
- mTaskStackView.setSystemInsets(mSystemInsets);
- addView(mTaskStackView);
- }
-
- // Reset the state
- mAwaitingFirstLayout = !isResumingFromVisible;
-
- // Update the stack
- mTaskStackView.onReload(isResumingFromVisible);
- updateStack(stack, true /* setStackViewTasks */);
- updateBusyness();
-
- if (isResumingFromVisible) {
- // If we are already visible, then restore the background scrim
- animateBackgroundScrim(getOpaqueScrimAlpha(), DEFAULT_UPDATE_SCRIM_DURATION);
- } else {
- // If we are already occluded by the app, then set the final background scrim alpha now.
- // Otherwise, defer until the enter animation completes to animate the scrim alpha with
- // the tasks for the home animation.
- if (launchState.launchedViaDockGesture || launchState.launchedFromApp
- || isTaskStackEmpty) {
- mBackgroundScrim.setAlpha((int) (getOpaqueScrimAlpha() * 255));
- } else {
- mBackgroundScrim.setAlpha(0);
- }
- mMultiWindowBackgroundScrim.setAlpha(mBackgroundScrim.getAlpha());
- }
- }
-
- /**
- * Called from RecentsActivity when the task stack is updated.
- */
- public void updateStack(TaskStack stack, boolean setStackViewTasks) {
- if (setStackViewTasks) {
- mTaskStackView.setTasks(stack, true /* allowNotifyStackChanges */);
- }
-
- // Update the top level view's visibilities
- if (stack.getTaskCount() > 0) {
- hideEmptyView();
- } else {
- showEmptyView(R.string.recents_empty_message);
- }
- }
-
- /**
- * Animates the scrim opacity based on how many tasks are visible.
- * Called from {@link RecentsActivity} when tasks are dismissed.
- */
- public void updateScrimOpacity() {
- if (updateBusyness()) {
- animateBackgroundScrim(getOpaqueScrimAlpha(), DEFAULT_UPDATE_SCRIM_DURATION);
- }
- }
-
- /**
- * Updates the busyness factor.
- *
- * @return True if it changed.
- */
- private boolean updateBusyness() {
- final int taskCount = mTaskStackView.getStack().getTaskCount();
- final float busyness = Math.min(taskCount, BUSY_RECENTS_TASK_COUNT)
- / (float) BUSY_RECENTS_TASK_COUNT;
- if (mBusynessFactor == busyness) {
- return false;
- } else {
- mBusynessFactor = busyness;
- return true;
- }
- }
-
- /**
- * Returns the current TaskStack.
- */
- public TaskStack getStack() {
- return mTaskStackView.getStack();
- }
-
- /**
- * Returns the window background scrim.
- */
- public void updateBackgroundScrim(Window window, boolean isInMultiWindow) {
- if (isInMultiWindow) {
- mBackgroundScrim.setCallback(null);
- window.setBackgroundDrawable(mMultiWindowBackgroundScrim);
- } else {
- mMultiWindowBackgroundScrim.setCallback(null);
- window.setBackgroundDrawable(mBackgroundScrim);
- }
- }
-
- /** Launches the focused task from the first stack if possible */
- public boolean launchFocusedTask(int logEvent) {
- if (mTaskStackView != null) {
- Task task = mTaskStackView.getFocusedTask();
- if (task != null) {
- TaskView taskView = mTaskStackView.getChildViewForTask(task);
- EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false));
-
- if (logEvent != 0) {
- MetricsLogger.action(getContext(), logEvent,
- task.key.getComponent().toString());
- }
- return true;
- }
- }
- return false;
- }
-
- /** Launches the task that recents was launched from if possible */
- public boolean launchPreviousTask() {
- if (Recents.getConfiguration().getLaunchState().launchedFromPipApp) {
- // If the app auto-entered PiP on the way to Recents, then just re-expand it
- EventBus.getDefault().send(new ExpandPipEvent());
- return true;
- }
-
- if (mTaskStackView != null) {
- Task task = getStack().getLaunchTarget();
- if (task != null) {
- TaskView taskView = mTaskStackView.getChildViewForTask(task);
- EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null, false));
- return true;
- }
- }
- return false;
- }
-
- /**
- * Hides the task stack and shows the empty view.
- */
- public void showEmptyView(int msgResId) {
- mTaskStackView.setVisibility(View.INVISIBLE);
- mEmptyView.setText(msgResId);
- mEmptyView.setVisibility(View.VISIBLE);
- mEmptyView.bringToFront();
- mStackActionButton.bringToFront();
- }
-
- /**
- * Shows the task stack and hides the empty view.
- */
- public void hideEmptyView() {
- mEmptyView.setVisibility(View.INVISIBLE);
- mTaskStackView.setVisibility(View.VISIBLE);
- mTaskStackView.bringToFront();
- mStackActionButton.bringToFront();
- }
-
- /**
- * Set the color of the scrim.
- *
- * @param scrimColors Colors to use.
- * @param animated Interpolate colors if true.
- */
- public void setScrimColors(ColorExtractor.GradientColors scrimColors, boolean animated) {
- mBackgroundScrim.setColors(scrimColors, animated);
- int alpha = mMultiWindowBackgroundScrim.getAlpha();
- mMultiWindowBackgroundScrim.setColor(scrimColors.getMainColor());
- mMultiWindowBackgroundScrim.setAlpha(alpha);
- }
-
- @Override
- protected void onAttachedToWindow() {
- EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
- EventBus.getDefault().register(mTouchHandler, RecentsActivity.EVENT_BUS_PRIORITY + 2);
- super.onAttachedToWindow();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- EventBus.getDefault().unregister(this);
- EventBus.getDefault().unregister(mTouchHandler);
- }
-
- /**
- * This is called with the full size of the window since we are handling our own insets.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
-
- if (mTaskStackView.getVisibility() != GONE) {
- mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
- }
-
- // Measure the empty view to the full size of the screen
- if (mEmptyView.getVisibility() != GONE) {
- measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
- }
-
- // Measure the stack action button within the constraints of the space above the stack
- Rect buttonBounds = mTaskStackView.mLayoutAlgorithm.getStackActionButtonRect();
- measureChild(mStackActionButton,
- MeasureSpec.makeMeasureSpec(buttonBounds.width(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(buttonBounds.height(), MeasureSpec.AT_MOST));
-
- setMeasuredDimension(width, height);
- }
-
- /**
- * This is called with the full size of the window since we are handling our own insets.
- */
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- if (mTaskStackView.getVisibility() != GONE) {
- mTaskStackView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
- }
-
- // Layout the empty view
- if (mEmptyView.getVisibility() != GONE) {
- int leftRightInsets = mSystemInsets.left + mSystemInsets.right;
- int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
- int childWidth = mEmptyView.getMeasuredWidth();
- int childHeight = mEmptyView.getMeasuredHeight();
- int childLeft = left + mSystemInsets.left +
- Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
- int childTop = top + mSystemInsets.top +
- Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
- mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
- }
-
- // Needs to know the screen size since the gradient never scales up or down
- // even when bounds change.
- mContext.getDisplay().getRealSize(mTmpDisplaySize);
- mBackgroundScrim.setScreenSize(mTmpDisplaySize.x, mTmpDisplaySize.y);
- mBackgroundScrim.setBounds(left, top, right, bottom);
- mMultiWindowBackgroundScrim.setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
-
- // Layout the stack action button such that its drawable is start-aligned with the
- // stack, vertically centered in the available space above the stack
- Rect buttonBounds = getStackActionButtonBoundsFromStackLayout();
- mStackActionButton.layout(buttonBounds.left, buttonBounds.top, buttonBounds.right,
- buttonBounds.bottom);
-
- if (mAwaitingFirstLayout) {
- mAwaitingFirstLayout = false;
- // If launched via dragging from the nav bar, then we should translate the whole view
- // down offscreen
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (launchState.launchedViaDragGesture) {
- setTranslationY(getMeasuredHeight());
- } else {
- setTranslationY(0f);
- }
-
- if (Recents.getConfiguration().isLowRamDevice
- && mEmptyView.getVisibility() == View.VISIBLE) {
- animateEmptyView(true /* show */, null /* postAnimationTrigger */);
- }
- }
- }
-
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mSystemInsets.set(insets.getSystemWindowInsets());
- mTaskStackView.setSystemInsets(mSystemInsets);
- requestLayout();
- return insets;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return mTouchHandler.onInterceptTouchEvent(ev);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return mTouchHandler.onTouchEvent(ev);
- }
-
- @Override
- public void onDrawForeground(Canvas canvas) {
- super.onDrawForeground(canvas);
-
- ArrayList<DockState> visDockStates = mTouchHandler.getVisibleDockStates();
- for (int i = visDockStates.size() - 1; i >= 0; i--) {
- visDockStates.get(i).viewState.draw(canvas);
- }
- }
-
- @Override
- protected boolean verifyDrawable(Drawable who) {
- ArrayList<DockState> visDockStates = mTouchHandler.getVisibleDockStates();
- for (int i = visDockStates.size() - 1; i >= 0; i--) {
- Drawable d = visDockStates.get(i).viewState.dockAreaOverlay;
- if (d == who) {
- return true;
- }
- }
- return super.verifyDrawable(who);
- }
-
- /**** EventBus Events ****/
-
- public final void onBusEvent(LaunchTaskEvent event) {
- launchTaskFromRecents(getStack(), event.task, mTaskStackView, event.taskView,
- event.screenPinningRequested, event.targetWindowingMode, event.targetActivityType);
- if (Recents.getConfiguration().isLowRamDevice) {
- EventBus.getDefault().send(new HideStackActionButtonEvent(false /* translate */));
- }
- }
-
- public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
- int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
- // Hide the stack action button
- EventBus.getDefault().send(new HideStackActionButtonEvent());
- animateBackgroundScrim(0f, taskViewExitToHomeDuration);
-
- if (Recents.getConfiguration().isLowRamDevice) {
- animateEmptyView(false /* show */, event.getAnimationTrigger());
- }
- }
-
- public final void onBusEvent(DragStartEvent event) {
- updateVisibleDockRegions(Recents.getConfiguration().getDockStatesForCurrentOrientation(),
- true /* isDefaultDockState */, DockState.NONE.viewState.dockAreaAlpha,
- DockState.NONE.viewState.hintTextAlpha,
- true /* animateAlpha */, false /* animateBounds */);
-
- // Temporarily hide the stack action button without changing visibility
- if (mStackActionButton != null) {
- mStackActionButton.animate()
- .alpha(0f)
- .setDuration(HIDE_STACK_ACTION_BUTTON_DURATION)
- .setInterpolator(Interpolators.ALPHA_OUT)
- .start();
- }
- }
-
- public final void onBusEvent(DragDropTargetChangedEvent event) {
- if (event.dropTarget == null || !(event.dropTarget instanceof DockState)) {
- updateVisibleDockRegions(
- Recents.getConfiguration().getDockStatesForCurrentOrientation(),
- true /* isDefaultDockState */, DockState.NONE.viewState.dockAreaAlpha,
- DockState.NONE.viewState.hintTextAlpha,
- true /* animateAlpha */, true /* animateBounds */);
- } else {
- final DockState dockState = (DockState) event.dropTarget;
- updateVisibleDockRegions(new DockState[] {dockState},
- false /* isDefaultDockState */, -1, -1, true /* animateAlpha */,
- true /* animateBounds */);
- }
- if (mStackActionButton != null) {
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- // Move the clear all button to its new position
- Rect buttonBounds = getStackActionButtonBoundsFromStackLayout();
- mStackActionButton.setLeftTopRightBottom(buttonBounds.left, buttonBounds.top,
- buttonBounds.right, buttonBounds.bottom);
- }
- });
- }
- }
-
- public final void onBusEvent(final DragEndEvent event) {
- // Handle the case where we drop onto a dock region
- if (event.dropTarget instanceof DockState) {
- final DockState dockState = (DockState) event.dropTarget;
-
- // Hide the dock region
- updateVisibleDockRegions(null, false /* isDefaultDockState */, -1, -1,
- false /* animateAlpha */, false /* animateBounds */);
-
- // We translated the view but we need to animate it back from the current layout-space
- // rect to its final layout-space rect
- Utilities.setViewFrameFromTranslation(event.taskView);
-
- final ActivityOptions options = ActivityOptionsCompat.makeSplitScreenOptions(
- dockState.createMode == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT);
- if (ActivityManagerWrapper.getInstance().startActivityFromRecents(event.task.key.id,
- options)) {
- final Runnable animStartedListener = () -> {
- EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
- // Remove the task and don't bother relaying out, as all the tasks
- // will be relaid out when the stack changes on the multiwindow
- // change event
- getStack().removeTask(event.task, null, true /* fromDockGesture */);
- };
- final Rect taskRect = getTaskRect(event.taskView);
- AppTransitionAnimationSpecsFuture future = new AppTransitionAnimationSpecsFuture(
- getHandler()) {
- @Override
- public List<AppTransitionAnimationSpecCompat> composeSpecs() {
- return mTransitionHelper.composeDockAnimationSpec(event.taskView, taskRect);
- }
- };
- WindowManagerWrapper.getInstance().overridePendingAppTransitionMultiThumbFuture(
- future, animStartedListener, getHandler(), true /* scaleUp */);
- MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP,
- event.task.getTopComponent().flattenToShortString());
- } else {
- EventBus.getDefault().send(new DragEndCancelledEvent(getStack(), event.task,
- event.taskView));
- }
- } else {
- // Animate the overlay alpha back to 0
- updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, -1,
- true /* animateAlpha */, false /* animateBounds */);
- }
-
- // Show the stack action button again without changing visibility
- if (mStackActionButton != null) {
- mStackActionButton.animate()
- .alpha(1f)
- .setDuration(SHOW_STACK_ACTION_BUTTON_DURATION)
- .setInterpolator(Interpolators.ALPHA_IN)
- .start();
- }
- }
-
- public final void onBusEvent(final DragEndCancelledEvent event) {
- // Animate the overlay alpha back to 0
- updateVisibleDockRegions(null, true /* isDefaultDockState */, -1, -1,
- true /* animateAlpha */, false /* animateBounds */);
- }
-
- private Rect getTaskRect(TaskView taskView) {
- int[] location = taskView.getLocationOnScreen();
- int viewX = location[0];
- int viewY = location[1];
- return new Rect(viewX, viewY,
- (int) (viewX + taskView.getWidth() * taskView.getScaleX()),
- (int) (viewY + taskView.getHeight() * taskView.getScaleY()));
- }
-
- public final void onBusEvent(DraggingInRecentsEvent event) {
- if (mTaskStackView.getTaskViews().size() > 0) {
- setTranslationY(event.distanceFromTop - mTaskStackView.getTaskViews().get(0).getY());
- }
- }
-
- public final void onBusEvent(DraggingInRecentsEndedEvent event) {
- ViewPropertyAnimator animator = animate();
- if (event.velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
- animator.translationY(getHeight());
- animator.withEndAction(new Runnable() {
- @Override
- public void run() {
- WindowManagerProxy.getInstance().maximizeDockedStack();
- }
- });
- mFlingAnimationUtils.apply(animator, getTranslationY(), getHeight(), event.velocity);
- } else {
- animator.translationY(0f);
- animator.setListener(null);
- mFlingAnimationUtils.apply(animator, getTranslationY(), 0, event.velocity);
- }
- animator.start();
- }
-
- public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (!launchState.launchedViaDockGesture && !launchState.launchedFromApp
- && getStack().getTaskCount() > 0) {
- animateBackgroundScrim(getOpaqueScrimAlpha(),
- TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
- }
- }
-
- public final void onBusEvent(AllTaskViewsDismissedEvent event) {
- EventBus.getDefault().send(new HideStackActionButtonEvent());
- }
-
- public final void onBusEvent(DismissAllTaskViewsEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- if (!ssp.hasDockedTask()) {
- // Animate the background away only if we are dismissing Recents to home
- animateBackgroundScrim(0f, DEFAULT_UPDATE_SCRIM_DURATION);
- }
- }
-
- public final void onBusEvent(ShowStackActionButtonEvent event) {
- showStackActionButton(SHOW_STACK_ACTION_BUTTON_DURATION, event.translate);
- }
-
- public final void onBusEvent(HideStackActionButtonEvent event) {
- hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
- }
-
- public final void onBusEvent(MultiWindowStateChangedEvent event) {
- updateStack(event.stack, false /* setStackViewTasks */);
- }
-
- public final void onBusEvent(ShowEmptyViewEvent event) {
- showEmptyView(R.string.recents_empty_message);
- }
-
- /**
- * Shows the stack action button.
- */
- private void showStackActionButton(final int duration, final boolean translate) {
- final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- if (mStackActionButton.getVisibility() == View.INVISIBLE) {
- mStackActionButton.setVisibility(View.VISIBLE);
- mStackActionButton.setAlpha(0f);
- if (translate) {
- mStackActionButton.setTranslationY(mStackActionButton.getMeasuredHeight() *
- (Recents.getConfiguration().isLowRamDevice ? 1 : -0.25f));
- } else {
- mStackActionButton.setTranslationY(0f);
- }
- postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- if (translate) {
- mStackActionButton.animate()
- .translationY(0f);
- }
- mStackActionButton.animate()
- .alpha(1f)
- .setDuration(duration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .start();
- }
- });
- }
- postAnimationTrigger.flushLastDecrementRunnables();
- }
-
- /**
- * Hides the stack action button.
- */
- private void hideStackActionButton(int duration, boolean translate) {
- final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- hideStackActionButton(duration, translate, postAnimationTrigger);
- postAnimationTrigger.flushLastDecrementRunnables();
- }
-
- /**
- * Hides the stack action button.
- */
- private void hideStackActionButton(int duration, boolean translate,
- final ReferenceCountedTrigger postAnimationTrigger) {
- if (mStackActionButton.getVisibility() == View.VISIBLE) {
- if (translate) {
- mStackActionButton.animate().translationY(mStackActionButton.getMeasuredHeight()
- * (Recents.getConfiguration().isLowRamDevice ? 1 : -0.25f));
- }
- mStackActionButton.animate()
- .alpha(0f)
- .setDuration(duration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mStackActionButton.setVisibility(View.INVISIBLE);
- postAnimationTrigger.decrement();
- }
- })
- .start();
- postAnimationTrigger.increment();
- }
- }
-
- /**
- * Animates a translation in the Y direction and fades in/out for empty view to show or hide it.
- * @param show whether to translate up and fade in the empty view to the center of the screen
- * @param postAnimationTrigger to keep track of the animation
- */
- private void animateEmptyView(boolean show, ReferenceCountedTrigger postAnimationTrigger) {
- float start = mTaskStackView.getStackAlgorithm().getTaskRect().height() / 4;
- mEmptyView.setTranslationY(show ? start : 0);
- mEmptyView.setAlpha(show ? 0f : 1f);
- ViewPropertyAnimator animator = mEmptyView.animate()
- .setDuration(150)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .translationY(show ? 0 : start)
- .alpha(show ? 1f : 0f);
-
- if (postAnimationTrigger != null) {
- animator.setListener(postAnimationTrigger.decrementOnAnimationEnd());
- postAnimationTrigger.increment();
- }
- animator.start();
- }
-
- /**
- * Updates the dock region to match the specified dock state.
- */
- private void updateVisibleDockRegions(DockState[] newDockStates,
- boolean isDefaultDockState, int overrideAreaAlpha, int overrideHintAlpha,
- boolean animateAlpha, boolean animateBounds) {
- ArraySet<DockState> newDockStatesSet = Utilities.arrayToSet(newDockStates,
- new ArraySet<DockState>());
- ArrayList<DockState> visDockStates = mTouchHandler.getVisibleDockStates();
- for (int i = visDockStates.size() - 1; i >= 0; i--) {
- DockState dockState = visDockStates.get(i);
- DockState.ViewState viewState = dockState.viewState;
- if (newDockStates == null || !newDockStatesSet.contains(dockState)) {
- // This is no longer visible, so hide it
- viewState.startAnimation(null, 0, 0, TaskStackView.SLOW_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN, animateAlpha, animateBounds);
- } else {
- // This state is now visible, update the bounds and show it
- int areaAlpha = overrideAreaAlpha != -1
- ? overrideAreaAlpha
- : viewState.dockAreaAlpha;
- int hintAlpha = overrideHintAlpha != -1
- ? overrideHintAlpha
- : viewState.hintTextAlpha;
- Rect bounds = isDefaultDockState
- ? dockState.getPreDockedBounds(getMeasuredWidth(), getMeasuredHeight(),
- mSystemInsets)
- : dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight(),
- mDividerSize, mSystemInsets, getResources());
- if (viewState.dockAreaOverlay.getCallback() != this) {
- viewState.dockAreaOverlay.setCallback(this);
- viewState.dockAreaOverlay.setBounds(bounds);
- }
- viewState.startAnimation(bounds, areaAlpha, hintAlpha,
- TaskStackView.SLOW_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
- animateAlpha, animateBounds);
- }
- }
- }
-
- /**
- * Scrim alpha based on how busy recents is:
- * Scrim will be {@link ScrimController#GRADIENT_SCRIM_ALPHA} when the stack is empty,
- * and {@link ScrimController#GRADIENT_SCRIM_ALPHA_BUSY} when it's full.
- *
- * @return Alpha from 0 to 1.
- */
- private float getOpaqueScrimAlpha() {
- return MathUtils.map(0, 1, ScrimController.GRADIENT_SCRIM_ALPHA,
- ScrimController.GRADIENT_SCRIM_ALPHA_BUSY, mBusynessFactor);
- }
-
- /**
- * Animates the background scrim to the given {@param alpha}.
- */
- private void animateBackgroundScrim(float alpha, int duration) {
- Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
- // Calculate the absolute alpha to animate from
- final int fromAlpha = mBackgroundScrim.getAlpha();
- final int toAlpha = (int) (alpha * 255);
- mBackgroundScrimAnimator = ValueAnimator.ofInt(fromAlpha, toAlpha);
- mBackgroundScrimAnimator.setDuration(duration);
- mBackgroundScrimAnimator.setInterpolator(toAlpha > fromAlpha
- ? Interpolators.ALPHA_IN
- : Interpolators.ALPHA_OUT);
- mBackgroundScrimAnimator.addUpdateListener(mUpdateBackgroundScrimAlpha);
- mBackgroundScrimAnimator.start();
- }
-
- /**
- * @return the bounds of the stack action button.
- */
- Rect getStackActionButtonBoundsFromStackLayout() {
- Rect actionButtonRect = new Rect(
- mTaskStackView.mLayoutAlgorithm.getStackActionButtonRect());
- int left, top;
- if (Recents.getConfiguration().isLowRamDevice) {
- Rect windowRect = Recents.getSystemServices().getWindowRect();
- int spaceLeft = windowRect.width() - mSystemInsets.left - mSystemInsets.right;
- left = (spaceLeft - mStackActionButton.getMeasuredWidth()) / 2 + mSystemInsets.left;
- top = windowRect.height() - (mStackActionButton.getMeasuredHeight()
- + mSystemInsets.bottom + mStackActionButton.getPaddingBottom() / 2);
- } else {
- left = isLayoutRtl()
- ? actionButtonRect.left - mStackActionButton.getPaddingLeft()
- : actionButtonRect.right + mStackActionButton.getPaddingRight()
- - mStackActionButton.getMeasuredWidth();
- top = actionButtonRect.top +
- (actionButtonRect.height() - mStackActionButton.getMeasuredHeight()) / 2;
- }
- actionButtonRect.set(left, top, left + mStackActionButton.getMeasuredWidth(),
- top + mStackActionButton.getMeasuredHeight());
- return actionButtonRect;
- }
-
- View getStackActionButton() {
- return mStackActionButton;
- }
-
- /**
- * Launches the specified {@link Task}.
- */
- public void launchTaskFromRecents(final TaskStack stack, @Nullable final Task task,
- final TaskStackView stackView, final TaskView taskView,
- final boolean screenPinningRequested, final int windowingMode, final int activityType) {
-
- final Runnable animStartedListener;
- final AppTransitionAnimationSpecsFuture transitionFuture;
- if (taskView != null) {
-
- // Fetch window rect here already in order not to be blocked on lock contention in WM
- // when the future calls it.
- final Rect windowRect = Recents.getSystemServices().getWindowRect();
- transitionFuture = new AppTransitionAnimationSpecsFuture(stackView.getHandler()) {
- @Override
- public List<AppTransitionAnimationSpecCompat> composeSpecs() {
- return mTransitionHelper.composeAnimationSpecs(task, stackView, windowingMode,
- activityType, windowRect);
- }
- };
- animStartedListener = new Runnable() {
- private boolean mHandled;
-
- @Override
- public void run() {
- if (mHandled) {
- return;
- }
- mHandled = true;
-
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
- EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
- stackView.cancelAllTaskViewAnimations();
-
- if (screenPinningRequested) {
- // Request screen pinning after the animation runs
- mHandler.postDelayed(() -> {
- EventBus.getDefault().send(new ScreenPinningRequestEvent(mContext,
- task.key.id));
- }, 350);
- }
-
- if (!Recents.getConfiguration().isLowRamDevice) {
- // Reset the state where we are waiting for the transition to start
- EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
- }
- }
- };
- } else {
- // This is only the case if the task is not on screen (scrolled offscreen for example)
- transitionFuture = null;
- animStartedListener = new Runnable() {
- private boolean mHandled;
-
- @Override
- public void run() {
- if (mHandled) {
- return;
- }
- mHandled = true;
-
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
- EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
- stackView.cancelAllTaskViewAnimations();
-
- if (!Recents.getConfiguration().isLowRamDevice) {
- // Reset the state where we are waiting for the transition to start
- EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
- }
- }
- };
- }
-
- EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(true));
- final ActivityOptions opts = RecentsTransition.createAspectScaleAnimation(mContext,
- mHandler, true /* scaleUp */, transitionFuture != null ? transitionFuture : null,
- animStartedListener);
- if (taskView == null) {
- // If there is no task view, then we do not need to worry about animating out occluding
- // task views, and we can launch immediately
- startTaskActivity(stack, task, taskView, opts, transitionFuture,
- windowingMode, activityType);
- } else {
- LaunchTaskStartedEvent launchStartedEvent = new LaunchTaskStartedEvent(taskView,
- screenPinningRequested);
- EventBus.getDefault().send(launchStartedEvent);
- startTaskActivity(stack, task, taskView, opts, transitionFuture, windowingMode,
- activityType);
- }
- ActivityManagerWrapper.getInstance().closeSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
- }
-
- /**
- * Starts the activity for the launch task.
- *
- * @param taskView this is the {@link TaskView} that we are launching from. This can be null if
- * we are toggling recents and the launch-to task is now offscreen.
- */
- private void startTaskActivity(TaskStack stack, Task task, @Nullable TaskView taskView,
- ActivityOptions opts, AppTransitionAnimationSpecsFuture transitionFuture,
- int windowingMode, int activityType) {
- ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(task.key, opts,
- windowingMode, activityType, succeeded -> {
- if (succeeded) {
- // Keep track of the index of the task launch
- int taskIndexFromFront = 0;
- int taskIndex = stack.indexOfTask(task);
- if (taskIndex > -1) {
- taskIndexFromFront = stack.getTaskCount() - taskIndex - 1;
- }
- EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
- } else {
- Log.e(TAG, mContext.getString(R.string.recents_launch_error_message, task.title));
-
- // Dismiss the task if we fail to launch it
- if (taskView != null) {
- taskView.dismissTask();
- }
-
- // Keep track of failed launches
- EventBus.getDefault().send(new LaunchTaskFailedEvent());
- }
- }, getHandler());
- if (transitionFuture != null) {
- mHandler.post(transitionFuture::composeSpecsSynchronous);
- }
- }
-
- @Override
- public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
- super.requestDisallowInterceptTouchEvent(disallowIntercept);
- mTouchHandler.cancelStackActionButtonClick();
- }
-
- public void dump(String prefix, PrintWriter writer) {
- String innerPrefix = prefix + " ";
- String id = Integer.toHexString(System.identityHashCode(this));
-
- writer.print(prefix); writer.print(TAG);
- writer.print(" awaitingFirstLayout="); writer.print(mAwaitingFirstLayout ? "Y" : "N");
- writer.print(" insets="); writer.print(Utilities.dumpRect(mSystemInsets));
- writer.print(" [0x"); writer.print(id); writer.print("]");
- writer.println();
-
- if (getStack() != null) {
- getStack().dump(innerPrefix, writer);
- }
- if (mTaskStackView != null) {
- mTaskStackView.dump(innerPrefix, writer);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
deleted file mode 100644
index 53a91e5..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.PointerIcon;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewDebug;
-
-import com.android.internal.policy.DividerSnapAlgorithm;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
-import com.android.systemui.recents.events.ui.HideIncompatibleAppOverlayEvent;
-import com.android.systemui.recents.events.ui.ShowIncompatibleAppOverlayEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartInitializeDropTargetsEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.model.Task;
-
-import java.util.ArrayList;
-
-/**
- * Handles touch events for a RecentsView.
- */
-public class RecentsViewTouchHandler {
-
- private RecentsView mRv;
-
- @ViewDebug.ExportedProperty(deepExport=true, prefix="drag_task")
- private Task mDragTask;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="drag_task_view_")
- private TaskView mTaskView;
-
- @ViewDebug.ExportedProperty(category="recents")
- private Point mTaskViewOffset = new Point();
- @ViewDebug.ExportedProperty(category="recents")
- private Point mDownPos = new Point();
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mDragRequested;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mIsDragging;
- private float mDragSlop;
- private int mDeviceId = -1;
-
- private DropTarget mLastDropTarget;
- private DividerSnapAlgorithm mDividerSnapAlgorithm;
- private ArrayList<DropTarget> mDropTargets = new ArrayList<>();
- private ArrayList<DockState> mVisibleDockStates = new ArrayList<>();
-
- public RecentsViewTouchHandler(RecentsView rv) {
- mRv = rv;
- mDragSlop = ViewConfiguration.get(rv.getContext()).getScaledTouchSlop();
- updateSnapAlgorithm();
- }
-
- private void updateSnapAlgorithm() {
- Rect insets = new Rect();
- SystemServicesProxy.getInstance(mRv.getContext()).getStableInsets(insets);
- mDividerSnapAlgorithm = DividerSnapAlgorithm.create(mRv.getContext(), insets);
- }
-
- /**
- * Registers a new drop target for the current drag only.
- */
- public void registerDropTargetForCurrentDrag(DropTarget target) {
- mDropTargets.add(target);
- }
-
- /**
- * Returns the set of visible dock states for this current drag.
- */
- public ArrayList<DockState> getVisibleDockStates() {
- return mVisibleDockStates;
- }
-
- /** Touch preprocessing for handling below */
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return handleTouchEvent(ev) || mDragRequested;
- }
-
- /** Handles touch events once we have intercepted them */
- public boolean onTouchEvent(MotionEvent ev) {
- handleTouchEvent(ev);
- if (ev.getAction() == MotionEvent.ACTION_UP && mRv.getStack().getTaskCount() == 0) {
- EventBus.getDefault().send(new HideRecentsEvent(false, true));
- }
- return true;
- }
-
- /**** Events ****/
-
- public final void onBusEvent(DragStartEvent event) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- mRv.getParent().requestDisallowInterceptTouchEvent(true);
- mDragRequested = true;
- // We defer starting the actual drag handling until the user moves past the drag slop
- mIsDragging = false;
- mDragTask = event.task;
- mTaskView = event.taskView;
- mDropTargets.clear();
-
- int[] recentsViewLocation = new int[2];
- mRv.getLocationInWindow(recentsViewLocation);
- mTaskViewOffset.set(mTaskView.getLeft() - recentsViewLocation[0] + event.tlOffset.x,
- mTaskView.getTop() - recentsViewLocation[1] + event.tlOffset.y);
-
- // Change space coordinates relative to the view to RecentsView when user initiates a touch
- if (event.isUserTouchInitiated) {
- float x = mDownPos.x - mTaskViewOffset.x;
- float y = mDownPos.y - mTaskViewOffset.y;
- mTaskView.setTranslationX(x);
- mTaskView.setTranslationY(y);
- }
-
- mVisibleDockStates.clear();
- if (ActivityTaskManager.supportsMultiWindow(mRv.getContext()) && !ssp.hasDockedTask()
- && mDividerSnapAlgorithm.isSplitScreenFeasible()) {
- Recents.logDockAttempt(mRv.getContext(), event.task.getTopComponent(),
- event.task.resizeMode);
- if (!event.task.isDockable) {
- EventBus.getDefault().send(new ShowIncompatibleAppOverlayEvent());
- } else {
- // Add the dock state drop targets (these take priority)
- DockState[] dockStates = Recents.getConfiguration()
- .getDockStatesForCurrentOrientation();
- for (DockState dockState : dockStates) {
- registerDropTargetForCurrentDrag(dockState);
- dockState.update(mRv.getContext());
- mVisibleDockStates.add(dockState);
- }
- }
- }
-
- // Request other drop targets to register themselves
- EventBus.getDefault().send(new DragStartInitializeDropTargetsEvent(event.task,
- event.taskView, this));
- if (mDeviceId != -1) {
- InputDevice device = InputDevice.getDevice(mDeviceId);
- if (device != null) {
- device.setPointerType(PointerIcon.TYPE_GRABBING);
- }
- }
- }
-
- public final void onBusEvent(DragEndEvent event) {
- if (!mDragTask.isDockable) {
- EventBus.getDefault().send(new HideIncompatibleAppOverlayEvent());
- }
- mDragRequested = false;
- mDragTask = null;
- mTaskView = null;
- mLastDropTarget = null;
- }
-
- public final void onBusEvent(ConfigurationChangedEvent event) {
- if (event.fromDisplayDensityChange || event.fromDeviceOrientationChange) {
- updateSnapAlgorithm();
- }
- }
-
- void cancelStackActionButtonClick() {
- mRv.getStackActionButton().setPressed(false);
- }
-
- private boolean isWithinStackActionButton(float x, float y) {
- Rect rect = mRv.getStackActionButtonBoundsFromStackLayout();
- return mRv.getStackActionButton().getVisibility() == View.VISIBLE &&
- mRv.getStackActionButton().pointInView(x - rect.left, y - rect.top, 0 /* slop */);
- }
-
- private void changeStackActionButtonDrawableHotspot(float x, float y) {
- Rect rect = mRv.getStackActionButtonBoundsFromStackLayout();
- mRv.getStackActionButton().drawableHotspotChanged(x - rect.left, y - rect.top);
- }
-
- /**
- * Handles dragging touch events
- */
- private boolean handleTouchEvent(MotionEvent ev) {
- int action = ev.getActionMasked();
- boolean consumed = false;
- float evX = ev.getX();
- float evY = ev.getY();
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mDownPos.set((int) evX, (int) evY);
- mDeviceId = ev.getDeviceId();
-
- if (isWithinStackActionButton(evX, evY)) {
- changeStackActionButtonDrawableHotspot(evX, evY);
- mRv.getStackActionButton().setPressed(true);
- }
- break;
- case MotionEvent.ACTION_MOVE: {
- float x = evX - mTaskViewOffset.x;
- float y = evY - mTaskViewOffset.y;
-
- if (mRv.getStackActionButton().isPressed() && isWithinStackActionButton(evX, evY)) {
- changeStackActionButtonDrawableHotspot(evX, evY);
- }
-
- if (mDragRequested) {
- if (!mIsDragging) {
- mIsDragging = Math.hypot(evX - mDownPos.x, evY - mDownPos.y) > mDragSlop;
- }
- if (mIsDragging) {
- int width = mRv.getMeasuredWidth();
- int height = mRv.getMeasuredHeight();
-
- DropTarget currentDropTarget = null;
-
- // Give priority to the current drop target to retain the touch handling
- if (mLastDropTarget != null) {
- if (mLastDropTarget.acceptsDrop((int) evX, (int) evY, width, height,
- mRv.mSystemInsets, true /* isCurrentTarget */)) {
- currentDropTarget = mLastDropTarget;
- }
- }
-
- // Otherwise, find the next target to handle this event
- if (currentDropTarget == null) {
- for (DropTarget target : mDropTargets) {
- if (target.acceptsDrop((int) evX, (int) evY, width, height,
- mRv.mSystemInsets, false /* isCurrentTarget */)) {
- currentDropTarget = target;
- break;
- }
- }
- }
- if (mLastDropTarget != currentDropTarget) {
- mLastDropTarget = currentDropTarget;
- EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask,
- currentDropTarget));
- }
- }
- mTaskView.setTranslationX(x);
- mTaskView.setTranslationY(y);
- }
- break;
- }
- case MotionEvent.ACTION_UP:
- case MotionEvent.ACTION_CANCEL: {
- if (mRv.getStackActionButton().isPressed() && isWithinStackActionButton(evX, evY)) {
- EventBus.getDefault().send(new DismissAllTaskViewsEvent());
- consumed = true;
- }
- cancelStackActionButtonClick();
- if (mDragRequested) {
- boolean cancelled = action == MotionEvent.ACTION_CANCEL;
- if (cancelled) {
- EventBus.getDefault().send(new DragDropTargetChangedEvent(mDragTask, null));
- }
- EventBus.getDefault().send(new DragEndEvent(mDragTask, mTaskView,
- !cancelled ? mLastDropTarget : null));
- break;
- }
- mDeviceId = -1;
- }
- }
- return consumed;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
deleted file mode 100644
index 170e39d..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.view.View;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivity;
-import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
-import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-
-/** Manages the scrims for the various system bars. */
-public class SystemBarScrimViews {
-
- private static final int DEFAULT_ANIMATION_DURATION = 150;
-
- private Context mContext;
-
- private View mNavBarScrimView;
-
- private boolean mHasNavBarScrim;
- private boolean mShouldAnimateNavBarScrim;
- private boolean mHasTransposedNavBar;
- private boolean mHasDockedTasks;
- private int mNavBarScrimEnterDuration;
-
- public SystemBarScrimViews(RecentsActivity activity) {
- mContext = activity;
- mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
- mNavBarScrimView.forceHasOverlappingRendering(false);
- mNavBarScrimEnterDuration = activity.getResources().getInteger(
- R.integer.recents_nav_bar_scrim_enter_duration);
- mHasNavBarScrim = Recents.getSystemServices().hasTransposedNavigationBar();
- mHasDockedTasks = Recents.getSystemServices().hasDockedTask();
- }
-
- /**
- * Updates the nav bar scrim.
- */
- public void updateNavBarScrim(boolean animateNavBarScrim, boolean hasStackTasks,
- AnimationProps animation) {
- prepareEnterRecentsAnimation(isNavBarScrimRequired(hasStackTasks), animateNavBarScrim);
- if (animateNavBarScrim && animation != null) {
- animateNavBarScrimVisibility(true, animation);
- }
- }
-
- /**
- * Prepares the scrim views for animating when entering Recents. This will be called before
- * the first draw, unless we are updating the scrim on configuration change.
- */
- private void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
- mHasNavBarScrim = hasNavBarScrim;
- mShouldAnimateNavBarScrim = animateNavBarScrim;
-
- mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
- View.VISIBLE : View.INVISIBLE);
- }
-
- /**
- * Animates the nav bar scrim visibility.
- */
- private void animateNavBarScrimVisibility(boolean visible, AnimationProps animation) {
- int toY = 0;
- if (visible) {
- mNavBarScrimView.setVisibility(View.VISIBLE);
- mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
- } else {
- toY = mNavBarScrimView.getMeasuredHeight();
- }
- if (animation != AnimationProps.IMMEDIATE) {
- mNavBarScrimView.animate()
- .translationY(toY)
- .setDuration(animation.getDuration(AnimationProps.BOUNDS))
- .setInterpolator(animation.getInterpolator(AnimationProps.BOUNDS))
- .start();
- } else {
- mNavBarScrimView.setTranslationY(toY);
- }
- }
-
- /**
- * @return Whether to show the nav bar scrim.
- */
- private boolean isNavBarScrimRequired(boolean hasStackTasks) {
- return hasStackTasks && !mHasTransposedNavBar && !mHasDockedTasks;
- }
-
- /**** EventBus events ****/
-
- /**
- * Starts animating the scrim views when entering Recents.
- */
- public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- if (mHasNavBarScrim) {
- AnimationProps animation = mShouldAnimateNavBarScrim
- ? new AnimationProps()
- .setDuration(AnimationProps.BOUNDS, mNavBarScrimEnterDuration)
- .setInterpolator(AnimationProps.BOUNDS, Interpolators.DECELERATE_QUINT)
- : AnimationProps.IMMEDIATE;
- animateNavBarScrimVisibility(true, animation);
- }
- }
-
- /**
- * Starts animating the scrim views when leaving Recents (either via launching a task, or
- * going home).
- */
- public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
- if (mHasNavBarScrim) {
- AnimationProps animation = createBoundsAnimation(
- TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION);
- animateNavBarScrimVisibility(false, animation);
- }
- }
-
- public final void onBusEvent(DismissAllTaskViewsEvent event) {
- if (mHasNavBarScrim) {
- AnimationProps animation = createBoundsAnimation(
- TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION);
- animateNavBarScrimVisibility(false, animation);
- }
- }
-
- public final void onBusEvent(ConfigurationChangedEvent event) {
- if (event.fromDeviceOrientationChange) {
- mHasNavBarScrim = Recents.getSystemServices().hasTransposedNavigationBar();
- }
- animateScrimToCurrentNavBarState(event.hasStackTasks);
- }
-
- public final void onBusEvent(MultiWindowStateChangedEvent event) {
- mHasDockedTasks = event.inMultiWindow;
- animateScrimToCurrentNavBarState(event.stack.getTaskCount() > 0);
- }
-
- public final void onBusEvent(final DragEndEvent event) {
- // Hide the nav bar scrims once we drop to a dock region
- if (event.dropTarget instanceof DockState) {
- animateScrimToCurrentNavBarState(false /* hasStackTasks */);
- }
- }
-
- public final void onBusEvent(final DragEndCancelledEvent event) {
- // Restore the scrims to the normal state
- animateScrimToCurrentNavBarState(event.stack.getTaskCount() > 0);
- }
-
- /**
- * Animates the scrim to match the state of the current nav bar.
- */
- private void animateScrimToCurrentNavBarState(boolean hasStackTasks) {
- boolean hasNavBarScrim = isNavBarScrimRequired(hasStackTasks);
- if (mHasNavBarScrim != hasNavBarScrim) {
- AnimationProps animation = hasNavBarScrim
- ? createBoundsAnimation(DEFAULT_ANIMATION_DURATION)
- : AnimationProps.IMMEDIATE;
- animateNavBarScrimVisibility(hasNavBarScrim, animation);
- }
- mHasNavBarScrim = hasNavBarScrim;
- }
-
- /**
- * @return a default animation to aniamte the bounds of the scrim.
- */
- private AnimationProps createBoundsAnimation(int duration) {
- return new AnimationProps()
- .setDuration(AnimationProps.BOUNDS, duration)
- .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
deleted file mode 100644
index 67d0978..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.util.Log;
-import android.view.animation.Interpolator;
-import android.view.animation.PathInterpolator;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsDebugFlags;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.recents.views.lowram.TaskStackLowRamLayoutAlgorithm;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A helper class to create task view animations for {@link TaskView}s in a {@link TaskStackView},
- * but not the contents of the {@link TaskView}s.
- */
-public class TaskStackAnimationHelper {
-
- /**
- * Callbacks from the helper to coordinate view-content animations with view animations.
- */
- public interface Callbacks {
- /**
- * Callback to prepare for the start animation for the launch target {@link TaskView}.
- */
- void onPrepareLaunchTargetForEnterAnimation();
-
- /**
- * Callback to start the animation for the launch target {@link TaskView}.
- */
- void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
- boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger);
-
- /**
- * Callback to start the animation for the launch target {@link TaskView} when it is
- * launched from Recents.
- */
- void onStartLaunchTargetLaunchAnimation(int duration, boolean screenPinningRequested,
- ReferenceCountedTrigger postAnimationTrigger);
-
- /**
- * Callback to start the animation for the front {@link TaskView} if there is no launch
- * target.
- */
- void onStartFrontTaskEnterAnimation(boolean screenPinningEnabled);
- }
-
- private static final int DOUBLE_FRAME_OFFSET_MS = 33;
- private static final int FRAME_OFFSET_MS = 16;
-
- private static final int ENTER_EXIT_NUM_ANIMATING_TASKS = 5;
-
- private static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
- public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 300;
- private static final Interpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = Interpolators.LINEAR;
-
- public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 200;
- private static final Interpolator EXIT_TO_HOME_TRANSLATION_INTERPOLATOR =
- new PathInterpolator(0.4f, 0, 0.6f, 1f);
-
- private static final int DISMISS_TASK_DURATION = 175;
- private static final int DISMISS_ALL_TASKS_DURATION = 200;
- private static final Interpolator DISMISS_ALL_TRANSLATION_INTERPOLATOR =
- new PathInterpolator(0.4f, 0, 1f, 1f);
-
- private static final Interpolator FOCUS_NEXT_TASK_INTERPOLATOR =
- new PathInterpolator(0.4f, 0, 0, 1f);
- private static final Interpolator FOCUS_IN_FRONT_NEXT_TASK_INTERPOLATOR =
- new PathInterpolator(0, 0, 0, 1f);
- private static final Interpolator FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR =
- Interpolators.LINEAR_OUT_SLOW_IN;
-
- private static final Interpolator ENTER_WHILE_DOCKING_INTERPOLATOR =
- Interpolators.LINEAR_OUT_SLOW_IN;
-
- private final int mEnterAndExitFromHomeTranslationOffset;
- private TaskStackView mStackView;
-
- private TaskViewTransform mTmpTransform = new TaskViewTransform();
- private ArrayList<TaskViewTransform> mTmpCurrentTaskTransforms = new ArrayList<>();
- private ArrayList<TaskViewTransform> mTmpFinalTaskTransforms = new ArrayList<>();
-
- public TaskStackAnimationHelper(Context context, TaskStackView stackView) {
- mStackView = stackView;
- mEnterAndExitFromHomeTranslationOffset = Recents.getConfiguration().isGridEnabled
- ? 0 : DOUBLE_FRAME_OFFSET_MS;
- }
-
- /**
- * Prepares the stack views and puts them in their initial animation state while visible, before
- * the in-app enter animations start (after the window-transition completes).
- */
- public void prepareForEnterAnimation() {
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- Resources res = mStackView.getResources();
- Resources appResources = mStackView.getContext().getApplicationContext().getResources();
-
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mStackView.getScroller();
- TaskStack stack = mStackView.getStack();
- Task launchTargetTask = stack.getLaunchTarget();
-
- // Break early if there are no tasks
- if (stack.getTaskCount() == 0) {
- return;
- }
-
- int offscreenYOffset = stackLayout.mStackRect.height();
- int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
- R.dimen.recents_task_stack_animation_affiliate_enter_offset);
- int launchedWhileDockingOffset = res.getDimensionPixelSize(
- R.dimen.recents_task_stack_animation_launched_while_docking_offset);
- boolean isLandscape = appResources.getConfiguration().orientation
- == Configuration.ORIENTATION_LANDSCAPE;
-
- float top = 0;
- final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
- if (isLowRamDevice && launchState.launchedFromApp && !launchState.launchedViaDockGesture) {
- stackLayout.getStackTransform(launchTargetTask, stackScroller.getStackScroll(),
- mTmpTransform, null /* frontTransform */);
- top = mTmpTransform.rect.top;
- }
-
- // Prepare each of the task views for their enter animation from front to back
- List<TaskView> taskViews = mStackView.getTaskViews();
- for (int i = taskViews.size() - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- // Get the current transform for the task, which will be used to position it offscreen
- stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
- null);
-
- if (launchState.launchedFromApp && !launchState.launchedViaDockGesture) {
- if (task.isLaunchTarget) {
- tv.onPrepareLaunchTargetForEnterAnimation();
- } else if (isLowRamDevice && i >= taskViews.size() -
- (TaskStackLowRamLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT + 1)
- && !RecentsDebugFlags.Static.DisableRecentsLowRamEnterExitAnimation) {
- // Move the last 2nd and 3rd last tasks in-app animation to match the motion of
- // the last task's app transition
- stackLayout.getStackTransform(task, stackScroller.getStackScroll(),
- mTmpTransform, null);
- mTmpTransform.rect.offset(0, -top);
- mTmpTransform.alpha = 0f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform,
- AnimationProps.IMMEDIATE);
- stackLayout.getStackTransform(task, stackScroller.getStackScroll(),
- mTmpTransform, null);
- mTmpTransform.alpha = 1f;
- // Duration see {@link
- // com.android.server.wm.AppTransition#DEFAULT_APP_TRANSITION_DURATION}
- mStackView.updateTaskViewToTransform(tv, mTmpTransform,
- new AnimationProps(336, Interpolators.FAST_OUT_SLOW_IN));
- }
- } else if (launchState.launchedFromHome) {
- if (isLowRamDevice) {
- mTmpTransform.rect.offset(0, stackLayout.getTaskRect().height() / 4);
- } else {
- // Move the task view off screen (below) so we can animate it in
- mTmpTransform.rect.offset(0, offscreenYOffset);
- }
- mTmpTransform.alpha = 0f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, AnimationProps.IMMEDIATE);
- } else if (launchState.launchedViaDockGesture) {
- int offset = isLandscape
- ? launchedWhileDockingOffset
- : (int) (offscreenYOffset * 0.9f);
- mTmpTransform.rect.offset(0, offset);
- mTmpTransform.alpha = 0f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, AnimationProps.IMMEDIATE);
- }
- }
- }
-
- /**
- * Starts the in-app enter animation, which animates the {@link TaskView}s to their final places
- * depending on how Recents was triggered.
- */
- public void startEnterAnimation(final ReferenceCountedTrigger postAnimationTrigger) {
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- Resources res = mStackView.getResources();
- Resources appRes = mStackView.getContext().getApplicationContext().getResources();
-
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mStackView.getScroller();
- TaskStack stack = mStackView.getStack();
- Task launchTargetTask = stack.getLaunchTarget();
-
- // Break early if there are no tasks
- if (stack.getTaskCount() == 0) {
- return;
- }
-
- final boolean isLowRamDevice = Recents.getConfiguration().isLowRamDevice;
- int taskViewEnterFromAppDuration = res.getInteger(
- R.integer.recents_task_enter_from_app_duration);
- int taskViewEnterFromAffiliatedAppDuration = res.getInteger(
- R.integer.recents_task_enter_from_affiliated_app_duration);
- int dockGestureAnimDuration = appRes.getInteger(
- R.integer.long_press_dock_anim_duration);
-
- // Since low ram devices have an animation when entering app -> recents, do not allow
- // toggle until the animation is complete
- if (launchState.launchedFromApp && !launchState.launchedViaDockGesture && isLowRamDevice) {
- postAnimationTrigger.addLastDecrementRunnable(() -> EventBus.getDefault()
- .send(new SetWaitingForTransitionStartEvent(false)));
- }
-
- // Create enter animations for each of the views from front to back
- List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- int taskIndexFromFront = taskViewCount - i - 1;
- int taskIndexFromBack = i;
- final TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- // Get the current transform for the task, which will be updated to the final transform
- // to animate to depending on how recents was invoked
- stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
- null);
-
- if (launchState.launchedFromApp && !launchState.launchedViaDockGesture) {
- if (task.isLaunchTarget) {
- tv.onStartLaunchTargetEnterAnimation(mTmpTransform,
- taskViewEnterFromAppDuration, mStackView.mScreenPinningEnabled,
- postAnimationTrigger);
- }
-
- } else if (launchState.launchedFromHome) {
- // Animate the tasks up, but offset the animations to be relative to the front-most
- // task animation
- final float startOffsetFraction = (float) (Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS,
- taskIndexFromFront) * mEnterAndExitFromHomeTranslationOffset) /
- ENTER_FROM_HOME_TRANSLATION_DURATION;
- AnimationProps taskAnimation = new AnimationProps()
- .setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
- .setListener(postAnimationTrigger.decrementOnAnimationEnd());
- if (isLowRamDevice) {
- taskAnimation.setInterpolator(AnimationProps.BOUNDS,
- Interpolators.FAST_OUT_SLOW_IN)
- .setDuration(AnimationProps.BOUNDS, 150)
- .setDuration(AnimationProps.ALPHA, 150);
- } else {
- taskAnimation.setStartDelay(AnimationProps.ALPHA,
- Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
- FRAME_OFFSET_MS)
- .setInterpolator(AnimationProps.BOUNDS,
- new RecentsEntrancePathInterpolator(0f, 0f, 0.2f, 1f,
- startOffsetFraction))
- .setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION)
- .setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION);
- }
- postAnimationTrigger.increment();
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- if (i == taskViewCount - 1) {
- tv.onStartFrontTaskEnterAnimation(mStackView.mScreenPinningEnabled);
- }
- } else if (launchState.launchedViaDockGesture) {
- // Animate the tasks up - add some delay to match the divider animation
- AnimationProps taskAnimation = new AnimationProps()
- .setDuration(AnimationProps.BOUNDS, dockGestureAnimDuration +
- (taskIndexFromBack * DOUBLE_FRAME_OFFSET_MS))
- .setInterpolator(AnimationProps.BOUNDS,
- ENTER_WHILE_DOCKING_INTERPOLATOR)
- .setStartDelay(AnimationProps.BOUNDS, 48)
- .setListener(postAnimationTrigger.decrementOnAnimationEnd());
- postAnimationTrigger.increment();
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- }
- }
-
- /**
- * Starts an in-app animation to hide all the task views so that we can transition back home.
- */
- public void startExitToHomeAnimation(boolean animated,
- ReferenceCountedTrigger postAnimationTrigger) {
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStack stack = mStackView.getStack();
-
- // Break early if there are no tasks
- if (stack.getTaskCount() == 0) {
- return;
- }
-
- int offscreenYOffset = stackLayout.mStackRect.height();
-
- // Create the animations for each of the tasks
- List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- int taskIndexFromFront = taskViewCount - i - 1;
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- if (mStackView.isIgnoredTask(task)) {
- continue;
- }
-
- // Animate the tasks down
- AnimationProps taskAnimation;
- if (animated) {
- int delay = Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS , taskIndexFromFront) *
- mEnterAndExitFromHomeTranslationOffset;
- taskAnimation = new AnimationProps()
- .setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION)
- .setListener(postAnimationTrigger.decrementOnAnimationEnd());
- if (Recents.getConfiguration().isLowRamDevice) {
- taskAnimation.setInterpolator(AnimationProps.BOUNDS,
- Interpolators.FAST_OUT_SLOW_IN);
- } else {
- taskAnimation.setStartDelay(AnimationProps.BOUNDS, delay)
- .setInterpolator(AnimationProps.BOUNDS,
- EXIT_TO_HOME_TRANSLATION_INTERPOLATOR);
- }
- postAnimationTrigger.increment();
- } else {
- taskAnimation = AnimationProps.IMMEDIATE;
- }
-
- mTmpTransform.fillIn(tv);
- if (Recents.getConfiguration().isLowRamDevice) {
- taskAnimation.setInterpolator(AnimationProps.ALPHA,
- EXIT_TO_HOME_TRANSLATION_INTERPOLATOR)
- .setDuration(AnimationProps.ALPHA, EXIT_TO_HOME_TRANSLATION_DURATION);
- mTmpTransform.rect.offset(0, stackLayout.mTaskStackLowRamLayoutAlgorithm
- .getTaskRect().height() / 4);
- mTmpTransform.alpha = 0f;
- } else {
- mTmpTransform.rect.offset(0, offscreenYOffset);
- }
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- }
-
- /**
- * Starts the animation for the launching task view, hiding any tasks that might occlude the
- * window transition for the launching task.
- */
- public void startLaunchTaskAnimation(TaskView launchingTaskView, boolean screenPinningRequested,
- final ReferenceCountedTrigger postAnimationTrigger) {
- Resources res = mStackView.getResources();
-
- int taskViewExitToAppDuration = res.getInteger(
- R.integer.recents_task_exit_to_app_duration);
- int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
- R.dimen.recents_task_stack_animation_affiliate_enter_offset);
-
- Task launchingTask = launchingTaskView.getTask();
- List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- if (tv == launchingTaskView) {
- tv.setClipViewInStack(false);
- postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- tv.setClipViewInStack(true);
- }
- });
- tv.onStartLaunchTargetLaunchAnimation(taskViewExitToAppDuration,
- screenPinningRequested, postAnimationTrigger);
- }
- }
- }
-
- /**
- * Starts the delete animation for the specified {@link TaskView}.
- */
- public void startDeleteTaskAnimation(final TaskView deleteTaskView, boolean gridLayout,
- final ReferenceCountedTrigger postAnimationTrigger) {
- if (gridLayout) {
- startTaskGridDeleteTaskAnimation(deleteTaskView, postAnimationTrigger);
- } else {
- startTaskStackDeleteTaskAnimation(deleteTaskView, postAnimationTrigger);
- }
- }
-
- /**
- * Starts the delete animation for all the {@link TaskView}s.
- */
- public void startDeleteAllTasksAnimation(final List<TaskView> taskViews, boolean gridLayout,
- final ReferenceCountedTrigger postAnimationTrigger) {
- if (gridLayout) {
- for (int i = 0; i < taskViews.size(); i++) {
- startTaskGridDeleteTaskAnimation(taskViews.get(i), postAnimationTrigger);
- }
- } else {
- startTaskStackDeleteAllTasksAnimation(taskViews, postAnimationTrigger);
- }
- }
-
- /**
- * Starts the animation to focus the next {@link TaskView} when paging through recents.
- *
- * @return whether or not this will trigger a scroll in the stack
- */
- public boolean startScrollToFocusedTaskAnimation(Task newFocusedTask,
- boolean requestViewFocus) {
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mStackView.getScroller();
- TaskStack stack = mStackView.getStack();
-
- final float curScroll = stackScroller.getStackScroll();
- final float newScroll = stackScroller.getBoundedStackScroll(
- stackLayout.getStackScrollForTask(newFocusedTask));
- boolean willScrollToFront = newScroll > curScroll;
- boolean willScroll = Float.compare(newScroll, curScroll) != 0;
-
- // Get the current set of task transforms
- int taskViewCount = mStackView.getTaskViews().size();
- ArrayList<Task> stackTasks = stack.getTasks();
- mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
-
- // Pick up the newly visible views after the scroll
- mStackView.bindVisibleTaskViews(newScroll);
-
- // Update the internal state
- stackLayout.setFocusState(TaskStackLayoutAlgorithm.STATE_FOCUSED);
- stackScroller.setStackScroll(newScroll, null /* animation */);
- mStackView.cancelDeferredTaskViewLayoutAnimation();
-
- // Get the final set of task transforms
- mStackView.getLayoutTaskTransforms(newScroll, stackLayout.getFocusState(), stackTasks,
- true /* ignoreTaskOverrides */, mTmpFinalTaskTransforms);
-
- // Focus the task view
- TaskView newFocusedTaskView = mStackView.getChildViewForTask(newFocusedTask);
- if (newFocusedTaskView == null) {
- // Log the error if we have no task view, and skip the animation
- Log.e("TaskStackAnimationHelper", "b/27389156 null-task-view prebind:" + taskViewCount +
- " postbind:" + mStackView.getTaskViews().size() + " prescroll:" + curScroll +
- " postscroll: " + newScroll);
- return false;
- }
- newFocusedTaskView.setFocusedState(true, requestViewFocus);
-
- // Setup the end listener to return all the hidden views to the view pool after the
- // focus animation
- ReferenceCountedTrigger postAnimTrigger = new ReferenceCountedTrigger();
- postAnimTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- mStackView.bindVisibleTaskViews(newScroll);
- }
- });
-
- List<TaskView> taskViews = mStackView.getTaskViews();
- taskViewCount = taskViews.size();
- int newFocusTaskViewIndex = taskViews.indexOf(newFocusedTaskView);
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- if (mStackView.isIgnoredTask(task)) {
- continue;
- }
-
- int taskIndex = stackTasks.indexOf(task);
- TaskViewTransform fromTransform = mTmpCurrentTaskTransforms.get(taskIndex);
- TaskViewTransform toTransform = mTmpFinalTaskTransforms.get(taskIndex);
-
- // Update the task to the initial state (for the newly picked up tasks)
- mStackView.updateTaskViewToTransform(tv, fromTransform, AnimationProps.IMMEDIATE);
-
- int duration;
- Interpolator interpolator;
- if (willScrollToFront) {
- duration = calculateStaggeredAnimDuration(i);
- interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR;
- } else {
- if (i < newFocusTaskViewIndex) {
- duration = 150 + ((newFocusTaskViewIndex - i - 1) * 50);
- interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR;
- } else if (i > newFocusTaskViewIndex) {
- duration = Math.max(100, 150 - ((i - newFocusTaskViewIndex - 1) * 50));
- interpolator = FOCUS_IN_FRONT_NEXT_TASK_INTERPOLATOR;
- } else {
- duration = 200;
- interpolator = FOCUS_NEXT_TASK_INTERPOLATOR;
- }
- }
-
- AnimationProps anim = new AnimationProps()
- .setDuration(AnimationProps.BOUNDS, duration)
- .setInterpolator(AnimationProps.BOUNDS, interpolator)
- .setListener(postAnimTrigger.decrementOnAnimationEnd());
- postAnimTrigger.increment();
- mStackView.updateTaskViewToTransform(tv, toTransform, anim);
- }
- return willScroll;
- }
-
- /**
- * Starts the animation to go to the initial stack layout with a task focused. In addition, the
- * previous task will be animated in after the scroll completes.
- */
- public void startNewStackScrollAnimation(TaskStack newStack,
- ReferenceCountedTrigger animationTrigger) {
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mStackView.getScroller();
-
- // Get the current set of task transforms
- ArrayList<Task> stackTasks = newStack.getTasks();
- mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
-
- // Update the stack
- mStackView.setTasks(newStack, false /* allowNotifyStackChanges */);
- mStackView.updateLayoutAlgorithm(false /* boundScroll */);
-
- // Pick up the newly visible views after the scroll
- final float newScroll = stackLayout.mInitialScrollP;
- mStackView.bindVisibleTaskViews(newScroll);
-
- // Update the internal state
- stackLayout.setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
- stackLayout.setTaskOverridesForInitialState(newStack, true /* ignoreScrollToFront */);
- stackScroller.setStackScroll(newScroll);
- mStackView.cancelDeferredTaskViewLayoutAnimation();
-
- // Get the final set of task transforms
- mStackView.getLayoutTaskTransforms(newScroll, stackLayout.getFocusState(), stackTasks,
- false /* ignoreTaskOverrides */, mTmpFinalTaskTransforms);
-
- // Hide the front most task view until the scroll is complete
- Task frontMostTask = newStack.getFrontMostTask();
- final TaskView frontMostTaskView = mStackView.getChildViewForTask(frontMostTask);
- final TaskViewTransform frontMostTransform = mTmpFinalTaskTransforms.get(
- stackTasks.indexOf(frontMostTask));
- if (frontMostTaskView != null) {
- mStackView.updateTaskViewToTransform(frontMostTaskView,
- stackLayout.getFrontOfStackTransform(), AnimationProps.IMMEDIATE);
- }
-
- // Setup the end listener to return all the hidden views to the view pool after the
- // focus animation
- animationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- mStackView.bindVisibleTaskViews(newScroll);
-
- // Now, animate in the front-most task
- if (frontMostTaskView != null) {
- mStackView.updateTaskViewToTransform(frontMostTaskView, frontMostTransform,
- new AnimationProps(75, 250, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR));
- }
- }
- });
-
- List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- if (mStackView.isIgnoredTask(task)) {
- continue;
- }
- if (task == frontMostTask && frontMostTaskView != null) {
- continue;
- }
-
- int taskIndex = stackTasks.indexOf(task);
- TaskViewTransform fromTransform = mTmpCurrentTaskTransforms.get(taskIndex);
- TaskViewTransform toTransform = mTmpFinalTaskTransforms.get(taskIndex);
-
- // Update the task to the initial state (for the newly picked up tasks)
- mStackView.updateTaskViewToTransform(tv, fromTransform, AnimationProps.IMMEDIATE);
-
- int duration = calculateStaggeredAnimDuration(i);
- Interpolator interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR;
-
- AnimationProps anim = new AnimationProps()
- .setDuration(AnimationProps.BOUNDS, duration)
- .setInterpolator(AnimationProps.BOUNDS, interpolator)
- .setListener(animationTrigger.decrementOnAnimationEnd());
- animationTrigger.increment();
- mStackView.updateTaskViewToTransform(tv, toTransform, anim);
- }
- }
-
- /**
- * Caclulates a staggered duration for {@link #startScrollToFocusedTaskAnimation} and
- * {@link #startNewStackScrollAnimation}.
- */
- private int calculateStaggeredAnimDuration(int i) {
- return Math.max(100, 100 + ((i - 1) * 50));
- }
-
- private void startTaskGridDeleteTaskAnimation(final TaskView deleteTaskView,
- final ReferenceCountedTrigger postAnimationTrigger) {
- postAnimationTrigger.increment();
- postAnimationTrigger.addLastDecrementRunnable(() -> {
- mStackView.getTouchHandler().onChildDismissed(deleteTaskView);
- });
- deleteTaskView.animate().setDuration(300).scaleX(0.9f).scaleY(0.9f).alpha(0).setListener(
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- postAnimationTrigger.decrement();
- }}).start();
- }
-
- private void startTaskStackDeleteTaskAnimation(final TaskView deleteTaskView,
- final ReferenceCountedTrigger postAnimationTrigger) {
- TaskStackViewTouchHandler touchHandler = mStackView.getTouchHandler();
- touchHandler.onBeginManualDrag(deleteTaskView);
-
- postAnimationTrigger.increment();
- postAnimationTrigger.addLastDecrementRunnable(() -> {
- touchHandler.onChildDismissed(deleteTaskView);
- });
-
- final float dismissSize = touchHandler.getScaledDismissSize();
- ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
- animator.setDuration(400);
- animator.addUpdateListener((animation) -> {
- float progress = (Float) animation.getAnimatedValue();
- deleteTaskView.setTranslationX(progress * dismissSize);
- touchHandler.updateSwipeProgress(deleteTaskView, true, progress);
- });
- animator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- postAnimationTrigger.decrement();
- }
- });
- animator.start();
- }
-
- private void startTaskStackDeleteAllTasksAnimation(final List<TaskView> taskViews,
- final ReferenceCountedTrigger postAnimationTrigger) {
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
-
- int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.getTaskRect().left;
-
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- int taskIndexFromFront = taskViewCount - i - 1;
- int startDelay = taskIndexFromFront * DOUBLE_FRAME_OFFSET_MS;
-
- // Disabling clipping with the stack while the view is animating away
- tv.setClipViewInStack(false);
-
- // Compose the new animation and transform and star the animation
- AnimationProps taskAnimation = new AnimationProps(startDelay,
- DISMISS_ALL_TASKS_DURATION, DISMISS_ALL_TRANSLATION_INTERPOLATOR,
- new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- postAnimationTrigger.decrement();
-
- // Re-enable clipping with the stack (we will reuse this view)
- tv.setClipViewInStack(true);
- }
- });
- postAnimationTrigger.increment();
-
- mTmpTransform.fillIn(tv);
- mTmpTransform.rect.offset(offscreenXOffset, 0);
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
deleted file mode 100644
index d9f79bb..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ /dev/null
@@ -1,1280 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.annotation.IntDef;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.util.SparseIntArray;
-import android.view.ViewDebug;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsDebugFlags;
-import com.android.systemui.recents.misc.FreePathInterpolator;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.recents.views.lowram.TaskStackLowRamLayoutAlgorithm;
-import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
-
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Used to describe a visible range that can be normalized to [0, 1].
- */
-class Range {
- final float relativeMin;
- final float relativeMax;
- float origin;
- float min;
- float max;
-
- public Range(float relMin, float relMax) {
- min = relativeMin = relMin;
- max = relativeMax = relMax;
- }
-
- /**
- * Offsets this range to a given absolute position.
- */
- public void offset(float x) {
- this.origin = x;
- min = x + relativeMin;
- max = x + relativeMax;
- }
-
- /**
- * Returns x normalized to the range 0 to 1 such that 0 = min, 0.5 = origin and 1 = max
- *
- * @param x is an absolute value in the same domain as origin
- */
- public float getNormalizedX(float x) {
- if (x < origin) {
- return 0.5f + 0.5f * (x - origin) / -relativeMin;
- } else {
- return 0.5f + 0.5f * (x - origin) / relativeMax;
- }
- }
-
- /**
- * Given a normalized {@param x} value in this range, projected onto the full range to get an
- * absolute value about the given {@param origin}.
- */
- public float getAbsoluteX(float normX) {
- if (normX < 0.5f) {
- return (normX - 0.5f) / 0.5f * -relativeMin;
- } else {
- return (normX - 0.5f) / 0.5f * relativeMax;
- }
- }
-
- /**
- * Returns whether a value at an absolute x would be within range.
- */
- public boolean isInRange(float absX) {
- return (absX >= Math.floor(min)) && (absX <= Math.ceil(max));
- }
-}
-
-/**
- * The layout logic for a TaskStackView. This layout needs to be able to calculate the stack layout
- * without an activity-specific context only with the information passed in. This layout can have
- * two states focused and unfocused, and in the focused state, there is a task that is displayed
- * more prominently in the stack.
- */
-public class TaskStackLayoutAlgorithm {
-
- private static final String TAG = "TaskStackLayoutAlgorithm";
-
- // The distribution of view bounds alpha
- // XXX: This is a hack because you can currently set the max alpha to be > 1f
- public static final float OUTLINE_ALPHA_MIN_VALUE = 0f;
- public static final float OUTLINE_ALPHA_MAX_VALUE = 2f;
-
- // The medium/maximum dim on the tasks
- private static final float MED_DIM = 0.15f;
- private static final float MAX_DIM = 0.25f;
-
- // The various focus states
- public static final int STATE_FOCUSED = 1;
- public static final int STATE_UNFOCUSED = 0;
-
- // The side that an offset is anchored
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({FROM_TOP, FROM_BOTTOM})
- public @interface AnchorSide {}
- private static final int FROM_TOP = 0;
- private static final int FROM_BOTTOM = 1;
-
- // The extent that we care about when calculating fractions
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({WIDTH, HEIGHT})
- public @interface Extent {}
- private static final int WIDTH = 0;
- private static final int HEIGHT = 1;
-
- public interface TaskStackLayoutAlgorithmCallbacks {
- void onFocusStateChanged(int prevFocusState, int curFocusState);
- }
-
- /**
- * @return True if we should use the grid layout.
- */
- boolean useGridLayout() {
- return Recents.getConfiguration().isGridEnabled;
- }
-
- // A report of the visibility state of the stack
- public static class VisibilityReport {
- public int numVisibleTasks;
- public int numVisibleThumbnails;
-
- public VisibilityReport(int tasks, int thumbnails) {
- numVisibleTasks = tasks;
- numVisibleThumbnails = thumbnails;
- }
- }
-
- Context mContext;
- private TaskStackLayoutAlgorithmCallbacks mCb;
-
- // The task bounds (untransformed) for layout. This rect is anchored at mTaskRoot.
- @ViewDebug.ExportedProperty(category="recents")
- public Rect mTaskRect = new Rect();
- // The stack bounds, inset from the top system insets, and runs to the bottom of the screen
- @ViewDebug.ExportedProperty(category="recents")
- public Rect mStackRect = new Rect();
- // This is the current system insets
- @ViewDebug.ExportedProperty(category="recents")
- public Rect mSystemInsets = new Rect();
-
- // The visible ranges when the stack is focused and unfocused
- private Range mUnfocusedRange;
- private Range mFocusedRange;
-
- // This is the bounds of the stack action above the stack rect
- @ViewDebug.ExportedProperty(category="recents")
- private Rect mStackActionButtonRect = new Rect();
- // The base top margin for the stack from the system insets
- @ViewDebug.ExportedProperty(category="recents")
- private int mBaseTopMargin;
- // The base side margin for the stack from the system insets
- @ViewDebug.ExportedProperty(category="recents")
- private int mBaseSideMargin;
- // The base bottom margin for the stack from the system insets
- @ViewDebug.ExportedProperty(category="recents")
- private int mBaseBottomMargin;
- private int mMinMargin;
-
- // The initial offset that the focused task is from the top
- @ViewDebug.ExportedProperty(category="recents")
- private int mInitialTopOffset;
- private int mBaseInitialTopOffset;
- // The initial offset that the launch-from task is from the bottom
- @ViewDebug.ExportedProperty(category="recents")
- private int mInitialBottomOffset;
- private int mBaseInitialBottomOffset;
-
- // The height between the top margin and the top of the focused task
- @ViewDebug.ExportedProperty(category="recents")
- private int mFocusedTopPeekHeight;
- // The height between the bottom margin and the top of task in front of the focused task
- @ViewDebug.ExportedProperty(category="recents")
- private int mFocusedBottomPeekHeight;
-
- // The offset from the bottom of the stack to the bottom of the bounds when the stack is
- // scrolled to the front
- @ViewDebug.ExportedProperty(category="recents")
- private int mStackBottomOffset;
-
- /** The height, in pixels, of each task view's title bar. */
- private int mTitleBarHeight;
-
- // The paths defining the motion of the tasks when the stack is focused and unfocused
- private Path mUnfocusedCurve;
- private Path mFocusedCurve;
- private FreePathInterpolator mUnfocusedCurveInterpolator;
- private FreePathInterpolator mFocusedCurveInterpolator;
-
- // The paths defining the distribution of the dim to apply to tasks in the stack when focused
- // and unfocused
- private Path mUnfocusedDimCurve;
- private Path mFocusedDimCurve;
- private FreePathInterpolator mUnfocusedDimCurveInterpolator;
- private FreePathInterpolator mFocusedDimCurveInterpolator;
-
- // The state of the stack focus (0..1), which controls the transition of the stack from the
- // focused to non-focused state
- @ViewDebug.ExportedProperty(category="recents")
- private int mFocusState;
-
- // The smallest scroll progress, at this value, the back most task will be visible
- @ViewDebug.ExportedProperty(category="recents")
- float mMinScrollP;
- // The largest scroll progress, at this value, the front most task will be visible above the
- // navigation bar
- @ViewDebug.ExportedProperty(category="recents")
- float mMaxScrollP;
- // The initial progress that the scroller is set when you first enter recents
- @ViewDebug.ExportedProperty(category="recents")
- float mInitialScrollP;
- // The task progress for the front-most task in the stack
- @ViewDebug.ExportedProperty(category="recents")
- float mFrontMostTaskP;
-
- // The last computed task counts
- @ViewDebug.ExportedProperty(category="recents")
- int mNumStackTasks;
-
- // The min/max z translations
- @ViewDebug.ExportedProperty(category="recents")
- int mMinTranslationZ;
- @ViewDebug.ExportedProperty(category="recents")
- public int mMaxTranslationZ;
-
- // Optimization, allows for quick lookup of task -> index
- private SparseIntArray mTaskIndexMap = new SparseIntArray();
- private SparseArray<Float> mTaskIndexOverrideMap = new SparseArray<>();
-
- TaskGridLayoutAlgorithm mTaskGridLayoutAlgorithm;
- TaskStackLowRamLayoutAlgorithm mTaskStackLowRamLayoutAlgorithm;
-
- // The transform to place TaskViews at the front and back of the stack respectively
- TaskViewTransform mBackOfStackTransform = new TaskViewTransform();
- TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();
-
- public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
- mContext = context;
- mCb = cb;
- mTaskGridLayoutAlgorithm = new TaskGridLayoutAlgorithm(context);
- mTaskStackLowRamLayoutAlgorithm = new TaskStackLowRamLayoutAlgorithm(context);
- reloadOnConfigurationChange(context);
- }
-
- /**
- * Reloads the layout for the current configuration.
- */
- public void reloadOnConfigurationChange(Context context) {
- Resources res = context.getResources();
- mFocusedRange = new Range(res.getFloat(R.integer.recents_layout_focused_range_min),
- res.getFloat(R.integer.recents_layout_focused_range_max));
- mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
- res.getFloat(R.integer.recents_layout_unfocused_range_max));
- mFocusState = getInitialFocusState();
- mFocusedTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_layout_top_peek_size);
- mFocusedBottomPeekHeight =
- res.getDimensionPixelSize(R.dimen.recents_layout_bottom_peek_size);
- mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_layout_z_min);
- mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_layout_z_max);
- mBaseInitialTopOffset = getDimensionForDevice(context,
- R.dimen.recents_layout_initial_top_offset_phone_port,
- R.dimen.recents_layout_initial_top_offset_phone_land,
- R.dimen.recents_layout_initial_top_offset_tablet,
- R.dimen.recents_layout_initial_top_offset_tablet,
- R.dimen.recents_layout_initial_top_offset_tablet,
- R.dimen.recents_layout_initial_top_offset_tablet,
- R.dimen.recents_layout_initial_top_offset_tablet);
- mBaseInitialBottomOffset = getDimensionForDevice(context,
- R.dimen.recents_layout_initial_bottom_offset_phone_port,
- R.dimen.recents_layout_initial_bottom_offset_phone_land,
- R.dimen.recents_layout_initial_bottom_offset_tablet,
- R.dimen.recents_layout_initial_bottom_offset_tablet,
- R.dimen.recents_layout_initial_bottom_offset_tablet,
- R.dimen.recents_layout_initial_bottom_offset_tablet,
- R.dimen.recents_layout_initial_bottom_offset_tablet);
- mTaskGridLayoutAlgorithm.reloadOnConfigurationChange(context);
- mTaskStackLowRamLayoutAlgorithm.reloadOnConfigurationChange(context);
- mMinMargin = res.getDimensionPixelSize(R.dimen.recents_layout_min_margin);
- mBaseTopMargin = getDimensionForDevice(context,
- R.dimen.recents_layout_top_margin_phone,
- R.dimen.recents_layout_top_margin_tablet,
- R.dimen.recents_layout_top_margin_tablet_xlarge,
- R.dimen.recents_layout_top_margin_tablet);
- mBaseSideMargin = getDimensionForDevice(context,
- R.dimen.recents_layout_side_margin_phone,
- R.dimen.recents_layout_side_margin_tablet,
- R.dimen.recents_layout_side_margin_tablet_xlarge,
- R.dimen.recents_layout_side_margin_tablet);
- mBaseBottomMargin = res.getDimensionPixelSize(R.dimen.recents_layout_bottom_margin);
- mTitleBarHeight = getDimensionForDevice(mContext,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height_tablet_land,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height_tablet_land,
- R.dimen.recents_grid_task_view_header_height);
- }
-
- /**
- * Resets this layout when the stack view is reset.
- */
- public void reset() {
- mTaskIndexOverrideMap.clear();
- setFocusState(getInitialFocusState());
- }
-
- /**
- * Sets the system insets.
- */
- public boolean setSystemInsets(Rect systemInsets) {
- boolean changed = !mSystemInsets.equals(systemInsets);
- mSystemInsets.set(systemInsets);
- mTaskGridLayoutAlgorithm.setSystemInsets(systemInsets);
- mTaskStackLowRamLayoutAlgorithm.setSystemInsets(systemInsets);
- return changed;
- }
-
- /**
- * Sets the focused state.
- */
- public void setFocusState(int focusState) {
- int prevFocusState = mFocusState;
- mFocusState = focusState;
- updateFrontBackTransforms();
- if (mCb != null) {
- mCb.onFocusStateChanged(prevFocusState, focusState);
- }
- }
-
- /**
- * Gets the focused state.
- */
- public int getFocusState() {
- return mFocusState;
- }
-
- /**
- * Computes the stack and task rects. The given task stack bounds already has the top/right
- * insets and left/right padding already applied.
- */
- public void initialize(Rect displayRect, Rect windowRect, Rect taskStackBounds) {
- Rect lastStackRect = new Rect(mStackRect);
-
- int topMargin = getScaleForExtent(windowRect, displayRect, mBaseTopMargin, mMinMargin, HEIGHT);
- int bottomMargin = getScaleForExtent(windowRect, displayRect, mBaseBottomMargin, mMinMargin,
- HEIGHT);
- mInitialTopOffset = getScaleForExtent(windowRect, displayRect, mBaseInitialTopOffset,
- mMinMargin, HEIGHT);
- mInitialBottomOffset = mBaseInitialBottomOffset;
-
- // Compute the stack bounds
- mStackBottomOffset = mSystemInsets.bottom + bottomMargin;
- mStackRect.set(taskStackBounds);
- mStackRect.top += topMargin;
-
- // The stack action button will take the full un-padded header space above the stack
- mStackActionButtonRect.set(mStackRect.left, mStackRect.top - topMargin,
- mStackRect.right, mStackRect.top + mFocusedTopPeekHeight);
-
- // Anchor the task rect top aligned to the stack rect
- int height = mStackRect.height() - mInitialTopOffset - mStackBottomOffset;
- mTaskRect.set(mStackRect.left, mStackRect.top, mStackRect.right, mStackRect.top + height);
-
- if (mTaskRect.width() <= 0 || mTaskRect.height() <= 0) {
- // Logging for b/36654830
- Log.e(TAG, "Invalid task rect: taskRect=" + mTaskRect + " stackRect=" + mStackRect
- + " displayRect=" + displayRect + " windowRect=" + windowRect
- + " taskStackBounds=" + taskStackBounds);
- }
-
- // Short circuit here if the stack rects haven't changed so we don't do all the work below
- if (!lastStackRect.equals(mStackRect)) {
- // Reinitialize the focused and unfocused curves
- mUnfocusedCurve = constructUnfocusedCurve();
- mUnfocusedCurveInterpolator = new FreePathInterpolator(mUnfocusedCurve);
- mFocusedCurve = constructFocusedCurve();
- mFocusedCurveInterpolator = new FreePathInterpolator(mFocusedCurve);
- mUnfocusedDimCurve = constructUnfocusedDimCurve();
- mUnfocusedDimCurveInterpolator = new FreePathInterpolator(mUnfocusedDimCurve);
- mFocusedDimCurve = constructFocusedDimCurve();
- mFocusedDimCurveInterpolator = new FreePathInterpolator(mFocusedDimCurve);
-
- updateFrontBackTransforms();
- }
-
- // Initialize the grid layout
- mTaskGridLayoutAlgorithm.initialize(windowRect);
- mTaskStackLowRamLayoutAlgorithm.initialize(windowRect);
- }
-
- /**
- * Computes the minimum and maximum scroll progress values and the progress values for each task
- * in the stack.
- */
- public void update(TaskStack stack, ArraySet<Task.TaskKey> ignoreTasksSet,
- RecentsActivityLaunchState launchState, float lastScrollPPercent) {
- SystemServicesProxy ssp = Recents.getSystemServices();
-
- // Clear the progress map
- mTaskIndexMap.clear();
-
- // Return early if we have no tasks
- ArrayList<Task> tasks = stack.getTasks();
- if (tasks.isEmpty()) {
- mFrontMostTaskP = 0;
- mMinScrollP = mMaxScrollP = mInitialScrollP = 0;
- mNumStackTasks = 0;
- return;
- }
-
- // Filter the set of stack tasks
- ArrayList<Task> stackTasks = new ArrayList<>();
- for (int i = 0; i < tasks.size(); i++) {
- Task task = tasks.get(i);
- if (ignoreTasksSet.contains(task.key)) {
- continue;
- }
- stackTasks.add(task);
- }
- mNumStackTasks = stackTasks.size();
-
- // Put each of the tasks in the progress map at a fixed index (does not need to actually
- // map to a scroll position, just by index)
- int taskCount = stackTasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task task = stackTasks.get(i);
- mTaskIndexMap.put(task.key.id, i);
- }
-
- // Calculate the min/max/initial scroll
- Task launchTask = stack.getLaunchTarget();
- int launchTaskIndex = launchTask != null
- ? stack.indexOfTask(launchTask)
- : mNumStackTasks - 1;
- if (getInitialFocusState() == STATE_FOCUSED) {
- int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
- float maxBottomNormX = getNormalizedXFromFocusedY(maxBottomOffset, FROM_BOTTOM);
- mFocusedRange.offset(0f);
- mMinScrollP = 0;
- mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
- Math.max(0, mFocusedRange.getAbsoluteX(maxBottomNormX)));
- if (launchState.launchedFromHome || launchState.launchedFromPipApp
- || launchState.launchedWithNextPipApp) {
- mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- } else {
- mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
- }
- } else if (mNumStackTasks == 1) {
- // If there is one stack task, ignore the min/max/initial scroll positions
- mMinScrollP = 0;
- mMaxScrollP = 0;
- mInitialScrollP = 0;
- } else {
- // Set the max scroll to be the point where the front most task is visible with the
- // stack bottom offset
- int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
- float maxBottomNormX = getNormalizedXFromUnfocusedY(maxBottomOffset, FROM_BOTTOM);
- mUnfocusedRange.offset(0f);
- mMinScrollP = Recents.getConfiguration().isLowRamDevice
- ? mTaskStackLowRamLayoutAlgorithm.getMinScrollP()
- : 0;
- mMaxScrollP = Recents.getConfiguration().isLowRamDevice
- ? mTaskStackLowRamLayoutAlgorithm.getMaxScrollP(taskCount)
- : Math.max(mMinScrollP, (mNumStackTasks - 1) -
- Math.max(0, mUnfocusedRange.getAbsoluteX(maxBottomNormX)));
- boolean scrollToFront = launchState.launchedFromHome || launchState.launchedFromPipApp
- || launchState.launchedWithNextPipApp || launchState.launchedViaDockGesture;
-
- if (launchState.launchedWithAltTab) {
- mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- } else if (0 <= lastScrollPPercent && lastScrollPPercent <= 1) {
- mInitialScrollP = Utilities.mapRange(lastScrollPPercent, mMinScrollP, mMaxScrollP);
- } else if (Recents.getConfiguration().isLowRamDevice) {
- mInitialScrollP = mTaskStackLowRamLayoutAlgorithm.getInitialScrollP(mNumStackTasks,
- scrollToFront);
- } else if (scrollToFront) {
- mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
- } else {
- // We are overriding the initial two task positions, so set the initial scroll
- // position to match the second task (aka focused task) position
- float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
- mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2))
- - Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX)));
- }
- }
- }
-
- /**
- * Creates task overrides to ensure the initial stack layout if necessary.
- */
- public void setTaskOverridesForInitialState(TaskStack stack, boolean ignoreScrollToFront) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
-
- mTaskIndexOverrideMap.clear();
-
- boolean scrollToFront = launchState.launchedFromHome ||
- launchState.launchedFromPipApp ||
- launchState.launchedWithNextPipApp ||
- launchState.launchedViaDockGesture;
- if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
- if (ignoreScrollToFront || (!launchState.launchedWithAltTab && !scrollToFront)) {
- // Set the initial scroll to the predefined state (which differs from the stack)
- float [] initialNormX = null;
- float minBottomTaskNormX = getNormalizedXFromUnfocusedY(mSystemInsets.bottom +
- mInitialBottomOffset, FROM_BOTTOM);
- float maxBottomTaskNormX = getNormalizedXFromUnfocusedY(mFocusedTopPeekHeight +
- mTaskRect.height() - mMinMargin, FROM_TOP);
- if (mNumStackTasks <= 2) {
- // For small stacks, position the tasks so that they are top aligned to under
- // the action button, but ensure that it is at least a certain offset from the
- // bottom of the stack
- initialNormX = new float[] {
- Math.min(maxBottomTaskNormX, minBottomTaskNormX),
- getNormalizedXFromUnfocusedY(mFocusedTopPeekHeight, FROM_TOP)
- };
- } else {
- initialNormX = new float[] {
- minBottomTaskNormX,
- getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP)
- };
- }
-
- mUnfocusedRange.offset(0f);
- List<Task> tasks = stack.getTasks();
- int taskCount = tasks.size();
- for (int i = taskCount - 1; i >= 0; i--) {
- int indexFromFront = taskCount - i - 1;
- if (indexFromFront >= initialNormX.length) {
- break;
- }
- float newTaskProgress = mInitialScrollP +
- mUnfocusedRange.getAbsoluteX(initialNormX[indexFromFront]);
- mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress);
- }
- }
- }
- }
-
- /**
- * Adds and override task progress for the given task when transitioning from focused to
- * unfocused state.
- */
- public void addUnfocusedTaskOverride(Task task, float stackScroll) {
- if (mFocusState != STATE_UNFOCUSED) {
- mFocusedRange.offset(stackScroll);
- mUnfocusedRange.offset(stackScroll);
- float focusedRangeX = mFocusedRange.getNormalizedX(mTaskIndexMap.get(task.key.id));
- float focusedY = mFocusedCurveInterpolator.getInterpolation(focusedRangeX);
- float unfocusedRangeX = mUnfocusedCurveInterpolator.getX(focusedY);
- float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
- if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
- mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
- }
- }
- }
-
- /**
- * Adds and override task progress for the given task when transitioning from focused to
- * unfocused state.
- */
- public void addUnfocusedTaskOverride(TaskView taskView, float stackScroll) {
- mFocusedRange.offset(stackScroll);
- mUnfocusedRange.offset(stackScroll);
-
- Task task = taskView.getTask();
- int top = taskView.getTop() - mTaskRect.top;
- float focusedRangeX = getNormalizedXFromFocusedY(top, FROM_TOP);
- float unfocusedRangeX = getNormalizedXFromUnfocusedY(top, FROM_TOP);
- float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
- if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
- mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
- }
- }
-
- public void clearUnfocusedTaskOverrides() {
- mTaskIndexOverrideMap.clear();
- }
-
- /**
- * Updates this stack when a scroll happens.
- *
- */
- public float updateFocusStateOnScroll(float lastTargetStackScroll, float targetStackScroll,
- float lastStackScroll) {
- if (targetStackScroll == lastStackScroll || Recents.getConfiguration().isLowRamDevice) {
- return targetStackScroll;
- }
-
- float deltaScroll = targetStackScroll - lastStackScroll;
- float deltaTargetScroll = targetStackScroll - lastTargetStackScroll;
- float newScroll = targetStackScroll;
- mUnfocusedRange.offset(targetStackScroll);
- for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
- int taskId = mTaskIndexOverrideMap.keyAt(i);
- float x = mTaskIndexMap.get(taskId);
- float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
- float newOverrideX = overrideX + deltaScroll;
- if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
- // Remove the override once we reach the original task index
- mTaskIndexOverrideMap.removeAt(i);
- } else if ((overrideX >= x && deltaScroll <= 0f) ||
- (overrideX <= x && deltaScroll >= 0f)) {
- // Scrolling from override x towards x, then lock the task in place
- mTaskIndexOverrideMap.put(taskId, newOverrideX);
- } else {
- // Scrolling override x away from x, we should still move the scroll towards x
- newScroll = lastStackScroll;
- newOverrideX = overrideX - deltaTargetScroll;
- if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
- mTaskIndexOverrideMap.removeAt(i);
- } else{
- mTaskIndexOverrideMap.put(taskId, newOverrideX);
- }
- }
- }
- return newScroll;
- }
-
- private boolean isInvalidOverrideX(float x, float overrideX, float newOverrideX) {
- boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
- mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
- return outOfBounds || (overrideX >= x && x >= newOverrideX) ||
- (overrideX <= x && x <= newOverrideX);
- }
-
- /**
- * Returns the default focus state.
- */
- public int getInitialFocusState() {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- if (launchState.launchedWithAltTab) {
- return STATE_FOCUSED;
- } else {
- return STATE_UNFOCUSED;
- }
- }
-
- public Rect getStackActionButtonRect() {
- return useGridLayout()
- ? mTaskGridLayoutAlgorithm.getStackActionButtonRect() : mStackActionButtonRect;
- }
-
- /**
- * Returns the TaskViewTransform that would put the task just off the back of the stack.
- */
- public TaskViewTransform getBackOfStackTransform() {
- return mBackOfStackTransform;
- }
-
- /**
- * Returns the TaskViewTransform that would put the task just off the front of the stack.
- */
- public TaskViewTransform getFrontOfStackTransform() {
- return mFrontOfStackTransform;
- }
-
- /**
- * Returns whether this stack layout has been initialized.
- */
- public boolean isInitialized() {
- return !mStackRect.isEmpty();
- }
-
- /**
- * Computes the maximum number of visible tasks and thumbnails when the scroll is at the initial
- * stack scroll. Requires that update() is called first.
- */
- public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
- if (useGridLayout()) {
- return mTaskGridLayoutAlgorithm.computeStackVisibilityReport(tasks);
- }
-
- if (Recents.getConfiguration().isLowRamDevice) {
- return mTaskStackLowRamLayoutAlgorithm.computeStackVisibilityReport(tasks);
- }
-
- // Ensure minimum visibility count
- if (tasks.size() <= 1) {
- return new VisibilityReport(1, 1);
- }
-
- // Otherwise, walk backwards in the stack and count the number of tasks and visible
- // thumbnails and add that to the total task count
- TaskViewTransform tmpTransform = new TaskViewTransform();
- Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
- currentRange.offset(mInitialScrollP);
- int taskBarHeight = mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_task_view_header_height);
- int numVisibleTasks = 0;
- int numVisibleThumbnails = 0;
- float prevScreenY = Integer.MAX_VALUE;
- for (int i = tasks.size() - 1; i >= 0; i--) {
- Task task = tasks.get(i);
-
- // Skip invisible
- float taskProgress = getStackScrollForTask(task);
- if (!currentRange.isInRange(taskProgress)) {
- continue;
- }
-
- getStackTransform(taskProgress, taskProgress, mInitialScrollP, mFocusState,
- tmpTransform, null, false /* ignoreSingleTaskCase */, false /* forceUpdate */);
- float screenY = tmpTransform.rect.top;
- boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
- if (hasVisibleThumbnail) {
- numVisibleThumbnails++;
- numVisibleTasks++;
- prevScreenY = screenY;
- } else {
- // Once we hit the next front most task that does not have a visible thumbnail,
- // walk through remaining visible set
- for (int j = i; j >= 0; j--) {
- taskProgress = getStackScrollForTask(tasks.get(j));
- if (!currentRange.isInRange(taskProgress)) {
- break;
- }
- numVisibleTasks++;
- }
- break;
- }
- }
- return new VisibilityReport(numVisibleTasks, numVisibleThumbnails);
- }
-
- /**
- * Returns the transform for the given task. This transform is relative to the mTaskRect, which
- * is what the view is measured and laid out with.
- */
- public TaskViewTransform getStackTransform(Task task, float stackScroll,
- TaskViewTransform transformOut, TaskViewTransform frontTransform) {
- return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
- false /* forceUpdate */, false /* ignoreTaskOverrides */);
- }
-
- public TaskViewTransform getStackTransform(Task task, float stackScroll,
- TaskViewTransform transformOut, TaskViewTransform frontTransform,
- boolean ignoreTaskOverrides) {
- return getStackTransform(task, stackScroll, mFocusState, transformOut, frontTransform,
- false /* forceUpdate */, ignoreTaskOverrides);
- }
-
- public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
- TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate,
- boolean ignoreTaskOverrides) {
- if (useGridLayout()) {
- int taskIndex = mTaskIndexMap.get(task.key.id);
- int taskCount = mTaskIndexMap.size();
- mTaskGridLayoutAlgorithm.getTransform(taskIndex, taskCount, transformOut, this);
- return transformOut;
- } else if (Recents.getConfiguration().isLowRamDevice) {
- if (task == null) {
- transformOut.reset();
- return transformOut;
- }
- int taskIndex = mTaskIndexMap.get(task.key.id);
- mTaskStackLowRamLayoutAlgorithm.getTransform(taskIndex, stackScroll, transformOut,
- mNumStackTasks, this);
- return transformOut;
- } else {
- // Return early if we have an invalid index
- int nonOverrideTaskProgress = mTaskIndexMap.get(task.key.id, -1);
- if (task == null || nonOverrideTaskProgress == -1) {
- transformOut.reset();
- return transformOut;
- }
- float taskProgress = ignoreTaskOverrides
- ? nonOverrideTaskProgress
- : getStackScrollForTask(task);
-
- getStackTransform(taskProgress, nonOverrideTaskProgress, stackScroll, focusState,
- transformOut, frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
- return transformOut;
- }
- }
-
- /**
- * Like {@link #getStackTransform}, but in screen coordinates
- */
- public TaskViewTransform getStackTransformScreenCoordinates(Task task, float stackScroll,
- TaskViewTransform transformOut, TaskViewTransform frontTransform,
- Rect windowOverrideRect) {
- TaskViewTransform transform = getStackTransform(task, stackScroll, mFocusState,
- transformOut, frontTransform, true /* forceUpdate */,
- false /* ignoreTaskOverrides */);
- return transformToScreenCoordinates(transform, windowOverrideRect);
- }
-
- /**
- * Transforms the given {@param transformOut} to the screen coordinates, overriding the current
- * window rectangle with {@param windowOverrideRect} if non-null.
- */
- TaskViewTransform transformToScreenCoordinates(TaskViewTransform transformOut,
- Rect windowOverrideRect) {
- Rect windowRect = windowOverrideRect != null
- ? windowOverrideRect
- : Recents.getSystemServices().getWindowRect();
- transformOut.rect.offset(windowRect.left, windowRect.top);
- if (useGridLayout()) {
- // Draw the thumbnail a little lower to perfectly coincide with the view we are
- // transitioning to, where the header bar has already been drawn.
- transformOut.rect.offset(0, mTitleBarHeight);
- }
- return transformOut;
- }
-
- /**
- * Update/get the transform.
- *
- * @param ignoreSingleTaskCase When set, will ensure that the transform computed does not take
- * into account the special single-task case. This is only used
- * internally to ensure that we can calculate the transform for any
- * position in the stack.
- */
- public void getStackTransform(float taskProgress, float nonOverrideTaskProgress,
- float stackScroll, int focusState, TaskViewTransform transformOut,
- TaskViewTransform frontTransform, boolean ignoreSingleTaskCase, boolean forceUpdate) {
- SystemServicesProxy ssp = Recents.getSystemServices();
-
- // Ensure that the task is in range
- mUnfocusedRange.offset(stackScroll);
- mFocusedRange.offset(stackScroll);
- boolean unfocusedVisible = mUnfocusedRange.isInRange(taskProgress);
- boolean focusedVisible = mFocusedRange.isInRange(taskProgress);
-
- // Skip if the task is not visible
- if (!forceUpdate && !unfocusedVisible && !focusedVisible) {
- transformOut.reset();
- return;
- }
-
- // Map the absolute task progress to the normalized x at the stack scroll. We use this to
- // calculate positions along the curve.
- mUnfocusedRange.offset(stackScroll);
- mFocusedRange.offset(stackScroll);
- float unfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
- float focusedRangeX = mFocusedRange.getNormalizedX(taskProgress);
-
- // Map the absolute task progress to the normalized x at the bounded stack scroll. We use
- // this to calculate bounded properties, like translationZ and outline alpha.
- float boundedStackScroll = Utilities.clamp(stackScroll, mMinScrollP, mMaxScrollP);
- mUnfocusedRange.offset(boundedStackScroll);
- mFocusedRange.offset(boundedStackScroll);
- float boundedScrollUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
- float boundedScrollUnfocusedNonOverrideRangeX =
- mUnfocusedRange.getNormalizedX(nonOverrideTaskProgress);
-
- // Map the absolute task progress to the normalized x at the upper bounded stack scroll.
- // We use this to calculate the dim, which is bounded only on one end.
- float lowerBoundedStackScroll = Utilities.clamp(stackScroll, -Float.MAX_VALUE, mMaxScrollP);
- mUnfocusedRange.offset(lowerBoundedStackScroll);
- mFocusedRange.offset(lowerBoundedStackScroll);
- float lowerBoundedUnfocusedRangeX = mUnfocusedRange.getNormalizedX(taskProgress);
- float lowerBoundedFocusedRangeX = mFocusedRange.getNormalizedX(taskProgress);
-
- int x = (mStackRect.width() - mTaskRect.width()) / 2;
- int y;
- float z;
- float dimAlpha;
- float viewOutlineAlpha;
- if (mNumStackTasks == 1 && !ignoreSingleTaskCase) {
- // When there is exactly one task, then decouple the task from the stack and just move
- // in screen space
- float tmpP = (mMinScrollP - stackScroll) / mNumStackTasks;
- int centerYOffset = (mStackRect.top - mTaskRect.top) +
- (mStackRect.height() - mSystemInsets.bottom - mTaskRect.height()) / 2;
- y = centerYOffset + getYForDeltaP(tmpP, 0);
- z = mMaxTranslationZ;
- dimAlpha = 0f;
- viewOutlineAlpha = OUTLINE_ALPHA_MIN_VALUE +
- (OUTLINE_ALPHA_MAX_VALUE - OUTLINE_ALPHA_MIN_VALUE) / 2f;
-
- } else {
- // Otherwise, update the task to the stack layout
- int unfocusedY = (int) ((1f - mUnfocusedCurveInterpolator.getInterpolation(
- unfocusedRangeX)) * mStackRect.height());
- int focusedY = (int) ((1f - mFocusedCurveInterpolator.getInterpolation(
- focusedRangeX)) * mStackRect.height());
- float unfocusedDim = mUnfocusedDimCurveInterpolator.getInterpolation(
- lowerBoundedUnfocusedRangeX);
- float focusedDim = mFocusedDimCurveInterpolator.getInterpolation(
- lowerBoundedFocusedRangeX);
-
- // Special case, because we override the initial task positions differently for small
- // stacks, we clamp the dim to 0 in the initial position, and then only modulate the
- // dim when the task is scrolled back towards the top of the screen
- if (mNumStackTasks <= 2 && nonOverrideTaskProgress == 0f) {
- if (boundedScrollUnfocusedRangeX >= 0.5f) {
- unfocusedDim = 0f;
- } else {
- float offset = mUnfocusedDimCurveInterpolator.getInterpolation(0.5f);
- unfocusedDim -= offset;
- unfocusedDim *= MAX_DIM / (MAX_DIM - offset);
- }
- }
- y = (mStackRect.top - mTaskRect.top) +
- (int) Utilities.mapRange(focusState, unfocusedY, focusedY);
- z = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedNonOverrideRangeX),
- mMinTranslationZ, mMaxTranslationZ);
- dimAlpha = Utilities.mapRange(focusState, unfocusedDim, focusedDim);
- viewOutlineAlpha = Utilities.mapRange(Utilities.clamp01(boundedScrollUnfocusedRangeX),
- OUTLINE_ALPHA_MIN_VALUE, OUTLINE_ALPHA_MAX_VALUE);
- }
-
- // Fill out the transform
- transformOut.scale = 1f;
- transformOut.alpha = 1f;
- transformOut.translationZ = z;
- transformOut.dimAlpha = dimAlpha;
- transformOut.viewOutlineAlpha = viewOutlineAlpha;
- transformOut.rect.set(mTaskRect);
- transformOut.rect.offset(x, y);
- Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
- transformOut.visible = (transformOut.rect.top < mStackRect.bottom) &&
- (frontTransform == null || transformOut.rect.top != frontTransform.rect.top);
- }
-
- /**
- * Returns the untransformed task view bounds.
- */
- public Rect getUntransformedTaskViewBounds() {
- return new Rect(mTaskRect);
- }
-
- /**
- * Returns the scroll progress to scroll to such that the top of the task is at the top of the
- * stack.
- */
- float getStackScrollForTask(Task t) {
- Float overrideP = mTaskIndexOverrideMap.get(t.key.id, null);
- if (Recents.getConfiguration().isLowRamDevice || overrideP == null) {
- return (float) mTaskIndexMap.get(t.key.id, 0);
- }
- return overrideP;
- }
-
- /**
- * Returns the original scroll progress to scroll to such that the top of the task is at the top
- * of the stack.
- */
- float getStackScrollForTaskIgnoreOverrides(Task t) {
- return (float) mTaskIndexMap.get(t.key.id, 0);
- }
-
- /**
- * Returns the scroll progress to scroll to such that the top of the task at the initial top
- * offset (which is at the task's brightest point).
- */
- float getStackScrollForTaskAtInitialOffset(Task t) {
- if (Recents.getConfiguration().isLowRamDevice) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- return mTaskStackLowRamLayoutAlgorithm.getInitialScrollP(mNumStackTasks,
- launchState.launchedFromHome || launchState.launchedFromPipApp
- || launchState.launchedWithNextPipApp);
- }
- float normX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
- mUnfocusedRange.offset(0f);
- return Utilities.clamp((float) mTaskIndexMap.get(t.key.id, 0) - Math.max(0,
- mUnfocusedRange.getAbsoluteX(normX)), mMinScrollP, mMaxScrollP);
- }
-
- /**
- * Maps a movement in screen y, relative to {@param downY}, to a movement in along the arc
- * length of the curve. We know the curve is mostly flat, so we just map the length of the
- * screen along the arc-length proportionally (1/arclength).
- */
- public float getDeltaPForY(int downY, int y) {
- if (Recents.getConfiguration().isLowRamDevice) {
- return mTaskStackLowRamLayoutAlgorithm.scrollToPercentage(downY - y);
- }
- float deltaP = (float) (y - downY) / mStackRect.height() *
- mUnfocusedCurveInterpolator.getArcLength();
- return -deltaP;
- }
-
- /**
- * This is the inverse of {@link #getDeltaPForY}. Given a movement along the arc length
- * of the curve, map back to the screen y.
- */
- public int getYForDeltaP(float downScrollP, float p) {
- if (Recents.getConfiguration().isLowRamDevice) {
- return mTaskStackLowRamLayoutAlgorithm.percentageToScroll(downScrollP - p);
- }
- int y = (int) ((p - downScrollP) * mStackRect.height() *
- (1f / mUnfocusedCurveInterpolator.getArcLength()));
- return -y;
- }
-
- /**
- * Returns the task stack bounds in the current orientation. This rect takes into account the
- * top and right system insets (but not the bottom inset) and left/right paddings, but _not_
- * the top/bottom padding or insets.
- */
- public void getTaskStackBounds(Rect displayRect, Rect windowRect, int topInset, int leftInset,
- int rightInset, Rect taskStackBounds) {
- taskStackBounds.set(windowRect.left + leftInset, windowRect.top + topInset,
- windowRect.right - rightInset, windowRect.bottom);
-
- // Ensure that the new width is at most the smaller display edge size
- int sideMargin = getScaleForExtent(windowRect, displayRect, mBaseSideMargin, mMinMargin,
- WIDTH);
- int targetStackWidth = taskStackBounds.width() - 2 * sideMargin;
- if (Utilities.getAppConfiguration(mContext).orientation
- == Configuration.ORIENTATION_LANDSCAPE) {
- // If we are in landscape, calculate the width of the stack in portrait and ensure that
- // we are not larger than that size
- Rect portraitDisplayRect = new Rect(0, 0,
- Math.min(displayRect.width(), displayRect.height()),
- Math.max(displayRect.width(), displayRect.height()));
- int portraitSideMargin = getScaleForExtent(portraitDisplayRect, portraitDisplayRect,
- mBaseSideMargin, mMinMargin, WIDTH);
- targetStackWidth = Math.min(targetStackWidth,
- portraitDisplayRect.width() - 2 * portraitSideMargin);
- }
- taskStackBounds.inset((taskStackBounds.width() - targetStackWidth) / 2, 0);
- }
-
- /**
- * Retrieves resources that are constant regardless of the current configuration of the device.
- */
- public static int getDimensionForDevice(Context ctx, int phoneResId,
- int tabletResId, int xlargeTabletResId, int gridLayoutResId) {
- return getDimensionForDevice(ctx, phoneResId, phoneResId, tabletResId, tabletResId,
- xlargeTabletResId, xlargeTabletResId, gridLayoutResId);
- }
-
- /**
- * Retrieves resources that are constant regardless of the current configuration of the device.
- */
- public static int getDimensionForDevice(Context ctx, int phonePortResId, int phoneLandResId,
- int tabletPortResId, int tabletLandResId, int xlargeTabletPortResId,
- int xlargeTabletLandResId, int gridLayoutResId) {
- RecentsConfiguration config = Recents.getConfiguration();
- Resources res = ctx.getResources();
- boolean isLandscape = Utilities.getAppConfiguration(ctx).orientation ==
- Configuration.ORIENTATION_LANDSCAPE;
- if (config.isGridEnabled) {
- return res.getDimensionPixelSize(gridLayoutResId);
- } else if (config.isXLargeScreen) {
- return res.getDimensionPixelSize(isLandscape
- ? xlargeTabletLandResId
- : xlargeTabletPortResId);
- } else if (config.isLargeScreen) {
- return res.getDimensionPixelSize(isLandscape
- ? tabletLandResId
- : tabletPortResId);
- } else {
- return res.getDimensionPixelSize(isLandscape
- ? phoneLandResId
- : phonePortResId);
- }
- }
-
- /**
- * Returns the normalized x on the unfocused curve given an absolute Y position (relative to the
- * stack height).
- */
- private float getNormalizedXFromUnfocusedY(float y, @AnchorSide int fromSide) {
- float offset = (fromSide == FROM_TOP)
- ? mStackRect.height() - y
- : y;
- float offsetPct = offset / mStackRect.height();
- return mUnfocusedCurveInterpolator.getX(offsetPct);
- }
-
- /**
- * Returns the normalized x on the focused curve given an absolute Y position (relative to the
- * stack height).
- */
- private float getNormalizedXFromFocusedY(float y, @AnchorSide int fromSide) {
- float offset = (fromSide == FROM_TOP)
- ? mStackRect.height() - y
- : y;
- float offsetPct = offset / mStackRect.height();
- return mFocusedCurveInterpolator.getX(offsetPct);
- }
-
- /**
- * Creates a new path for the focused curve.
- */
- private Path constructFocusedCurve() {
- // Initialize the focused curve. This curve is a piecewise curve composed of several
- // linear pieces that goes from (0,1) through (0.5, peek height offset),
- // (0.5, bottom task offsets), and (1,0).
- float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
- float bottomPeekHeightPct = (float) (mStackBottomOffset + mFocusedBottomPeekHeight) /
- mStackRect.height();
- float minBottomPeekHeightPct = (float) (mFocusedTopPeekHeight + mTaskRect.height() -
- mMinMargin) / mStackRect.height();
- Path p = new Path();
- p.moveTo(0f, 1f);
- p.lineTo(0.5f, 1f - topPeekHeightPct);
- p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), Math.max(1f - minBottomPeekHeightPct,
- bottomPeekHeightPct));
- p.lineTo(1f, 0f);
- return p;
- }
-
- /**
- * Creates a new path for the unfocused curve.
- */
- private Path constructUnfocusedCurve() {
- // Initialize the unfocused curve. This curve is a piecewise curve composed of two quadradic
- // beziers that goes from (0,1) through (0.5, peek height offset) and ends at (1,0). This
- // ensures that we match the range, at which 0.5 represents the stack scroll at the current
- // task progress. Because the height offset can change depending on a resource, we compute
- // the control point of the second bezier such that between it and a first known point,
- // there is a tangent at (0.5, peek height offset).
- float cpoint1X = 0.4f;
- float cpoint1Y = 0.975f;
- float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
- float slope = ((1f - topPeekHeightPct) - cpoint1Y) / (0.5f - cpoint1X);
- float b = 1f - slope * cpoint1X;
- float cpoint2X = 0.65f;
- float cpoint2Y = slope * cpoint2X + b;
- Path p = new Path();
- p.moveTo(0f, 1f);
- p.cubicTo(0f, 1f, cpoint1X, cpoint1Y, 0.5f, 1f - topPeekHeightPct);
- p.cubicTo(0.5f, 1f - topPeekHeightPct, cpoint2X, cpoint2Y, 1f, 0f);
- return p;
- }
-
- /**
- * Creates a new path for the focused dim curve.
- */
- private Path constructFocusedDimCurve() {
- Path p = new Path();
- // The focused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
- // task), then goes back to max dim at the next task
- p.moveTo(0f, MAX_DIM);
- p.lineTo(0.5f, 0f);
- p.lineTo(0.5f + (0.5f / mFocusedRange.relativeMax), MAX_DIM);
- p.lineTo(1f, MAX_DIM);
- return p;
- }
-
- /**
- * Creates a new path for the unfocused dim curve.
- */
- private Path constructUnfocusedDimCurve() {
- float focusX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
- float cpoint2X = focusX + (1f - focusX) / 2;
- Path p = new Path();
- // The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
- // task), then goes back to max dim towards the front of the stack
- p.moveTo(0f, MAX_DIM);
- p.cubicTo(focusX * 0.5f, MAX_DIM, focusX * 0.75f, MAX_DIM * 0.75f, focusX, 0f);
- p.cubicTo(cpoint2X, 0f, cpoint2X, MED_DIM, 1f, MED_DIM);
- return p;
- }
-
- /**
- * Scales the given {@param value} to the scale of the {@param instance} rect relative to the
- * {@param other} rect in the {@param extent} side.
- */
- private int getScaleForExtent(Rect instance, Rect other, int value, int minValue,
- @Extent int extent) {
- if (extent == WIDTH) {
- float scale = Utilities.clamp01((float) instance.width() / other.width());
- return Math.max(minValue, (int) (scale * value));
- } else if (extent == HEIGHT) {
- float scale = Utilities.clamp01((float) instance.height() / other.height());
- return Math.max(minValue, (int) (scale * value));
- }
- return value;
- }
-
- /**
- * Updates the current transforms that would put a TaskView at the front and back of the stack.
- */
- private void updateFrontBackTransforms() {
- // Return early if we have not yet initialized
- if (mStackRect.isEmpty()) {
- return;
- }
- if (Recents.getConfiguration().isLowRamDevice) {
- mTaskStackLowRamLayoutAlgorithm.getBackOfStackTransform(mBackOfStackTransform, this);
- mTaskStackLowRamLayoutAlgorithm.getFrontOfStackTransform(mFrontOfStackTransform, this);
- return;
- }
-
- float min = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMin,
- mFocusedRange.relativeMin);
- float max = Utilities.mapRange(mFocusState, mUnfocusedRange.relativeMax,
- mFocusedRange.relativeMax);
- getStackTransform(min, min, 0f, mFocusState, mBackOfStackTransform, null,
- true /* ignoreSingleTaskCase */, true /* forceUpdate */);
- getStackTransform(max, max, 0f, mFocusState, mFrontOfStackTransform, null,
- true /* ignoreSingleTaskCase */, true /* forceUpdate */);
- mBackOfStackTransform.visible = true;
- mFrontOfStackTransform.visible = true;
- }
-
- /**
- * Returns the proper task rectangle according to the current grid state.
- */
- public Rect getTaskRect() {
- if (Recents.getConfiguration().isLowRamDevice) {
- return mTaskStackLowRamLayoutAlgorithm.getTaskRect();
- }
- return useGridLayout() ? mTaskGridLayoutAlgorithm.getTaskGridRect() : mTaskRect;
- }
-
- public void dump(String prefix, PrintWriter writer) {
- String innerPrefix = prefix + " ";
-
- writer.print(prefix); writer.print(TAG);
- writer.write(" numStackTasks="); writer.print(mNumStackTasks);
- writer.println();
-
- writer.print(innerPrefix);
- writer.print("insets="); writer.print(Utilities.dumpRect(mSystemInsets));
- writer.print(" stack="); writer.print(Utilities.dumpRect(mStackRect));
- writer.print(" task="); writer.print(Utilities.dumpRect(mTaskRect));
- writer.print(" actionButton="); writer.print(Utilities.dumpRect(mStackActionButtonRect));
- writer.println();
-
- writer.print(innerPrefix);
- writer.print("minScroll="); writer.print(mMinScrollP);
- writer.print(" maxScroll="); writer.print(mMaxScrollP);
- writer.print(" initialScroll="); writer.print(mInitialScrollP);
- writer.println();
-
- writer.print(innerPrefix);
- writer.print("focusState="); writer.print(mFocusState);
- writer.println();
-
- if (mTaskIndexOverrideMap.size() > 0) {
- for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
- int taskId = mTaskIndexOverrideMap.keyAt(i);
- float x = mTaskIndexMap.get(taskId);
- float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
-
- writer.print(innerPrefix);
- writer.print("taskId= "); writer.print(taskId);
- writer.print(" x= "); writer.print(x);
- writer.print(" overrideX= "); writer.print(overrideX);
- writer.println();
- }
- }
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
deleted file mode 100644
index 89288d8..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ /dev/null
@@ -1,2286 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.annotation.IntDef;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.MutableBoolean;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.widget.FrameLayout;
-import android.widget.ScrollView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivity;
-import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.RecentsDebugFlags;
-import com.android.systemui.recents.RecentsImpl;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
-import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
-import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
-import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
-import com.android.systemui.recents.events.activity.LaunchMostRecentTaskRequestEvent;
-import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskEvent;
-import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
-import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
-import com.android.systemui.recents.events.activity.PackagesChangedEvent;
-import com.android.systemui.recents.events.activity.ShowEmptyViewEvent;
-import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
-import com.android.systemui.recents.events.component.ActivityPinnedEvent;
-import com.android.systemui.recents.events.component.ExpandPipEvent;
-import com.android.systemui.recents.events.component.HidePipMenuEvent;
-import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
-import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
-import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
-import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
-import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
-import com.android.systemui.recents.events.ui.RecentsGrowingEvent;
-import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
-import com.android.systemui.recents.events.ui.UserInteractionEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
-import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent;
-import com.android.systemui.recents.misc.DozeTrigger;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.recents.views.grid.GridTaskView;
-import com.android.systemui.recents.views.grid.TaskGridLayoutAlgorithm;
-import com.android.systemui.recents.views.grid.TaskViewFocusFrame;
-
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import java.io.PrintWriter;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
-
-
-/* The visual representation of a task stack view */
-public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
- TaskView.TaskViewCallbacks, TaskStackViewScroller.TaskStackViewScrollerCallbacks,
- TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks,
- ViewPool.ViewPoolConsumer<TaskView, Task> {
-
- private static final String TAG = "TaskStackView";
-
- // The thresholds at which to show/hide the stack action button.
- private static final float SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
- private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
-
- public static final int DEFAULT_SYNC_STACK_DURATION = 200;
- public static final int SLOW_SYNC_STACK_DURATION = 250;
- private static final int DRAG_SCALE_DURATION = 175;
- static final float DRAG_SCALE_FACTOR = 1.05f;
-
- private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 216;
- private static final int LAUNCH_NEXT_SCROLL_INCR_DURATION = 32;
-
- // The actions to perform when resetting to initial state,
- @Retention(RetentionPolicy.SOURCE)
- @IntDef({INITIAL_STATE_UPDATE_NONE, INITIAL_STATE_UPDATE_ALL, INITIAL_STATE_UPDATE_LAYOUT_ONLY})
- public @interface InitialStateAction {}
- /** Do not update the stack and layout to the initial state. */
- private static final int INITIAL_STATE_UPDATE_NONE = 0;
- /** Update both the stack and layout to the initial state. */
- private static final int INITIAL_STATE_UPDATE_ALL = 1;
- /** Update only the layout to the initial state. */
- private static final int INITIAL_STATE_UPDATE_LAYOUT_ONLY = 2;
-
- private LayoutInflater mInflater;
- private TaskStack mStack = new TaskStack();
- @ViewDebug.ExportedProperty(deepExport=true, prefix="layout_")
- TaskStackLayoutAlgorithm mLayoutAlgorithm;
- // The stable layout algorithm is only used to calculate the task rect with the stable bounds
- private TaskStackLayoutAlgorithm mStableLayoutAlgorithm;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="scroller_")
- private TaskStackViewScroller mStackScroller;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="touch_")
- private TaskStackViewTouchHandler mTouchHandler;
- private TaskStackAnimationHelper mAnimationHelper;
- private ViewPool<TaskView, Task> mViewPool;
-
- private ArrayList<TaskView> mTaskViews = new ArrayList<>();
- private ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
- private ArraySet<Task.TaskKey> mIgnoreTasks = new ArraySet<>();
- private AnimationProps mDeferredTaskViewLayoutAnimation = null;
-
- @ViewDebug.ExportedProperty(deepExport=true, prefix="doze_")
- private DozeTrigger mUIDozeTrigger;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="focused_task_")
- private Task mFocusedTask;
-
- private int mTaskCornerRadiusPx;
- private int mDividerSize;
- private int mStartTimerIndicatorDuration;
-
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mTaskViewsClipDirty = true;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mEnterAnimationComplete = false;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mStackReloaded = false;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mFinishedLayoutAfterStackReload = false;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mLaunchNextAfterFirstMeasure = false;
- @ViewDebug.ExportedProperty(category="recents")
- @InitialStateAction
- private int mInitialState = INITIAL_STATE_UPDATE_ALL;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mInMeasureLayout = false;
- @ViewDebug.ExportedProperty(category="recents")
- boolean mTouchExplorationEnabled;
- @ViewDebug.ExportedProperty(category="recents")
- boolean mScreenPinningEnabled;
-
- // The stable stack bounds are the full bounds that we were measured with from RecentsView
- @ViewDebug.ExportedProperty(category="recents")
- private Rect mStableStackBounds = new Rect();
- // The current stack bounds are dynamic and may change as the user drags and drops
- @ViewDebug.ExportedProperty(category="recents")
- private Rect mStackBounds = new Rect();
- // The current window bounds at the point we were measured
- @ViewDebug.ExportedProperty(category="recents")
- private Rect mStableWindowRect = new Rect();
- // The current window bounds are dynamic and may change as the user drags and drops
- @ViewDebug.ExportedProperty(category="recents")
- private Rect mWindowRect = new Rect();
- // The current display bounds
- @ViewDebug.ExportedProperty(category="recents")
- private Rect mDisplayRect = new Rect();
- // The current display orientation
- @ViewDebug.ExportedProperty(category="recents")
- private int mDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
-
- private Rect mTmpRect = new Rect();
- private ArrayMap<Task.TaskKey, TaskView> mTmpTaskViewMap = new ArrayMap<>();
- private List<TaskView> mTmpTaskViews = new ArrayList<>();
- private TaskViewTransform mTmpTransform = new TaskViewTransform();
- private int[] mTmpIntPair = new int[2];
- private boolean mResetToInitialStateWhenResized;
- private int mLastWidth;
- private int mLastHeight;
- private boolean mStackActionButtonVisible;
-
- // Percentage of last ScrollP from the min to max scrollP that lives after configuration changes
- private float mLastScrollPPercent = -1;
-
- // We keep track of the task view focused by user interaction and draw a frame around it in the
- // grid layout.
- private TaskViewFocusFrame mTaskViewFocusFrame;
-
- private Task mPrefetchingTask;
- private final float mFastFlingVelocity;
-
- // A convenience update listener to request updating clipping of tasks
- private ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener =
- new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- if (!mTaskViewsClipDirty) {
- mTaskViewsClipDirty = true;
- invalidate();
- }
- }
- };
-
- private DropTarget mStackDropTarget = new DropTarget() {
- @Override
- public boolean acceptsDrop(int x, int y, int width, int height, Rect insets,
- boolean isCurrentTarget) {
- // This drop target has a fixed bounds and should be checked last, so just fall through
- // if it is the current target
- if (!isCurrentTarget) {
- return mLayoutAlgorithm.mStackRect.contains(x, y);
- }
- return false;
- }
- };
-
- public TaskStackView(Context context) {
- super(context);
- SystemServicesProxy ssp = Recents.getSystemServices();
- Resources res = context.getResources();
-
- // Set the stack first
- mStack.setCallbacks(this);
- mViewPool = new ViewPool<>(context, this);
- mInflater = LayoutInflater.from(context);
- mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
- mStableLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, null);
- mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
- mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
- mAnimationHelper = new TaskStackAnimationHelper(context, this);
- mTaskCornerRadiusPx = Recents.getConfiguration().isGridEnabled ?
- res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
- res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
- mFastFlingVelocity = res.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
- mDividerSize = ssp.getDockedDividerSize(context);
- mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
- mDisplayRect = ssp.getDisplayRect();
- mStackActionButtonVisible = false;
-
- // Create a frame to draw around the focused task view
- if (Recents.getConfiguration().isGridEnabled) {
- mTaskViewFocusFrame = new TaskViewFocusFrame(mContext, this,
- mLayoutAlgorithm.mTaskGridLayoutAlgorithm);
- addView(mTaskViewFocusFrame);
- getViewTreeObserver().addOnGlobalFocusChangeListener(mTaskViewFocusFrame);
- }
-
- int taskBarDismissDozeDelaySeconds = getResources().getInteger(
- R.integer.recents_task_bar_dismiss_delay_seconds);
- mUIDozeTrigger = new DozeTrigger(taskBarDismissDozeDelaySeconds, new Runnable() {
- @Override
- public void run() {
- // Show the task bar dismiss buttons
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- tv.startNoUserInteractionAnimation();
- }
- }
- });
- setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
-
- @Override
- protected void onAttachedToWindow() {
- EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
- super.onAttachedToWindow();
- readSystemFlags();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- EventBus.getDefault().unregister(this);
- }
-
- /**
- * Called from RecentsActivity when it is relaunched.
- */
- void onReload(boolean isResumingFromVisible) {
- if (!isResumingFromVisible) {
- // Reset the focused task
- resetFocusedTask(getFocusedTask());
- }
-
- // Reset the state of each of the task views
- List<TaskView> taskViews = new ArrayList<>();
- taskViews.addAll(getTaskViews());
- taskViews.addAll(mViewPool.getViews());
- for (int i = taskViews.size() - 1; i >= 0; i--) {
- taskViews.get(i).onReload(isResumingFromVisible);
- }
-
- // Reset the stack state
- readSystemFlags();
- mTaskViewsClipDirty = true;
- mUIDozeTrigger.stopDozing();
- if (!isResumingFromVisible) {
- mStackScroller.reset();
- mStableLayoutAlgorithm.reset();
- mLayoutAlgorithm.reset();
- mLastScrollPPercent = -1;
- }
-
- // Since we always animate to the same place in (the initial state), always reset the stack
- // to the initial state when resuming
- mStackReloaded = true;
- mFinishedLayoutAfterStackReload = false;
- mLaunchNextAfterFirstMeasure = false;
- mInitialState = INITIAL_STATE_UPDATE_ALL;
- requestLayout();
- }
-
- /**
- * Sets the stack tasks of this TaskStackView from the given TaskStack.
- */
- public void setTasks(TaskStack stack, boolean allowNotifyStackChanges) {
- boolean isInitialized = mLayoutAlgorithm.isInitialized();
-
- // Only notify if we are already initialized, otherwise, everything will pick up all the
- // new and old tasks when we next layout
- mStack.setTasks(stack, allowNotifyStackChanges && isInitialized);
- }
-
- /** Returns the task stack. */
- public TaskStack getStack() {
- return mStack;
- }
-
- /**
- * Updates this TaskStackView to the initial state.
- */
- public void updateToInitialState() {
- mStackScroller.setStackScrollToInitialState();
- mLayoutAlgorithm.setTaskOverridesForInitialState(mStack, false /* ignoreScrollToFront */);
- }
-
- /** Updates the list of task views */
- void updateTaskViewsList() {
- mTaskViews.clear();
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View v = getChildAt(i);
- if (v instanceof TaskView) {
- mTaskViews.add((TaskView) v);
- }
- }
- }
-
- /** Gets the list of task views */
- List<TaskView> getTaskViews() {
- return mTaskViews;
- }
-
- /**
- * Returns the front most task view.
- */
- private TaskView getFrontMostTaskView() {
- List<TaskView> taskViews = getTaskViews();
- if (taskViews.isEmpty()) {
- return null;
- }
- return taskViews.get(taskViews.size() - 1);
- }
-
- /**
- * Finds the child view given a specific {@param task}.
- */
- public TaskView getChildViewForTask(Task t) {
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- if (tv.getTask() == t) {
- return tv;
- }
- }
- return null;
- }
-
- /** Returns the stack algorithm for this task stack. */
- public TaskStackLayoutAlgorithm getStackAlgorithm() {
- return mLayoutAlgorithm;
- }
-
- /** Returns the grid algorithm for this task stack. */
- public TaskGridLayoutAlgorithm getGridAlgorithm() {
- return mLayoutAlgorithm.mTaskGridLayoutAlgorithm;
- }
-
- /**
- * Returns the touch handler for this task stack.
- */
- public TaskStackViewTouchHandler getTouchHandler() {
- return mTouchHandler;
- }
-
- /**
- * Adds a task to the ignored set.
- */
- void addIgnoreTask(Task task) {
- mIgnoreTasks.add(task.key);
- }
-
- /**
- * Removes a task from the ignored set.
- */
- void removeIgnoreTask(Task task) {
- mIgnoreTasks.remove(task.key);
- }
-
- /**
- * Returns whether the specified {@param task} is ignored.
- */
- boolean isIgnoredTask(Task task) {
- return mIgnoreTasks.contains(task.key);
- }
-
- /**
- * Computes the task transforms at the current stack scroll for all visible tasks. If a valid
- * target stack scroll is provided (ie. is different than {@param curStackScroll}), then the
- * visible range includes all tasks at the target stack scroll. This is useful for ensure that
- * all views necessary for a transition or animation will be visible at the start.
- *
- * @param taskTransforms The set of task view transforms to reuse, this list will be sized to
- * match the size of {@param tasks}
- * @param tasks The set of tasks for which to generate transforms
- * @param curStackScroll The current stack scroll
- * @param targetStackScroll The stack scroll that we anticipate we are going to be scrolling to.
- * The range of the union of the visible views at the current and
- * target stack scrolls will be returned.
- * @param ignoreTasksSet The set of tasks to skip for purposes of calculaing the visible range.
- * Transforms will still be calculated for the ignore tasks.
- * @return the front and back most visible task indices (there may be non visible tasks in
- * between this range)
- */
- int[] computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
- ArrayList<Task> tasks, float curStackScroll, float targetStackScroll,
- ArraySet<Task.TaskKey> ignoreTasksSet, boolean ignoreTaskOverrides) {
- int taskCount = tasks.size();
- int[] visibleTaskRange = mTmpIntPair;
- visibleTaskRange[0] = -1;
- visibleTaskRange[1] = -1;
- boolean useTargetStackScroll = Float.compare(curStackScroll, targetStackScroll) != 0;
-
- // We can reuse the task transforms where possible to reduce object allocation
- matchTaskListSize(tasks, taskTransforms);
-
- // Update the stack transforms
- TaskViewTransform frontTransform = null;
- TaskViewTransform frontTransformAtTarget = null;
- TaskViewTransform transform = null;
- TaskViewTransform transformAtTarget = null;
- for (int i = taskCount - 1; i >= 0; i--) {
- Task task = tasks.get(i);
-
- // Calculate the current and (if necessary) the target transform for the task
- transform = mLayoutAlgorithm.getStackTransform(task, curStackScroll,
- taskTransforms.get(i), frontTransform, ignoreTaskOverrides);
- if (useTargetStackScroll && !transform.visible) {
- // If we have a target stack scroll and the task is not currently visible, then we
- // just update the transform at the new scroll
- // TODO: Optimize this
- transformAtTarget = mLayoutAlgorithm.getStackTransform(task, targetStackScroll,
- new TaskViewTransform(), frontTransformAtTarget);
- if (transformAtTarget.visible) {
- transform.copyFrom(transformAtTarget);
- }
- }
-
- // For ignore tasks, only calculate the stack transform and skip the calculation of the
- // visible stack indices
- if (ignoreTasksSet.contains(task.key)) {
- continue;
- }
-
- frontTransform = transform;
- frontTransformAtTarget = transformAtTarget;
- if (transform.visible) {
- if (visibleTaskRange[0] < 0) {
- visibleTaskRange[0] = i;
- }
- visibleTaskRange[1] = i;
- }
- }
- return visibleTaskRange;
- }
-
- /**
- * Binds the visible {@link TaskView}s at the given target scroll.
- */
- void bindVisibleTaskViews(float targetStackScroll) {
- bindVisibleTaskViews(targetStackScroll, false /* ignoreTaskOverrides */);
- }
-
- /**
- * Synchronizes the set of children {@link TaskView}s to match the visible set of tasks in the
- * current {@link TaskStack}. This call does not continue on to update their position to the
- * computed {@link TaskViewTransform}s of the visible range, but only ensures that they will
- * be added/removed from the view hierarchy and placed in the correct Z order and initial
- * position (if not currently on screen).
- *
- * @param targetStackScroll If provided, will ensure that the set of visible {@link TaskView}s
- * includes those visible at the current stack scroll, and all at the
- * target stack scroll.
- * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
- * tasks at their non-overridden task progress
- */
- void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
- // Get all the task transforms
- ArrayList<Task> tasks = mStack.getTasks();
- int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
- mStackScroller.getStackScroll(), targetStackScroll, mIgnoreTasks,
- ignoreTaskOverrides);
-
- // Return all the invisible children to the pool
- mTmpTaskViewMap.clear();
- List<TaskView> taskViews = getTaskViews();
- int lastFocusedTaskIndex = -1;
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- // Skip ignored tasks
- if (mIgnoreTasks.contains(task.key)) {
- continue;
- }
-
- // It is possible for the set of lingering TaskViews to differ from the stack if the
- // stack was updated before the relayout. If the task view is no longer in the stack,
- // then just return it back to the view pool.
- int taskIndex = mStack.indexOfTask(task);
- TaskViewTransform transform = null;
- if (taskIndex != -1) {
- transform = mCurrentTaskTransforms.get(taskIndex);
- }
-
- if (transform != null && transform.visible) {
- mTmpTaskViewMap.put(task.key, tv);
- } else {
- if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) {
- lastFocusedTaskIndex = taskIndex;
- resetFocusedTask(task);
- }
- mViewPool.returnViewToPool(tv);
- }
- }
-
- // Pick up all the newly visible children
- for (int i = tasks.size() - 1; i >= 0; i--) {
- Task task = tasks.get(i);
- TaskViewTransform transform = mCurrentTaskTransforms.get(i);
-
- // Skip ignored tasks
- if (mIgnoreTasks.contains(task.key)) {
- continue;
- }
-
- // Skip the invisible stack tasks
- if (!transform.visible) {
- continue;
- }
-
- TaskView tv = mTmpTaskViewMap.get(task.key);
- if (tv == null) {
- tv = mViewPool.pickUpViewFromPool(task, task);
- if (transform.rect.top <= mLayoutAlgorithm.mStackRect.top) {
- updateTaskViewToTransform(tv, mLayoutAlgorithm.getBackOfStackTransform(),
- AnimationProps.IMMEDIATE);
- } else {
- updateTaskViewToTransform(tv, mLayoutAlgorithm.getFrontOfStackTransform(),
- AnimationProps.IMMEDIATE);
- }
- } else {
- // Reattach it in the right z order
- final int taskIndex = mStack.indexOfTask(task);
- final int insertIndex = findTaskViewInsertIndex(task, taskIndex);
- if (insertIndex != getTaskViews().indexOf(tv)){
- detachViewFromParent(tv);
- attachViewToParent(tv, insertIndex, tv.getLayoutParams());
- updateTaskViewsList();
- }
- }
- }
-
- updatePrefetchingTask(tasks, visibleTaskRange[0], visibleTaskRange[1]);
-
- // Update the focus if the previous focused task was returned to the view pool
- if (lastFocusedTaskIndex != -1) {
- int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1])
- ? visibleTaskRange[1]
- : visibleTaskRange[0];
- setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */,
- true /* requestViewFocus */);
- TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
- if (focusedTaskView != null) {
- focusedTaskView.requestAccessibilityFocus();
- }
- }
- }
-
- /**
- * @see #relayoutTaskViews(AnimationProps, ArrayMap<Task, AnimationProps>, boolean)
- */
- public void relayoutTaskViews(AnimationProps animation) {
- relayoutTaskViews(animation, null /* animationOverrides */,
- false /* ignoreTaskOverrides */);
- }
-
- /**
- * Relayout the the visible {@link TaskView}s to their current transforms as specified by the
- * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
- * animations that are current running on those task views, and will ensure that the children
- * {@link TaskView}s will match the set of visible tasks in the stack. If a {@link Task} has
- * an animation provided in {@param animationOverrides}, that will be used instead.
- */
- private void relayoutTaskViews(AnimationProps animation,
- ArrayMap<Task, AnimationProps> animationOverrides, boolean ignoreTaskOverrides) {
- // If we had a deferred animation, cancel that
- cancelDeferredTaskViewLayoutAnimation();
-
- // Synchronize the current set of TaskViews
- bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTaskOverrides);
-
- // Animate them to their final transforms with the given animation
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- if (mIgnoreTasks.contains(task.key)) {
- continue;
- }
-
- int taskIndex = mStack.indexOfTask(task);
- TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
- if (animationOverrides != null && animationOverrides.containsKey(task)) {
- animation = animationOverrides.get(task);
- }
-
- updateTaskViewToTransform(tv, transform, animation);
- }
- }
-
- /**
- * Posts an update to synchronize the {@link TaskView}s with the stack on the next frame.
- */
- void relayoutTaskViewsOnNextFrame(AnimationProps animation) {
- mDeferredTaskViewLayoutAnimation = animation;
- invalidate();
- }
-
- /**
- * Called to update a specific {@link TaskView} to a given {@link TaskViewTransform} with a
- * given set of {@link AnimationProps} properties.
- */
- public void updateTaskViewToTransform(TaskView taskView, TaskViewTransform transform,
- AnimationProps animation) {
- if (taskView.isAnimatingTo(transform)) {
- return;
- }
- taskView.cancelTransformAnimation();
- taskView.updateViewPropertiesToTaskTransform(transform, animation,
- mRequestUpdateClippingListener);
- }
-
- /**
- * Returns the current task transforms of all tasks, falling back to the stack layout if there
- * is no {@link TaskView} for the task.
- */
- public void getCurrentTaskTransforms(ArrayList<Task> tasks,
- ArrayList<TaskViewTransform> transformsOut) {
- matchTaskListSize(tasks, transformsOut);
- int focusState = mLayoutAlgorithm.getFocusState();
- for (int i = tasks.size() - 1; i >= 0; i--) {
- Task task = tasks.get(i);
- TaskViewTransform transform = transformsOut.get(i);
- TaskView tv = getChildViewForTask(task);
- if (tv != null) {
- transform.fillIn(tv);
- } else {
- mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
- focusState, transform, null, true /* forceUpdate */,
- false /* ignoreTaskOverrides */);
- }
- transform.visible = true;
- }
- }
-
- /**
- * Returns the task transforms for all the tasks in the stack if the stack was at the given
- * {@param stackScroll} and {@param focusState}.
- */
- public void getLayoutTaskTransforms(float stackScroll, int focusState, ArrayList<Task> tasks,
- boolean ignoreTaskOverrides, ArrayList<TaskViewTransform> transformsOut) {
- matchTaskListSize(tasks, transformsOut);
- for (int i = tasks.size() - 1; i >= 0; i--) {
- Task task = tasks.get(i);
- TaskViewTransform transform = transformsOut.get(i);
- mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
- true /* forceUpdate */, ignoreTaskOverrides);
- transform.visible = true;
- }
- }
-
- /**
- * Cancels the next deferred task view layout.
- */
- void cancelDeferredTaskViewLayoutAnimation() {
- mDeferredTaskViewLayoutAnimation = null;
- }
-
- /**
- * Cancels all {@link TaskView} animations.
- */
- void cancelAllTaskViewAnimations() {
- List<TaskView> taskViews = getTaskViews();
- for (int i = taskViews.size() - 1; i >= 0; i--) {
- final TaskView tv = taskViews.get(i);
- if (!mIgnoreTasks.contains(tv.getTask().key)) {
- tv.cancelTransformAnimation();
- }
- }
- }
-
- /**
- * Updates the clip for each of the task views from back to front.
- */
- private void clipTaskViews() {
- // We never clip task views in grid layout
- if (Recents.getConfiguration().isGridEnabled) {
- return;
- }
-
- // Update the clip on each task child
- List<TaskView> taskViews = getTaskViews();
- TaskView tmpTv = null;
- TaskView prevVisibleTv = null;
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- TaskView frontTv = null;
- int clipBottom = 0;
-
- if (isIgnoredTask(tv.getTask())) {
- // For each of the ignore tasks, update the translationZ of its TaskView to be
- // between the translationZ of the tasks immediately underneath it
- if (prevVisibleTv != null) {
- tv.setTranslationZ(Math.max(tv.getTranslationZ(),
- prevVisibleTv.getTranslationZ() + 0.1f));
- }
- }
-
- if (i < (taskViewCount - 1) && tv.shouldClipViewInStack()) {
- // Find the next view to clip against
- for (int j = i + 1; j < taskViewCount; j++) {
- tmpTv = taskViews.get(j);
-
- if (tmpTv.shouldClipViewInStack()) {
- frontTv = tmpTv;
- break;
- }
- }
-
- // Clip against the next view, this is just an approximation since we are
- // stacked and we can make assumptions about the visibility of the this
- // task relative to the ones in front of it.
- if (frontTv != null) {
- float taskBottom = tv.getBottom();
- float frontTaskTop = frontTv.getTop();
- if (frontTaskTop < taskBottom) {
- // Map the stack view space coordinate (the rects) to view space
- clipBottom = (int) (taskBottom - frontTaskTop) - mTaskCornerRadiusPx;
- }
- }
- }
- tv.getViewBounds().setClipBottom(clipBottom);
- tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
- prevVisibleTv = tv;
- }
- mTaskViewsClipDirty = false;
- }
-
- public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
- updateLayoutAlgorithm(boundScrollToNewMinMax, Recents.getConfiguration().getLaunchState());
- }
-
- /**
- * Updates the layout algorithm min and max virtual scroll bounds.
- */
- public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
- RecentsActivityLaunchState launchState) {
- // Compute the min and max scroll values
- mLayoutAlgorithm.update(mStack, mIgnoreTasks, launchState, mLastScrollPPercent);
-
- if (boundScrollToNewMinMax) {
- mStackScroller.boundScroll();
- }
- }
-
- /**
- * Updates the stack layout to its stable places.
- */
- private void updateLayoutToStableBounds() {
- mWindowRect.set(mStableWindowRect);
- mStackBounds.set(mStableStackBounds);
- mLayoutAlgorithm.setSystemInsets(mStableLayoutAlgorithm.mSystemInsets);
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds);
- updateLayoutAlgorithm(true /* boundScroll */);
- }
-
- /** Returns the scroller. */
- public TaskStackViewScroller getScroller() {
- return mStackScroller;
- }
-
- /**
- * Sets the focused task to the provided (bounded taskIndex).
- *
- * @return whether or not the stack will scroll as a part of this focus change
- */
- public boolean setFocusedTask(int taskIndex, boolean scrollToTask,
- final boolean requestViewFocus) {
- return setFocusedTask(taskIndex, scrollToTask, requestViewFocus, 0);
- }
-
- /**
- * Sets the focused task to the provided (bounded focusTaskIndex).
- *
- * @return whether or not the stack will scroll as a part of this focus change
- */
- public boolean setFocusedTask(int focusTaskIndex, boolean scrollToTask,
- boolean requestViewFocus, int timerIndicatorDuration) {
- // Find the next task to focus
- int newFocusedTaskIndex = mStack.getTaskCount() > 0 ?
- Utilities.clamp(focusTaskIndex, 0, mStack.getTaskCount() - 1) : -1;
- final Task newFocusedTask = (newFocusedTaskIndex != -1) ?
- mStack.getTasks().get(newFocusedTaskIndex) : null;
-
- // Reset the last focused task state if changed
- if (mFocusedTask != null) {
- // Cancel the timer indicator, if applicable
- if (timerIndicatorDuration > 0) {
- final TaskView tv = getChildViewForTask(mFocusedTask);
- if (tv != null) {
- tv.getHeaderView().cancelFocusTimerIndicator();
- }
- }
-
- resetFocusedTask(mFocusedTask);
- }
-
- boolean willScroll = false;
- mFocusedTask = newFocusedTask;
-
- if (newFocusedTask != null) {
- // Start the timer indicator, if applicable
- if (timerIndicatorDuration > 0) {
- final TaskView tv = getChildViewForTask(mFocusedTask);
- if (tv != null) {
- tv.getHeaderView().startFocusTimerIndicator(timerIndicatorDuration);
- } else {
- // The view is null; set a flag for later
- mStartTimerIndicatorDuration = timerIndicatorDuration;
- }
- }
-
- if (scrollToTask) {
- // Cancel any running enter animations at this point when we scroll or change focus
- if (!mEnterAnimationComplete) {
- cancelAllTaskViewAnimations();
- }
-
- mLayoutAlgorithm.clearUnfocusedTaskOverrides();
- willScroll = mAnimationHelper.startScrollToFocusedTaskAnimation(newFocusedTask,
- requestViewFocus);
- if (willScroll) {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
- }
- } else {
- // Focus the task view
- TaskView newFocusedTaskView = getChildViewForTask(newFocusedTask);
- if (newFocusedTaskView != null) {
- newFocusedTaskView.setFocusedState(true, requestViewFocus);
- }
- }
- // Any time a task view gets the focus, we move the focus frame around it.
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.moveGridTaskViewFocus(getChildViewForTask(newFocusedTask));
- }
- }
- return willScroll;
- }
-
- /**
- * Sets the focused task relative to the currently focused task.
- *
- * @param forward whether to go to the next task in the stack (along the curve) or the previous
- * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
- * if the currently focused task is not a stack task, will set the focus
- * to the first visible stack task
- * @param animated determines whether to actually draw the highlight along with the change in
- * focus.
- */
- public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) {
- setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0);
- }
-
- /**
- * Sets the focused task relative to the currently focused task.
- *
- * @param forward whether to go to the next task in the stack (along the curve) or the previous
- * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
- * if the currently focused task is not a stack task, will set the focus
- * to the first visible stack task
- * @param animated determines whether to actually draw the highlight along with the change in
- * focus.
- * @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll
- * happens.
- * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator
- */
- public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
- boolean cancelWindowAnimations, int timerIndicatorDuration) {
- Task focusedTask = getFocusedTask();
- int newIndex = mStack.indexOfTask(focusedTask);
- if (focusedTask != null) {
- if (stackTasksOnly) {
- List<Task> tasks = mStack.getTasks();
- // Try the next task if it is a stack task
- int tmpNewIndex = newIndex + (forward ? -1 : 1);
- if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
- newIndex = tmpNewIndex;
- }
- } else {
- // No restrictions, lets just move to the new task (looping forward/backwards if
- // necessary)
- int taskCount = mStack.getTaskCount();
- newIndex = (newIndex + (forward ? -1 : 1) + taskCount) % taskCount;
- }
- } else {
- // We don't have a focused task
- float stackScroll = mStackScroller.getStackScroll();
- ArrayList<Task> tasks = mStack.getTasks();
- int taskCount = tasks.size();
- if (useGridLayout()) {
- // For the grid layout, we directly set focus to the most recently used task
- // no matter we're moving forwards or backwards.
- newIndex = taskCount - 1;
- } else {
- // For the grid layout we pick a proper task to focus, according to the current
- // stack scroll.
- if (forward) {
- // Walk backwards and focus the next task smaller than the current stack scroll
- for (newIndex = taskCount - 1; newIndex >= 0; newIndex--) {
- float taskP = mLayoutAlgorithm.getStackScrollForTask(tasks.get(newIndex));
- if (Float.compare(taskP, stackScroll) <= 0) {
- break;
- }
- }
- } else {
- // Walk forwards and focus the next task larger than the current stack scroll
- for (newIndex = 0; newIndex < taskCount; newIndex++) {
- float taskP = mLayoutAlgorithm.getStackScrollForTask(tasks.get(newIndex));
- if (Float.compare(taskP, stackScroll) >= 0) {
- break;
- }
- }
- }
- }
- }
- if (newIndex != -1) {
- boolean willScroll = setFocusedTask(newIndex, true /* scrollToTask */,
- true /* requestViewFocus */, timerIndicatorDuration);
- if (willScroll && cancelWindowAnimations) {
- // As we iterate to the next/previous task, cancel any current/lagging window
- // transition animations
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
- }
- }
- }
-
- /**
- * Resets the focused task.
- */
- public void resetFocusedTask(Task task) {
- if (task != null) {
- TaskView tv = getChildViewForTask(task);
- if (tv != null) {
- tv.setFocusedState(false, false /* requestViewFocus */);
- }
- }
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.moveGridTaskViewFocus(null);
- }
- mFocusedTask = null;
- }
-
- /**
- * Returns the focused task.
- */
- public Task getFocusedTask() {
- return mFocusedTask;
- }
-
- /**
- * Returns the accessibility focused task.
- */
- Task getAccessibilityFocusedTask() {
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- if (Utilities.isDescendentAccessibilityFocused(tv)) {
- return tv.getTask();
- }
- }
- TaskView frontTv = getFrontMostTaskView();
- if (frontTv != null) {
- return frontTv.getTask();
- }
- return null;
- }
-
- @Override
- public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
- super.onInitializeAccessibilityEvent(event);
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- if (taskViewCount > 0) {
- TaskView backMostTask = taskViews.get(0);
- TaskView frontMostTask = taskViews.get(taskViewCount - 1);
- event.setFromIndex(mStack.indexOfTask(backMostTask.getTask()));
- event.setToIndex(mStack.indexOfTask(frontMostTask.getTask()));
- event.setContentDescription(frontMostTask.getTask().title);
- }
- event.setItemCount(mStack.getTaskCount());
-
- int stackHeight = mLayoutAlgorithm.mStackRect.height();
- event.setScrollY((int) (mStackScroller.getStackScroll() * stackHeight));
- event.setMaxScrollY((int) (mLayoutAlgorithm.mMaxScrollP * stackHeight));
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(info);
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- if (taskViewCount > 1) {
- // Find the accessibility focused task
- Task focusedTask = getAccessibilityFocusedTask();
- info.setScrollable(true);
- int focusedTaskIndex = mStack.indexOfTask(focusedTask);
- if (focusedTaskIndex > 0 || !mStackActionButtonVisible) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
- }
- if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
- }
- }
- }
-
- @Override
- public CharSequence getAccessibilityClassName() {
- return ScrollView.class.getName();
- }
-
- @Override
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- if (super.performAccessibilityAction(action, arguments)) {
- return true;
- }
- Task focusedTask = getAccessibilityFocusedTask();
- int taskIndex = mStack.indexOfTask(focusedTask);
- if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
- switch (action) {
- case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
- setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */,
- 0);
- return true;
- }
- case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
- setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */,
- 0);
- return true;
- }
- }
- }
- return false;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- return mTouchHandler.onInterceptTouchEvent(ev);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return mTouchHandler.onTouchEvent(ev);
- }
-
- @Override
- public boolean onGenericMotionEvent(MotionEvent ev) {
- return mTouchHandler.onGenericMotionEvent(ev);
- }
-
- @Override
- public void computeScroll() {
- if (mStackScroller.computeScroll()) {
- // Notify accessibility
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
- Recents.getTaskLoader().getHighResThumbnailLoader().setFlingingFast(
- mStackScroller.getScrollVelocity() > mFastFlingVelocity);
- }
- if (mDeferredTaskViewLayoutAnimation != null) {
- relayoutTaskViews(mDeferredTaskViewLayoutAnimation);
- mTaskViewsClipDirty = true;
- mDeferredTaskViewLayoutAnimation = null;
- }
- if (mTaskViewsClipDirty) {
- clipTaskViews();
- }
- mLastScrollPPercent = Utilities.clamp(Utilities.unmapRange(mStackScroller.getStackScroll(),
- mLayoutAlgorithm.mMinScrollP, mLayoutAlgorithm.mMaxScrollP), 0, 1);
- }
-
- /**
- * Computes the maximum number of visible tasks and thumbnails. Requires that
- * updateLayoutForStack() is called first.
- */
- public TaskStackLayoutAlgorithm.VisibilityReport computeStackVisibilityReport() {
- return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getTasks());
- }
-
- /**
- * Updates the system insets.
- */
- public void setSystemInsets(Rect systemInsets) {
- boolean changed = false;
- changed |= mStableLayoutAlgorithm.setSystemInsets(systemInsets);
- changed |= mLayoutAlgorithm.setSystemInsets(systemInsets);
- if (changed) {
- requestLayout();
- }
- }
-
- /**
- * This is called with the full window width and height to allow stack view children to
- * perform the full screen transition down.
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mInMeasureLayout = true;
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
-
- // Update the stable stack bounds, but only update the current stack bounds if the stable
- // bounds have changed. This is because we may get spurious measures while dragging where
- // our current stack bounds reflect the target drop region.
- mLayoutAlgorithm.getTaskStackBounds(mDisplayRect, new Rect(0, 0, width, height),
- mLayoutAlgorithm.mSystemInsets.top, mLayoutAlgorithm.mSystemInsets.left,
- mLayoutAlgorithm.mSystemInsets.right, mTmpRect);
- if (!mTmpRect.equals(mStableStackBounds)) {
- mStableStackBounds.set(mTmpRect);
- mStackBounds.set(mTmpRect);
- mStableWindowRect.set(0, 0, width, height);
- mWindowRect.set(0, 0, width, height);
- }
-
- // Compute the rects in the stack algorithm
- mStableLayoutAlgorithm.initialize(mDisplayRect, mStableWindowRect, mStableStackBounds);
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds);
- updateLayoutAlgorithm(false /* boundScroll */);
-
- // If this is the first layout, then scroll to the front of the stack, then update the
- // TaskViews with the stack so that we can lay them out
- boolean resetToInitialState = (width != mLastWidth || height != mLastHeight)
- && mResetToInitialStateWhenResized;
- if (!mFinishedLayoutAfterStackReload || mInitialState != INITIAL_STATE_UPDATE_NONE
- || resetToInitialState) {
- if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY || resetToInitialState) {
- updateToInitialState();
- mResetToInitialStateWhenResized = false;
- }
- if (mFinishedLayoutAfterStackReload) {
- mInitialState = INITIAL_STATE_UPDATE_NONE;
- }
- }
- // If we got the launch-next event before the first layout pass, then re-send it after the
- // initial state has been updated
- if (mLaunchNextAfterFirstMeasure) {
- mLaunchNextAfterFirstMeasure = false;
- EventBus.getDefault().post(new LaunchNextTaskRequestEvent());
- }
-
- // Rebind all the views, including the ignore ones
- bindVisibleTaskViews(mStackScroller.getStackScroll(), false /* ignoreTaskOverrides */);
-
- // Measure each of the TaskViews
- mTmpTaskViews.clear();
- mTmpTaskViews.addAll(getTaskViews());
- mTmpTaskViews.addAll(mViewPool.getViews());
- int taskViewCount = mTmpTaskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- measureTaskView(mTmpTaskViews.get(i));
- }
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.measure();
- }
-
- setMeasuredDimension(width, height);
- mLastWidth = width;
- mLastHeight = height;
- mInMeasureLayout = false;
- }
-
- /**
- * Measures a TaskView.
- */
- private void measureTaskView(TaskView tv) {
- Rect padding = new Rect();
- if (tv.getBackground() != null) {
- tv.getBackground().getPadding(padding);
- }
- mTmpRect.set(mStableLayoutAlgorithm.getTaskRect());
- mTmpRect.union(mLayoutAlgorithm.getTaskRect());
- tv.measure(
- MeasureSpec.makeMeasureSpec(mTmpRect.width() + padding.left + padding.right,
- MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(mTmpRect.height() + padding.top + padding.bottom,
- MeasureSpec.EXACTLY));
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- // Layout each of the TaskViews
- mTmpTaskViews.clear();
- mTmpTaskViews.addAll(getTaskViews());
- mTmpTaskViews.addAll(mViewPool.getViews());
- int taskViewCount = mTmpTaskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- layoutTaskView(changed, mTmpTaskViews.get(i));
- }
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.layout();
- }
-
- if (changed) {
- if (mStackScroller.isScrollOutOfBounds()) {
- mStackScroller.boundScroll();
- }
- }
-
- // Relayout all of the task views including the ignored ones
- relayoutTaskViews(AnimationProps.IMMEDIATE);
- clipTaskViews();
-
- if (!mFinishedLayoutAfterStackReload) {
- // Prepare the task enter animations (this can be called numerous times)
- mInitialState = INITIAL_STATE_UPDATE_NONE;
- onFirstLayout();
-
- if (mStackReloaded) {
- mFinishedLayoutAfterStackReload = true;
- tryStartEnterAnimation();
- }
- }
- }
-
- /**
- * Lays out a TaskView.
- */
- private void layoutTaskView(boolean changed, TaskView tv) {
- if (changed) {
- Rect padding = new Rect();
- if (tv.getBackground() != null) {
- tv.getBackground().getPadding(padding);
- }
- mTmpRect.set(mStableLayoutAlgorithm.getTaskRect());
- mTmpRect.union(mLayoutAlgorithm.getTaskRect());
- tv.cancelTransformAnimation();
- tv.layout(mTmpRect.left - padding.left, mTmpRect.top - padding.top,
- mTmpRect.right + padding.right, mTmpRect.bottom + padding.bottom);
- } else {
- // If the layout has not changed, then just lay it out again in-place
- tv.layout(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
- }
- }
-
- /** Handler for the first layout. */
- void onFirstLayout() {
- // Setup the view for the enter animation
- mAnimationHelper.prepareForEnterAnimation();
-
- // Set the task focused state without requesting view focus, and leave the focus animations
- // until after the enter-animation
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
-
- // We set the initial focused task view iff the following conditions are satisfied:
- // 1. Recents is showing task views in stack layout.
- // 2. Recents is launched with ALT + TAB.
- boolean setFocusOnFirstLayout = !useGridLayout() || launchState.launchedWithAltTab;
- if (setFocusOnFirstLayout) {
- int focusedTaskIndex = getInitialFocusTaskIndex(launchState, mStack.getTaskCount(),
- useGridLayout());
- if (focusedTaskIndex != -1) {
- setFocusedTask(focusedTaskIndex, false /* scrollToTask */,
- false /* requestViewFocus */);
- }
- }
- updateStackActionButtonVisibility();
- }
-
- public boolean isTouchPointInView(float x, float y, TaskView tv) {
- mTmpRect.set(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
- mTmpRect.offset((int) tv.getTranslationX(), (int) tv.getTranslationY());
- return mTmpRect.contains((int) x, (int) y);
- }
-
- /**
- * Returns a non-ignored task in the {@param tasks} list that can be used as an achor when
- * calculating the scroll position before and after a layout change.
- */
- public Task findAnchorTask(List<Task> tasks, MutableBoolean isFrontMostTask) {
- for (int i = tasks.size() - 1; i >= 0; i--) {
- Task task = tasks.get(i);
-
- // Ignore deleting tasks
- if (isIgnoredTask(task)) {
- if (i == tasks.size() - 1) {
- isFrontMostTask.value = true;
- }
- continue;
- }
- return task;
- }
- return null;
- }
-
- /**** TaskStackCallbacks Implementation ****/
-
- @Override
- public void onStackTaskAdded(TaskStack stack, Task newTask) {
- // Update the min/max scroll and animate other task views into their new positions
- updateLayoutAlgorithm(true /* boundScroll */);
-
- // Animate all the tasks into place
- relayoutTaskViews(!mFinishedLayoutAfterStackReload
- ? AnimationProps.IMMEDIATE
- : new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN));
- }
-
- /**
- * We expect that the {@link TaskView} associated with the removed task is already hidden.
- */
- @Override
- public void onStackTaskRemoved(TaskStack stack, Task removedTask, Task newFrontMostTask,
- AnimationProps animation, boolean fromDockGesture, boolean dismissRecentsIfAllRemoved) {
- if (mFocusedTask == removedTask) {
- resetFocusedTask(removedTask);
- }
-
- // Remove the view associated with this task, we can't rely on updateTransforms
- // to work here because the task is no longer in the list
- TaskView tv = getChildViewForTask(removedTask);
- if (tv != null) {
- mViewPool.returnViewToPool(tv);
- }
-
- // Remove the task from the ignored set
- removeIgnoreTask(removedTask);
-
- // If requested, relayout with the given animation
- if (animation != null) {
- updateLayoutAlgorithm(true /* boundScroll */);
- relayoutTaskViews(animation);
- }
-
- // Update the new front most task's action button
- if (mScreenPinningEnabled && newFrontMostTask != null) {
- TaskView frontTv = getChildViewForTask(newFrontMostTask);
- if (frontTv != null) {
- frontTv.showActionButton(true /* fadeIn */, DEFAULT_SYNC_STACK_DURATION);
- }
- }
-
- // If there are no remaining tasks, then just close recents
- if (mStack.getTaskCount() == 0) {
- if (dismissRecentsIfAllRemoved) {
- EventBus.getDefault().send(new AllTaskViewsDismissedEvent(fromDockGesture
- ? R.string.recents_empty_message
- : R.string.recents_empty_message_dismissed_all));
- } else {
- EventBus.getDefault().send(new ShowEmptyViewEvent());
- }
- }
- }
-
- @Override
- public void onStackTasksRemoved(TaskStack stack) {
- // Reset the focused task
- resetFocusedTask(getFocusedTask());
-
- // Return all the views to the pool
- List<TaskView> taskViews = new ArrayList<>();
- taskViews.addAll(getTaskViews());
- for (int i = taskViews.size() - 1; i >= 0; i--) {
- mViewPool.returnViewToPool(taskViews.get(i));
- }
-
- // Remove all the ignore tasks
- mIgnoreTasks.clear();
-
- // If there are no remaining tasks, then just close recents
- EventBus.getDefault().send(new AllTaskViewsDismissedEvent(
- R.string.recents_empty_message_dismissed_all));
- }
-
- @Override
- public void onStackTasksUpdated(TaskStack stack) {
- if (!mFinishedLayoutAfterStackReload) {
- return;
- }
-
- // Update the layout and immediately layout
- updateLayoutAlgorithm(false /* boundScroll */);
- relayoutTaskViews(AnimationProps.IMMEDIATE);
-
- // Rebind all the task views. This will not trigger new resources to be loaded
- // unless they have actually changed
- List<TaskView> taskViews = getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- bindTaskView(tv, tv.getTask());
- }
- }
-
- /**** ViewPoolConsumer Implementation ****/
-
- @Override
- public TaskView createView(Context context) {
- if (Recents.getConfiguration().isGridEnabled) {
- return (GridTaskView) mInflater.inflate(R.layout.recents_grid_task_view, this, false);
- } else {
- return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
- }
- }
-
- @Override
- public void onReturnViewToPool(TaskView tv) {
- final Task task = tv.getTask();
-
- // Unbind the task from the task view
- unbindTaskView(tv, task);
-
- // Reset the view properties and view state
- tv.clearAccessibilityFocus();
- tv.resetViewProperties();
- tv.setFocusedState(false, false /* requestViewFocus */);
- tv.setClipViewInStack(false);
- if (mScreenPinningEnabled) {
- tv.hideActionButton(false /* fadeOut */, 0 /* duration */, false /* scaleDown */, null);
- }
-
- // Detach the view from the hierarchy
- detachViewFromParent(tv);
- // Update the task views list after removing the task view
- updateTaskViewsList();
- }
-
- @Override
- public void onPickUpViewFromPool(TaskView tv, Task task, boolean isNewView) {
- // Find the index where this task should be placed in the stack
- int taskIndex = mStack.indexOfTask(task);
- int insertIndex = findTaskViewInsertIndex(task, taskIndex);
-
- // Add/attach the view to the hierarchy
- if (isNewView) {
- if (mInMeasureLayout) {
- // If we are measuring the layout, then just add the view normally as it will be
- // laid out during the layout pass
- addView(tv, insertIndex);
- } else {
- // Otherwise, this is from a bindVisibleTaskViews() call outside the measure/layout
- // pass, and we should layout the new child ourselves
- ViewGroup.LayoutParams params = tv.getLayoutParams();
- if (params == null) {
- params = generateDefaultLayoutParams();
- }
- addViewInLayout(tv, insertIndex, params, true /* preventRequestLayout */);
- measureTaskView(tv);
- layoutTaskView(true /* changed */, tv);
- }
- } else {
- attachViewToParent(tv, insertIndex, tv.getLayoutParams());
- }
- // Update the task views list after adding the new task view
- updateTaskViewsList();
-
- // Bind the task view to the new task
- bindTaskView(tv, task);
-
- // Set the new state for this view, including the callbacks and view clipping
- tv.setCallbacks(this);
- tv.setTouchEnabled(true);
- tv.setClipViewInStack(true);
- if (mFocusedTask == task) {
- tv.setFocusedState(true, false /* requestViewFocus */);
- if (mStartTimerIndicatorDuration > 0) {
- // The timer indicator couldn't be started before, so start it now
- tv.getHeaderView().startFocusTimerIndicator(mStartTimerIndicatorDuration);
- mStartTimerIndicatorDuration = 0;
- }
- }
-
- // Restore the action button visibility if it is the front most task view
- if (mScreenPinningEnabled && tv.getTask() == mStack.getFrontMostTask()) {
- tv.showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
- }
- }
-
- @Override
- public boolean hasPreferredData(TaskView tv, Task preferredData) {
- return (tv.getTask() == preferredData);
- }
-
- private void bindTaskView(TaskView tv, Task task) {
- // Rebind the task and request that this task's data be filled into the TaskView
- tv.onTaskBound(task, mTouchExplorationEnabled, mDisplayOrientation, mDisplayRect);
-
- // If the doze trigger has already fired, then update the state for this task view
- if (mUIDozeTrigger.isAsleep() ||
- useGridLayout() || Recents.getConfiguration().isLowRamDevice) {
- tv.setNoUserInteractionState();
- }
-
- if (task == mPrefetchingTask) {
- task.notifyTaskDataLoaded(task.thumbnail, task.icon);
- } else {
- // Load the task data
- Recents.getTaskLoader().loadTaskData(task);
- }
- Recents.getTaskLoader().getHighResThumbnailLoader().onTaskVisible(task);
- }
-
- private void unbindTaskView(TaskView tv, Task task) {
- if (task != mPrefetchingTask) {
- // Report that this task's data is no longer being used
- Recents.getTaskLoader().unloadTaskData(task);
- }
- Recents.getTaskLoader().getHighResThumbnailLoader().onTaskInvisible(task);
- }
-
- private void updatePrefetchingTask(ArrayList<Task> tasks, int frontIndex, int backIndex) {
- Task t = null;
- boolean somethingVisible = frontIndex != -1 && backIndex != -1;
- if (somethingVisible && frontIndex < tasks.size() - 1) {
- t = tasks.get(frontIndex + 1);
- }
- if (mPrefetchingTask != t) {
- if (mPrefetchingTask != null) {
- int index = tasks.indexOf(mPrefetchingTask);
- if (index < backIndex || index > frontIndex) {
- Recents.getTaskLoader().unloadTaskData(mPrefetchingTask);
- }
- }
- mPrefetchingTask = t;
- if (t != null) {
- Recents.getTaskLoader().loadTaskData(t);
- }
- }
- }
-
- private void clearPrefetchingTask() {
- if (mPrefetchingTask != null) {
- Recents.getTaskLoader().unloadTaskData(mPrefetchingTask);
- }
- mPrefetchingTask = null;
- }
-
- /**** TaskViewCallbacks Implementation ****/
-
- @Override
- public void onTaskViewClipStateChanged(TaskView tv) {
- if (!mTaskViewsClipDirty) {
- mTaskViewsClipDirty = true;
- invalidate();
- }
- }
-
- /**** TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks ****/
-
- @Override
- public void onFocusStateChanged(int prevFocusState, int curFocusState) {
- if (mDeferredTaskViewLayoutAnimation == null) {
- mUIDozeTrigger.poke();
- relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
- }
- }
-
- /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/
-
- @Override
- public void onStackScrollChanged(float prevScroll, float curScroll, AnimationProps animation) {
- mUIDozeTrigger.poke();
- if (animation != null) {
- relayoutTaskViewsOnNextFrame(animation);
- }
-
- // In grid layout, the stack action button always remains visible.
- if (mEnterAnimationComplete && !useGridLayout()) {
- if (Recents.getConfiguration().isLowRamDevice) {
- // Show stack button when user drags down to show older tasks on low ram devices
- if (mStack.getTaskCount() > 0 && !mStackActionButtonVisible
- && mTouchHandler.mIsScrolling && curScroll - prevScroll < 0) {
- // Going up
- EventBus.getDefault().send(
- new ShowStackActionButtonEvent(true /* translate */));
- }
- return;
- }
- if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
- curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
- mStack.getTaskCount() > 0) {
- EventBus.getDefault().send(new ShowStackActionButtonEvent(true /* translate */));
- } else if (prevScroll < HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
- curScroll >= HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new HideStackActionButtonEvent());
- }
- }
- }
-
- /**** EventBus Events ****/
-
- public final void onBusEvent(PackagesChangedEvent event) {
- // Compute which components need to be removed
- ArraySet<ComponentName> removedComponents = mStack.computeComponentsRemoved(
- event.packageName, event.userId);
-
- // For other tasks, just remove them directly if they no longer exist
- ArrayList<Task> tasks = mStack.getTasks();
- for (int i = tasks.size() - 1; i >= 0; i--) {
- final Task t = tasks.get(i);
- if (removedComponents.contains(t.key.getComponent())) {
- final TaskView tv = getChildViewForTask(t);
- if (tv != null) {
- // For visible children, defer removing the task until after the animation
- tv.dismissTask();
- } else {
- // Otherwise, remove the task from the stack immediately
- mStack.removeTask(t, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
- }
- }
- }
- }
-
- public final void onBusEvent(LaunchTaskEvent event) {
- // Cancel any doze triggers once a task is launched
- mUIDozeTrigger.stopDozing();
- }
-
- public final void onBusEvent(LaunchMostRecentTaskRequestEvent event) {
- if (mStack.getTaskCount() > 0) {
- Task mostRecentTask = mStack.getFrontMostTask();
- launchTask(mostRecentTask);
- }
- }
-
- public final void onBusEvent(ShowStackActionButtonEvent event) {
- mStackActionButtonVisible = true;
- }
-
- public final void onBusEvent(HideStackActionButtonEvent event) {
- mStackActionButtonVisible = false;
- }
-
- public final void onBusEvent(LaunchNextTaskRequestEvent event) {
- if (!mFinishedLayoutAfterStackReload) {
- mLaunchNextAfterFirstMeasure = true;
- return;
- }
-
- if (mStack.getTaskCount() == 0) {
- if (RecentsImpl.getLastPipTime() != -1) {
- EventBus.getDefault().send(new ExpandPipEvent());
- MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
- "pip");
- } else {
- // If there are no tasks, then just hide recents back to home.
- EventBus.getDefault().send(new HideRecentsEvent(false, true));
- }
- return;
- }
-
- if (!Recents.getConfiguration().getLaunchState().launchedFromPipApp
- && mStack.isNextLaunchTargetPip(RecentsImpl.getLastPipTime())) {
- // If the launch task is in the pinned stack, then expand the PiP now
- EventBus.getDefault().send(new ExpandPipEvent());
- MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK, "pip");
- } else {
- final Task launchTask = mStack.getNextLaunchTarget();
- if (launchTask != null) {
- // Defer launching the task until the PiP menu has been dismissed (if it is
- // showing at all)
- HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent();
- hideMenuEvent.addPostAnimationCallback(() -> {
- launchTask(launchTask);
- });
- EventBus.getDefault().send(hideMenuEvent);
- MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
- launchTask.key.getComponent().toString());
- }
- }
- }
-
- public final void onBusEvent(LaunchTaskStartedEvent event) {
- mAnimationHelper.startLaunchTaskAnimation(event.taskView, event.screenPinningRequested,
- event.getAnimationTrigger());
- }
-
- public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
- // Stop any scrolling
- mTouchHandler.cancelNonDismissTaskAnimations();
- mStackScroller.stopScroller();
- mStackScroller.stopBoundScrollAnimation();
- cancelDeferredTaskViewLayoutAnimation();
-
- // Start the task animations
- mAnimationHelper.startExitToHomeAnimation(event.animated, event.getAnimationTrigger());
-
- // Dismiss the grid task view focus frame
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.moveGridTaskViewFocus(null);
- }
- }
-
- public final void onBusEvent(DismissFocusedTaskViewEvent event) {
- if (mFocusedTask != null) {
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.moveGridTaskViewFocus(null);
- }
- TaskView tv = getChildViewForTask(mFocusedTask);
- if (tv != null) {
- tv.dismissTask();
- }
- resetFocusedTask(mFocusedTask);
- }
- }
-
- public final void onBusEvent(DismissTaskViewEvent event) {
- // For visible children, defer removing the task until after the animation
- mAnimationHelper.startDeleteTaskAnimation(
- event.taskView, useGridLayout(), event.getAnimationTrigger());
- }
-
- public final void onBusEvent(final DismissAllTaskViewsEvent event) {
- // Keep track of the tasks which will have their data removed
- ArrayList<Task> tasks = new ArrayList<>(mStack.getTasks());
- mAnimationHelper.startDeleteAllTasksAnimation(
- getTaskViews(), useGridLayout(), event.getAnimationTrigger());
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- // Announce for accessibility
- announceForAccessibility(getContext().getString(
- R.string.accessibility_recents_all_items_dismissed));
-
- // Remove all tasks and delete the task data for all tasks
- mStack.removeAllTasks(true /* notifyStackChanges */);
- for (int i = tasks.size() - 1; i >= 0; i--) {
- EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
- }
-
- MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS_ALL);
- }
- });
-
- }
-
- public final void onBusEvent(TaskViewDismissedEvent event) {
- // Announce for accessibility
- announceForAccessibility(getContext().getString(
- R.string.accessibility_recents_item_dismissed, event.task.title));
-
- if (useGridLayout() && event.animation != null) {
- event.animation.setListener(new AnimatorListenerAdapter() {
- public void onAnimationEnd(Animator animator) {
- if (mTaskViewFocusFrame != null) {
- // Resize the grid layout task view focus frame
- mTaskViewFocusFrame.resize();
- }
- }
- });
- }
-
- // Remove the task from the stack
- mStack.removeTask(event.task, event.animation, false /* fromDockGesture */);
- EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
- if (mStack.getTaskCount() > 0 && Recents.getConfiguration().isLowRamDevice) {
- EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
- }
-
- MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS,
- event.task.key.getComponent().toString());
- }
-
- public final void onBusEvent(FocusNextTaskViewEvent event) {
- // Stop any scrolling
- mStackScroller.stopScroller();
- mStackScroller.stopBoundScrollAnimation();
-
- setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */, false, 0);
- }
-
- public final void onBusEvent(FocusPreviousTaskViewEvent event) {
- // Stop any scrolling
- mStackScroller.stopScroller();
- mStackScroller.stopBoundScrollAnimation();
-
- setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
- }
-
- public final void onBusEvent(NavigateTaskViewEvent event) {
- if (useGridLayout()) {
- final int taskCount = mStack.getTaskCount();
- final int currentIndex = mStack.indexOfTask(getFocusedTask());
- final int nextIndex = mLayoutAlgorithm.mTaskGridLayoutAlgorithm.navigateFocus(taskCount,
- currentIndex, event.direction);
- setFocusedTask(nextIndex, false, true);
- } else {
- switch (event.direction) {
- case UP:
- EventBus.getDefault().send(new FocusPreviousTaskViewEvent());
- break;
- case DOWN:
- EventBus.getDefault().send(new FocusNextTaskViewEvent());
- break;
- }
- }
- }
-
- public final void onBusEvent(UserInteractionEvent event) {
- // Poke the doze trigger on user interaction
- mUIDozeTrigger.poke();
-
- RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- if (mFocusedTask != null) {
- TaskView tv = getChildViewForTask(mFocusedTask);
- if (tv != null) {
- tv.getHeaderView().cancelFocusTimerIndicator();
- }
- }
- }
-
- public final void onBusEvent(DragStartEvent event) {
- // Ensure that the drag task is not animated
- addIgnoreTask(event.task);
-
- // Enlarge the dragged view slightly
- float finalScale = event.taskView.getScaleX() * DRAG_SCALE_FACTOR;
- mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
- mTmpTransform, null);
- mTmpTransform.scale = finalScale;
- mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1;
- mTmpTransform.dimAlpha = 0f;
- updateTaskViewToTransform(event.taskView, mTmpTransform,
- new AnimationProps(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));
- }
-
- public final void onBusEvent(DragDropTargetChangedEvent event) {
- AnimationProps animation = new AnimationProps(SLOW_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN);
- boolean ignoreTaskOverrides = false;
- if (event.dropTarget instanceof DockState) {
- // Calculate the new task stack bounds that matches the window size that Recents will
- // have after the drop
- final DockState dockState = (DockState) event.dropTarget;
- Rect systemInsets = new Rect(mStableLayoutAlgorithm.mSystemInsets);
- // When docked, the nav bar insets are consumed and the activity is measured without
- // insets. However, the window bounds include the insets, so we need to subtract them
- // here to make them identical.
- int height = getMeasuredHeight();
- height -= systemInsets.bottom;
- systemInsets.bottom = 0;
- mStackBounds.set(dockState.getDockedTaskStackBounds(mDisplayRect, getMeasuredWidth(),
- height, mDividerSize, systemInsets,
- mLayoutAlgorithm, getResources(), mWindowRect));
- mLayoutAlgorithm.setSystemInsets(systemInsets);
- mLayoutAlgorithm.initialize(mDisplayRect, mWindowRect, mStackBounds);
- updateLayoutAlgorithm(true /* boundScroll */);
- ignoreTaskOverrides = true;
- } else {
- // Restore the pre-drag task stack bounds, but ensure that we don't layout the dragging
- // task view, so add it back to the ignore set after updating the layout
- removeIgnoreTask(event.task);
- updateLayoutToStableBounds();
- addIgnoreTask(event.task);
- }
- relayoutTaskViews(animation, null /* animationOverrides */, ignoreTaskOverrides);
- }
-
- public final void onBusEvent(final DragEndEvent event) {
- // We don't handle drops on the dock regions
- if (event.dropTarget instanceof DockState) {
- // However, we do need to reset the overrides, since the last state of this task stack
- // view layout was ignoring task overrides (see DragDropTargetChangedEvent handler)
- mLayoutAlgorithm.clearUnfocusedTaskOverrides();
- return;
- }
-
- // Restore the task, so that relayout will apply to it below
- removeIgnoreTask(event.task);
-
- // Convert the dragging task view back to its final layout-space rect
- Utilities.setViewFrameFromTranslation(event.taskView);
-
- // Animate all the tasks into place
- ArrayMap<Task, AnimationProps> animationOverrides = new ArrayMap<>();
- animationOverrides.put(event.task, new AnimationProps(SLOW_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN,
- event.getAnimationTrigger().decrementOnAnimationEnd()));
- relayoutTaskViews(new AnimationProps(SLOW_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN));
- event.getAnimationTrigger().increment();
- }
-
- public final void onBusEvent(final DragEndCancelledEvent event) {
- // Restore the pre-drag task stack bounds, including the dragging task view
- removeIgnoreTask(event.task);
- updateLayoutToStableBounds();
-
- // Convert the dragging task view back to its final layout-space rect
- Utilities.setViewFrameFromTranslation(event.taskView);
-
- // Animate all the tasks into place
- ArrayMap<Task, AnimationProps> animationOverrides = new ArrayMap<>();
- animationOverrides.put(event.task, new AnimationProps(SLOW_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN,
- event.getAnimationTrigger().decrementOnAnimationEnd()));
- relayoutTaskViews(new AnimationProps(SLOW_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN));
- event.getAnimationTrigger().increment();
- }
-
- public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- mEnterAnimationComplete = true;
- tryStartEnterAnimation();
- }
-
- private void tryStartEnterAnimation() {
- if (!mStackReloaded || !mFinishedLayoutAfterStackReload || !mEnterAnimationComplete) {
- return;
- }
-
- if (mStack.getTaskCount() > 0) {
- // Start the task enter animations
- ReferenceCountedTrigger trigger = new ReferenceCountedTrigger();
- mAnimationHelper.startEnterAnimation(trigger);
-
- // Add a runnable to the post animation ref counter to clear all the views
- trigger.addLastDecrementRunnable(() -> {
- // Start the dozer to trigger to trigger any UI that shows after a timeout
- mUIDozeTrigger.startDozing();
-
- // Update the focused state here -- since we only set the focused task without
- // requesting view focus in onFirstLayout(), actually request view focus and
- // animate the focused state if we are alt-tabbing now, after the window enter
- // animation is completed
- if (mFocusedTask != null) {
- RecentsConfiguration config = Recents.getConfiguration();
- RecentsActivityLaunchState launchState = config.getLaunchState();
- setFocusedTask(mStack.indexOfTask(mFocusedTask),
- false /* scrollToTask */, launchState.launchedWithAltTab);
- TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
- if (mTouchExplorationEnabled && focusedTaskView != null) {
- focusedTaskView.requestAccessibilityFocus();
- }
- }
- });
- }
-
- // This flag is only used to choreograph the enter animation, so we can reset it here
- mStackReloaded = false;
- }
-
- public final void onBusEvent(final MultiWindowStateChangedEvent event) {
- if (event.inMultiWindow || !event.showDeferredAnimation) {
- setTasks(event.stack, true /* allowNotifyStackChanges */);
- } else {
- // Reset the launch state before handling the multiwindow change
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- launchState.reset();
-
- // Defer until the next frame to ensure that we have received all the system insets, and
- // initial layout updates
- event.getAnimationTrigger().increment();
- post(new Runnable() {
- @Override
- public void run() {
- // Scroll the stack to the front to see the undocked task
- mAnimationHelper.startNewStackScrollAnimation(event.stack,
- event.getAnimationTrigger());
- event.getAnimationTrigger().decrement();
- }
- });
- }
- }
-
- public final void onBusEvent(ConfigurationChangedEvent event) {
- if (event.fromDeviceOrientationChange) {
- mDisplayOrientation = Utilities.getAppConfiguration(mContext).orientation;
- mDisplayRect = Recents.getSystemServices().getDisplayRect();
-
- // Always stop the scroller, otherwise, we may continue setting the stack scroll to the
- // wrong bounds in the new layout
- mStackScroller.stopScroller();
- }
- reloadOnConfigurationChange();
-
- // Notify the task views of the configuration change so they can reload their resources
- if (!event.fromMultiWindow) {
- mTmpTaskViews.clear();
- mTmpTaskViews.addAll(getTaskViews());
- mTmpTaskViews.addAll(mViewPool.getViews());
- int taskViewCount = mTmpTaskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- mTmpTaskViews.get(i).onConfigurationChanged();
- }
- }
-
- // Update the Clear All button in case we're switching in or out of grid layout.
- updateStackActionButtonVisibility();
-
- // Trigger a new layout and update to the initial state if necessary. When entering split
- // screen, the multi-window configuration change event can happen after the stack is already
- // reloaded (but pending measure/layout), in this case, do not override the intiial state
- // and just wait for the upcoming measure/layout pass.
- if (event.fromMultiWindow && mInitialState == INITIAL_STATE_UPDATE_NONE) {
- mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY;
- requestLayout();
- } else if (event.fromDeviceOrientationChange) {
- mInitialState = INITIAL_STATE_UPDATE_ALL;
- requestLayout();
- }
- }
-
- public final void onBusEvent(RecentsGrowingEvent event) {
- mResetToInitialStateWhenResized = true;
- }
-
- public final void onBusEvent(RecentsVisibilityChangedEvent event) {
- if (!event.visible) {
- if (mTaskViewFocusFrame != null) {
- mTaskViewFocusFrame.moveGridTaskViewFocus(null);
- }
-
- List<TaskView> taskViews = new ArrayList<>(getTaskViews());
- for (int i = 0; i < taskViews.size(); i++) {
- mViewPool.returnViewToPool(taskViews.get(i));
- }
- clearPrefetchingTask();
-
- // We can not reset mEnterAnimationComplete in onReload() because when docking the top
- // task, we can receive the enter animation callback before onReload(), so reset it
- // here onces Recents is not visible
- mEnterAnimationComplete = false;
- }
- }
-
- public final void onBusEvent(ActivityPinnedEvent event) {
- // If an activity enters PiP while Recents is open, remove the stack task associated with
- // the new PiP task
- Task removeTask = mStack.findTaskWithId(event.taskId);
- if (removeTask != null) {
- // In this case, we remove the task, but if the last task is removed, don't dismiss
- // Recents to home
- mStack.removeTask(removeTask, AnimationProps.IMMEDIATE, false /* fromDockGesture */,
- false /* dismissRecentsIfAllRemoved */);
- }
- updateLayoutAlgorithm(false /* boundScroll */);
- updateToInitialState();
- }
-
- public void reloadOnConfigurationChange() {
- mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext());
- mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
- }
-
- /**
- * Returns the insert index for the task in the current set of task views. If the given task
- * is already in the task view list, then this method returns the insert index assuming it
- * is first removed at the previous index.
- *
- * @param task the task we are finding the index for
- * @param taskIndex the index of the task in the stack
- */
- private int findTaskViewInsertIndex(Task task, int taskIndex) {
- if (taskIndex != -1) {
- List<TaskView> taskViews = getTaskViews();
- boolean foundTaskView = false;
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- Task tvTask = taskViews.get(i).getTask();
- if (tvTask == task) {
- foundTaskView = true;
- } else if (taskIndex < mStack.indexOfTask(tvTask)) {
- if (foundTaskView) {
- return i - 1;
- } else {
- return i;
- }
- }
- }
- }
- return -1;
- }
-
- private void launchTask(Task task) {
- // Stop all animations
- cancelAllTaskViewAnimations();
-
- float curScroll = mStackScroller.getStackScroll();
- float targetScroll = mLayoutAlgorithm.getStackScrollForTaskAtInitialOffset(task);
- float absScrollDiff = Math.abs(targetScroll - curScroll);
- if (getChildViewForTask(task) == null || absScrollDiff > 0.35f) {
- int duration = (int) (LAUNCH_NEXT_SCROLL_BASE_DURATION +
- absScrollDiff * LAUNCH_NEXT_SCROLL_INCR_DURATION);
- mStackScroller.animateScroll(targetScroll,
- duration, new Runnable() {
- @Override
- public void run() {
- EventBus.getDefault().send(new LaunchTaskEvent(
- getChildViewForTask(task), task, null,
- false /* screenPinningRequested */));
- }
- });
- } else {
- EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(task), task, null,
- false /* screenPinningRequested */));
- }
- }
-
- /**
- * Check whether we should use the grid layout.
- */
- public boolean useGridLayout() {
- return mLayoutAlgorithm.useGridLayout();
- }
-
- /**
- * Reads current system flags related to accessibility and screen pinning.
- */
- private void readSystemFlags() {
- SystemServicesProxy ssp = Recents.getSystemServices();
- mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
- mScreenPinningEnabled = ActivityManagerWrapper.getInstance().isScreenPinningEnabled()
- && !ActivityManagerWrapper.getInstance().isLockToAppActive();
- }
-
- private void updateStackActionButtonVisibility() {
- if (Recents.getConfiguration().isLowRamDevice) {
- return;
- }
-
- // Always show the button in grid layout.
- if (useGridLayout() ||
- (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
- mStack.getTaskCount() > 0)) {
- EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
- } else {
- EventBus.getDefault().send(new HideStackActionButtonEvent());
- }
- }
-
- /**
- * Returns the task to focus given the current launch state.
- */
- private int getInitialFocusTaskIndex(RecentsActivityLaunchState launchState, int numTasks,
- boolean useGridLayout) {
- if (launchState.launchedFromApp) {
- if (useGridLayout) {
- // If coming from another app to the grid layout, focus the front most task
- return numTasks - 1;
- }
-
- // If coming from another app, focus the next task
- return Math.max(0, numTasks - 2);
- } else {
- // If coming from home, focus the front most task
- return numTasks - 1;
- }
- }
-
- /**
- * Updates {@param transforms} to be the same size as {@param tasks}.
- */
- private void matchTaskListSize(List<Task> tasks, List<TaskViewTransform> transforms) {
- // We can reuse the task transforms where possible to reduce object allocation
- int taskTransformCount = transforms.size();
- int taskCount = tasks.size();
- if (taskTransformCount < taskCount) {
- // If there are less transforms than tasks, then add as many transforms as necessary
- for (int i = taskTransformCount; i < taskCount; i++) {
- transforms.add(new TaskViewTransform());
- }
- } else if (taskTransformCount > taskCount) {
- // If there are more transforms than tasks, then just subset the transform list
- transforms.subList(taskCount, taskTransformCount).clear();
- }
- }
-
- public void dump(String prefix, PrintWriter writer) {
- String innerPrefix = prefix + " ";
- String id = Integer.toHexString(System.identityHashCode(this));
-
- writer.print(prefix); writer.print(TAG);
- writer.print(" hasDefRelayout=");
- writer.print(mDeferredTaskViewLayoutAnimation != null ? "Y" : "N");
- writer.print(" clipDirty="); writer.print(mTaskViewsClipDirty ? "Y" : "N");
- writer.print(" awaitingStackReload="); writer.print(mFinishedLayoutAfterStackReload ? "Y" : "N");
- writer.print(" initialState="); writer.print(mInitialState);
- writer.print(" inMeasureLayout="); writer.print(mInMeasureLayout ? "Y" : "N");
- writer.print(" enterAnimCompleted="); writer.print(mEnterAnimationComplete ? "Y" : "N");
- writer.print(" touchExplorationOn="); writer.print(mTouchExplorationEnabled ? "Y" : "N");
- writer.print(" screenPinningOn="); writer.print(mScreenPinningEnabled ? "Y" : "N");
- writer.print(" numIgnoreTasks="); writer.print(mIgnoreTasks.size());
- writer.print(" numViewPool="); writer.print(mViewPool.getViews().size());
- writer.print(" stableStackBounds="); writer.print(Utilities.dumpRect(mStableStackBounds));
- writer.print(" stackBounds="); writer.print(Utilities.dumpRect(mStackBounds));
- writer.print(" stableWindow="); writer.print(Utilities.dumpRect(mStableWindowRect));
- writer.print(" window="); writer.print(Utilities.dumpRect(mWindowRect));
- writer.print(" display="); writer.print(Utilities.dumpRect(mDisplayRect));
- writer.print(" orientation="); writer.print(mDisplayOrientation);
- writer.print(" [0x"); writer.print(id); writer.print("]");
- writer.println();
-
- if (mFocusedTask != null) {
- writer.print(innerPrefix);
- writer.print("Focused task: ");
- mFocusedTask.dump("", writer);
- }
-
- int numTaskViews = mTaskViews.size();
- for (int i = 0; i < numTaskViews; i++) {
- mTaskViews.get(i).dump(innerPrefix, writer);
- }
-
- mLayoutAlgorithm.dump(innerPrefix, writer);
- mStackScroller.dump(innerPrefix, writer);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
deleted file mode 100644
index 6b23977..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.TimeInterpolator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.util.FloatProperty;
-import android.util.Log;
-import android.util.Property;
-import android.view.ViewConfiguration;
-import android.view.ViewDebug;
-import android.widget.OverScroller;
-
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.recents.views.lowram.TaskStackLowRamLayoutAlgorithm;
-import com.android.systemui.statusbar.FlingAnimationUtils;
-
-import java.io.PrintWriter;
-
-/* The scrolling logic for a TaskStackView */
-public class TaskStackViewScroller {
-
- private static final String TAG = "TaskStackViewScroller";
- private static final boolean DEBUG = false;
-
- public interface TaskStackViewScrollerCallbacks {
- void onStackScrollChanged(float prevScroll, float curScroll, AnimationProps animation);
- }
-
- /**
- * A Property wrapper around the <code>stackScroll</code> functionality handled by the
- * {@link #setStackScroll(float)} and
- * {@link #getStackScroll()} methods.
- */
- private static final Property<TaskStackViewScroller, Float> STACK_SCROLL =
- new FloatProperty<TaskStackViewScroller>("stackScroll") {
- @Override
- public void setValue(TaskStackViewScroller object, float value) {
- object.setStackScroll(value);
- }
-
- @Override
- public Float get(TaskStackViewScroller object) {
- return object.getStackScroll();
- }
- };
-
- Context mContext;
- TaskStackLayoutAlgorithm mLayoutAlgorithm;
- TaskStackViewScrollerCallbacks mCb;
-
- @ViewDebug.ExportedProperty(category="recents")
- float mStackScrollP;
- @ViewDebug.ExportedProperty(category="recents")
- float mLastDeltaP = 0f;
- float mFlingDownScrollP;
- int mFlingDownY;
-
- OverScroller mScroller;
- ObjectAnimator mScrollAnimator;
- float mFinalAnimatedScroll;
-
- final FlingAnimationUtils mFlingAnimationUtils;
-
- public TaskStackViewScroller(Context context, TaskStackViewScrollerCallbacks cb,
- TaskStackLayoutAlgorithm layoutAlgorithm) {
- mContext = context;
- mCb = cb;
- mScroller = new OverScroller(context);
- if (Recents.getConfiguration().isLowRamDevice) {
- mScroller.setFriction(0.06f);
- }
- mLayoutAlgorithm = layoutAlgorithm;
- mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
- }
-
- /** Resets the task scroller. */
- void reset() {
- mStackScrollP = 0f;
- mLastDeltaP = 0f;
- }
-
- void resetDeltaScroll() {
- mLastDeltaP = 0f;
- }
-
- /** Gets the current stack scroll */
- public float getStackScroll() {
- return mStackScrollP;
- }
-
- /**
- * Sets the current stack scroll immediately.
- */
- public void setStackScroll(float s) {
- setStackScroll(s, AnimationProps.IMMEDIATE);
- }
-
- /**
- * Sets the current stack scroll immediately, and returns the difference between the target
- * scroll and the actual scroll after accounting for the effect on the focus state.
- */
- public float setDeltaStackScroll(float downP, float deltaP) {
- float targetScroll = downP + deltaP;
- float newScroll = mLayoutAlgorithm.updateFocusStateOnScroll(downP + mLastDeltaP, targetScroll,
- mStackScrollP);
- setStackScroll(newScroll, AnimationProps.IMMEDIATE);
- mLastDeltaP = deltaP;
- return newScroll - targetScroll;
- }
-
- /**
- * Sets the current stack scroll, but indicates to the callback the preferred animation to
- * update to this new scroll.
- */
- public void setStackScroll(float newScroll, AnimationProps animation) {
- float prevScroll = mStackScrollP;
- mStackScrollP = newScroll;
- if (mCb != null) {
- mCb.onStackScrollChanged(prevScroll, mStackScrollP, animation);
- }
- }
-
- /**
- * Sets the current stack scroll to the initial state when you first enter recents.
- * @return whether the stack progress changed.
- */
- public boolean setStackScrollToInitialState() {
- float prevScroll = mStackScrollP;
- setStackScroll(mLayoutAlgorithm.mInitialScrollP);
- return Float.compare(prevScroll, mStackScrollP) != 0;
- }
-
- /**
- * Starts a fling that is coordinated with the {@link TaskStackViewTouchHandler}.
- */
- public void fling(float downScrollP, int downY, int y, int velY, int minY, int maxY,
- int overscroll) {
- if (DEBUG) {
- Log.d(TAG, "fling: " + downScrollP + ", downY: " + downY + ", y: " + y +
- ", velY: " + velY + ", minY: " + minY + ", maxY: " + maxY);
- }
- mFlingDownScrollP = downScrollP;
- mFlingDownY = downY;
- mScroller.fling(0, y, 0, velY, 0, 0, minY, maxY, 0, overscroll);
- }
-
- /** Bounds the current scroll if necessary */
- public boolean boundScroll() {
- float curScroll = getStackScroll();
- float newScroll = getBoundedStackScroll(curScroll);
- if (Float.compare(newScroll, curScroll) != 0) {
- setStackScroll(newScroll);
- return true;
- }
- return false;
- }
-
- /** Returns the bounded stack scroll */
- float getBoundedStackScroll(float scroll) {
- return Utilities.clamp(scroll, mLayoutAlgorithm.mMinScrollP, mLayoutAlgorithm.mMaxScrollP);
- }
-
- /** Returns the amount that the absolute value of how much the scroll is out of bounds. */
- float getScrollAmountOutOfBounds(float scroll) {
- if (scroll < mLayoutAlgorithm.mMinScrollP) {
- return Math.abs(scroll - mLayoutAlgorithm.mMinScrollP);
- } else if (scroll > mLayoutAlgorithm.mMaxScrollP) {
- return Math.abs(scroll - mLayoutAlgorithm.mMaxScrollP);
- }
- return 0f;
- }
-
- /** Returns whether the specified scroll is out of bounds */
- boolean isScrollOutOfBounds() {
- return Float.compare(getScrollAmountOutOfBounds(mStackScrollP), 0f) != 0;
- }
-
- /**
- * Scrolls the closest task and snaps into place. Only used in recents for low ram devices.
- * @param velocity of scroll
- */
- void scrollToClosestTask(int velocity) {
- float stackScroll = getStackScroll();
-
- // Skip if not in low ram layout and if the scroll is out of min and max bounds
- if (!Recents.getConfiguration().isLowRamDevice || stackScroll < mLayoutAlgorithm.mMinScrollP
- || stackScroll > mLayoutAlgorithm.mMaxScrollP) {
- return;
- }
- TaskStackLowRamLayoutAlgorithm algorithm = mLayoutAlgorithm.mTaskStackLowRamLayoutAlgorithm;
-
- float flingThreshold = ViewConfiguration.get(mContext).getScaledMinimumFlingVelocity();
- if (Math.abs(velocity) > flingThreshold) {
- int minY = algorithm.percentageToScroll(mLayoutAlgorithm.mMinScrollP);
- int maxY = algorithm.percentageToScroll(mLayoutAlgorithm.mMaxScrollP);
-
- // Calculate the fling and snap to closest task from final y position, computeScroll()
- // never runs when cancelled with animateScroll() and the overscroll is not calculated
- // here
- fling(0 /* downScrollP */, 0 /* downY */, algorithm.percentageToScroll(stackScroll),
- -velocity, minY, maxY, 0 /* overscroll */);
- float pos = algorithm.scrollToPercentage(mScroller.getFinalY());
-
- float newScrollP = algorithm.getClosestTaskP(pos, mLayoutAlgorithm.mNumStackTasks,
- velocity);
- ValueAnimator animator = ObjectAnimator.ofFloat(stackScroll, newScrollP);
- mFlingAnimationUtils.apply(animator, algorithm.percentageToScroll(stackScroll),
- algorithm.percentageToScroll(newScrollP), velocity);
- animateScroll(newScrollP, (int) animator.getDuration(), animator.getInterpolator(),
- null /* postRunnable */);
- } else {
- float newScrollP = algorithm.getClosestTaskP(stackScroll,
- mLayoutAlgorithm.mNumStackTasks, velocity);
- animateScroll(newScrollP, 300, Interpolators.ACCELERATE_DECELERATE,
- null /* postRunnable */);
- }
- }
-
- /** Animates the stack scroll into bounds */
- ObjectAnimator animateBoundScroll() {
- // TODO: Take duration for snap back
- float curScroll = getStackScroll();
- float newScroll = getBoundedStackScroll(curScroll);
- if (Float.compare(newScroll, curScroll) != 0) {
- // Start a new scroll animation
- animateScroll(newScroll, null /* postScrollRunnable */);
- }
- return mScrollAnimator;
- }
-
- /** Animates the stack scroll */
- void animateScroll(float newScroll, final Runnable postRunnable) {
- int duration = mContext.getResources().getInteger(
- R.integer.recents_animate_task_stack_scroll_duration);
- animateScroll(newScroll, duration, postRunnable);
- }
-
- /** Animates the stack scroll */
- void animateScroll(float newScroll, int duration, final Runnable postRunnable) {
- animateScroll(newScroll, duration, Interpolators.LINEAR_OUT_SLOW_IN, postRunnable);
- }
-
- /** Animates the stack scroll with time interpolator */
- void animateScroll(float newScroll, int duration, TimeInterpolator interpolator,
- final Runnable postRunnable) {
- ObjectAnimator an = ObjectAnimator.ofFloat(this, STACK_SCROLL, getStackScroll(), newScroll);
- an.setDuration(duration);
- an.setInterpolator(interpolator);
- animateScroll(newScroll, an, postRunnable);
- }
-
- /** Animates the stack scroll with animator */
- private void animateScroll(float newScroll, ObjectAnimator animator,
- final Runnable postRunnable) {
- // Finish any current scrolling animations
- if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
- setStackScroll(mFinalAnimatedScroll);
- mScroller.forceFinished(true);
- }
- stopScroller();
- stopBoundScrollAnimation();
-
- if (Float.compare(mStackScrollP, newScroll) != 0) {
- mFinalAnimatedScroll = newScroll;
- mScrollAnimator = animator;
- mScrollAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (postRunnable != null) {
- postRunnable.run();
- }
- mScrollAnimator.removeAllListeners();
- }
- });
- mScrollAnimator.start();
- } else {
- if (postRunnable != null) {
- postRunnable.run();
- }
- }
- }
-
- /** Aborts any current stack scrolls */
- void stopBoundScrollAnimation() {
- Utilities.cancelAnimationWithoutCallbacks(mScrollAnimator);
- }
-
- /**** OverScroller ****/
-
- /** Called from the view draw, computes the next scroll. */
- boolean computeScroll() {
- if (mScroller.computeScrollOffset()) {
- float deltaP = mLayoutAlgorithm.getDeltaPForY(mFlingDownY, mScroller.getCurrY());
- mFlingDownScrollP += setDeltaStackScroll(mFlingDownScrollP, deltaP);
- if (DEBUG) {
- Log.d(TAG, "computeScroll: " + (mFlingDownScrollP + deltaP));
- }
- return true;
- }
- return false;
- }
-
- /** Returns whether the overscroller is scrolling. */
- boolean isScrolling() {
- return !mScroller.isFinished();
- }
-
- float getScrollVelocity() {
- return mScroller.getCurrVelocity();
- }
-
- /** Stops the scroller and any current fling. */
- void stopScroller() {
- if (!mScroller.isFinished()) {
- mScroller.abortAnimation();
- }
- }
-
- public void dump(String prefix, PrintWriter writer) {
- writer.print(prefix); writer.print(TAG);
- writer.print(" stackScroll:"); writer.print(mStackScrollP);
- writer.println();
- }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
deleted file mode 100644
index c91cdfc..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Path;
-import android.util.ArrayMap;
-import android.util.MutableBoolean;
-import android.view.InputDevice;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewDebug;
-import android.view.ViewParent;
-import android.view.animation.Interpolator;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.HideRecentsEvent;
-import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
-import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
-import com.android.systemui.recents.misc.FreePathInterpolator;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.statusbar.FlingAnimationUtils;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Handles touch events for a TaskStackView.
- */
-class TaskStackViewTouchHandler implements SwipeHelper.Callback {
-
- private static final int INACTIVE_POINTER_ID = -1;
- private static final float CHALLENGING_SWIPE_ESCAPE_VELOCITY = 800f; // dp/sec
- // The min overscroll is the amount of task progress overscroll we want / the max overscroll
- // curve value below
- private static final float MAX_OVERSCROLL = 0.7f / 0.3f;
- private static final Interpolator OVERSCROLL_INTERP;
- static {
- Path OVERSCROLL_PATH = new Path();
- OVERSCROLL_PATH.moveTo(0, 0);
- OVERSCROLL_PATH.cubicTo(0.2f, 0.175f, 0.25f, 0.3f, 1f, 0.3f);
- OVERSCROLL_INTERP = new FreePathInterpolator(OVERSCROLL_PATH);
- }
-
- Context mContext;
- TaskStackView mSv;
- TaskStackViewScroller mScroller;
- VelocityTracker mVelocityTracker;
- FlingAnimationUtils mFlingAnimUtils;
- ValueAnimator mScrollFlingAnimator;
-
- @ViewDebug.ExportedProperty(category="recents")
- boolean mIsScrolling;
- float mDownScrollP;
- int mDownX, mDownY;
- int mLastY;
- int mActivePointerId = INACTIVE_POINTER_ID;
- int mOverscrollSize;
- TaskView mActiveTaskView = null;
-
- int mMinimumVelocity;
- int mMaximumVelocity;
- // The scroll touch slop is used to calculate when we start scrolling
- int mScrollTouchSlop;
- // Used to calculate when a tap is outside a task view rectangle.
- final int mWindowTouchSlop;
-
- private final StackViewScrolledEvent mStackViewScrolledEvent = new StackViewScrolledEvent();
-
- // The current and final set of task transforms, sized to match the list of tasks in the stack
- private ArrayList<Task> mCurrentTasks = new ArrayList<>();
- private ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
- private ArrayList<TaskViewTransform> mFinalTaskTransforms = new ArrayList<>();
- private ArrayMap<View, Animator> mSwipeHelperAnimations = new ArrayMap<>();
- private TaskViewTransform mTmpTransform = new TaskViewTransform();
- private float mTargetStackScroll;
-
- SwipeHelper mSwipeHelper;
- boolean mInterceptedBySwipeHelper;
-
- public TaskStackViewTouchHandler(Context context, TaskStackView sv,
- TaskStackViewScroller scroller) {
- Resources res = context.getResources();
- ViewConfiguration configuration = ViewConfiguration.get(context);
- mContext = context;
- mSv = sv;
- mScroller = scroller;
- mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
- mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
- mScrollTouchSlop = configuration.getScaledTouchSlop();
- mWindowTouchSlop = configuration.getScaledWindowTouchSlop();
- mFlingAnimUtils = new FlingAnimationUtils(context, 0.2f);
- mOverscrollSize = res.getDimensionPixelSize(R.dimen.recents_fling_overscroll_distance);
- mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context) {
- @Override
- protected float getSize(View v) {
- return getScaledDismissSize();
- }
-
- @Override
- protected void prepareDismissAnimation(View v, Animator anim) {
- mSwipeHelperAnimations.put(v, anim);
- }
-
- @Override
- protected void prepareSnapBackAnimation(View v, Animator anim) {
- anim.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
- mSwipeHelperAnimations.put(v, anim);
- }
-
- @Override
- protected float getUnscaledEscapeVelocity() {
- return CHALLENGING_SWIPE_ESCAPE_VELOCITY;
- }
-
- @Override
- protected long getMaxEscapeAnimDuration() {
- return 700;
- }
- };
- mSwipeHelper.setDisableHardwareLayers(true);
- }
-
- /** Velocity tracker helpers */
- void initOrResetVelocityTracker() {
- if (mVelocityTracker == null) {
- mVelocityTracker = VelocityTracker.obtain();
- } else {
- mVelocityTracker.clear();
- }
- }
- void recycleVelocityTracker() {
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- }
-
- /** Touch preprocessing for handling below */
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- // Pass through to swipe helper if we are swiping
- mInterceptedBySwipeHelper = isSwipingEnabled() && mSwipeHelper.onInterceptTouchEvent(ev);
- if (mInterceptedBySwipeHelper) {
- return true;
- }
-
- return handleTouchEvent(ev);
- }
-
- /** Handles touch events once we have intercepted them */
- public boolean onTouchEvent(MotionEvent ev) {
- // Pass through to swipe helper if we are swiping
- if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
- return true;
- }
-
- handleTouchEvent(ev);
- return true;
- }
-
- /**
- * Finishes all scroll-fling and non-dismissing animations currently running.
- */
- public void cancelNonDismissTaskAnimations() {
- Utilities.cancelAnimationWithoutCallbacks(mScrollFlingAnimator);
- if (!mSwipeHelperAnimations.isEmpty()) {
- // For the non-dismissing tasks, freeze the position into the task overrides
- List<TaskView> taskViews = mSv.getTaskViews();
- for (int i = taskViews.size() - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
-
- if (mSv.isIgnoredTask(tv.getTask())) {
- continue;
- }
-
- tv.cancelTransformAnimation();
- mSv.getStackAlgorithm().addUnfocusedTaskOverride(tv, mTargetStackScroll);
- }
- mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
- // Update the scroll to the final scroll position from onBeginDrag()
- mSv.getScroller().setStackScroll(mTargetStackScroll, null);
-
- mSwipeHelperAnimations.clear();
- }
- mActiveTaskView = null;
- }
-
- private boolean handleTouchEvent(MotionEvent ev) {
- // Short circuit if we have no children
- if (mSv.getTaskViews().size() == 0) {
- return false;
- }
-
- final TaskStackLayoutAlgorithm layoutAlgorithm = mSv.mLayoutAlgorithm;
- int action = ev.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_DOWN: {
- // Stop the current scroll if it is still flinging
- mScroller.stopScroller();
- mScroller.stopBoundScrollAnimation();
- mScroller.resetDeltaScroll();
- cancelNonDismissTaskAnimations();
- mSv.cancelDeferredTaskViewLayoutAnimation();
-
- // Save the touch down info
- mDownX = (int) ev.getX();
- mDownY = (int) ev.getY();
- mLastY = mDownY;
- mDownScrollP = mScroller.getStackScroll();
- mActivePointerId = ev.getPointerId(0);
- mActiveTaskView = findViewAtPoint(mDownX, mDownY);
-
- // Initialize the velocity tracker
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- break;
- }
- case MotionEvent.ACTION_POINTER_DOWN: {
- final int index = ev.getActionIndex();
- mActivePointerId = ev.getPointerId(index);
- mDownX = (int) ev.getX(index);
- mDownY = (int) ev.getY(index);
- mLastY = mDownY;
- mDownScrollP = mScroller.getStackScroll();
- mScroller.resetDeltaScroll();
- mVelocityTracker.addMovement(ev);
- break;
- }
- case MotionEvent.ACTION_MOVE: {
- int activePointerIndex = ev.findPointerIndex(mActivePointerId);
- if (activePointerIndex == -1) {
- break;
- }
- int y = (int) ev.getY(activePointerIndex);
- int x = (int) ev.getX(activePointerIndex);
- if (!mIsScrolling) {
- int yDiff = Math.abs(y - mDownY);
- int xDiff = Math.abs(x - mDownX);
- if (Math.abs(y - mDownY) > mScrollTouchSlop && yDiff > xDiff) {
- mIsScrolling = true;
- float stackScroll = mScroller.getStackScroll();
- List<TaskView> taskViews = mSv.getTaskViews();
- for (int i = taskViews.size() - 1; i >= 0; i--) {
- layoutAlgorithm.addUnfocusedTaskOverride(taskViews.get(i).getTask(),
- stackScroll);
- }
- layoutAlgorithm.setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
-
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
-
- MetricsLogger.action(mSv.getContext(), MetricsEvent.OVERVIEW_SCROLL);
- mLastY = mDownY = y;
- }
- }
- if (mIsScrolling) {
- // If we just move linearly on the screen, then that would map to 1/arclength
- // of the curve, so just move the scroll proportional to that
- float deltaP = layoutAlgorithm.getDeltaPForY(mDownY, y);
-
- // Modulate the overscroll to prevent users from pulling the stack too far
- float minScrollP = layoutAlgorithm.mMinScrollP;
- float maxScrollP = layoutAlgorithm.mMaxScrollP;
- float curScrollP = mDownScrollP + deltaP;
- if (curScrollP < minScrollP || curScrollP > maxScrollP) {
- float clampedScrollP = Utilities.clamp(curScrollP, minScrollP, maxScrollP);
- float overscrollP = (curScrollP - clampedScrollP);
- float maxOverscroll = Recents.getConfiguration().isLowRamDevice
- ? layoutAlgorithm.mTaskStackLowRamLayoutAlgorithm.getMaxOverscroll()
- : MAX_OVERSCROLL;
- float overscrollX = Math.abs(overscrollP) / maxOverscroll;
- float interpX = OVERSCROLL_INTERP.getInterpolation(overscrollX);
- curScrollP = clampedScrollP + Math.signum(overscrollP) *
- (interpX * maxOverscroll);
- }
- mDownScrollP += mScroller.setDeltaStackScroll(mDownScrollP,
- curScrollP - mDownScrollP);
- mStackViewScrolledEvent.updateY(y - mLastY);
- EventBus.getDefault().send(mStackViewScrolledEvent);
- }
-
- mLastY = y;
- mVelocityTracker.addMovement(ev);
- break;
- }
- case MotionEvent.ACTION_POINTER_UP: {
- int pointerIndex = ev.getActionIndex();
- int pointerId = ev.getPointerId(pointerIndex);
- if (pointerId == mActivePointerId) {
- // Select a new active pointer id and reset the motion state
- final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
- mActivePointerId = ev.getPointerId(newPointerIndex);
- mDownX = (int) ev.getX(pointerIndex);
- mDownY = (int) ev.getY(pointerIndex);
- mLastY = mDownY;
- mDownScrollP = mScroller.getStackScroll();
- }
- mVelocityTracker.addMovement(ev);
- break;
- }
- case MotionEvent.ACTION_UP: {
- mVelocityTracker.addMovement(ev);
- mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- int activePointerIndex = ev.findPointerIndex(mActivePointerId);
- int y = (int) ev.getY(activePointerIndex);
- int velocity = (int) mVelocityTracker.getYVelocity(mActivePointerId);
- if (mIsScrolling) {
- if (mScroller.isScrollOutOfBounds()) {
- mScroller.animateBoundScroll();
- } else if (Math.abs(velocity) > mMinimumVelocity &&
- !Recents.getConfiguration().isLowRamDevice) {
- float minY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
- layoutAlgorithm.mMaxScrollP);
- float maxY = mDownY + layoutAlgorithm.getYForDeltaP(mDownScrollP,
- layoutAlgorithm.mMinScrollP);
- mScroller.fling(mDownScrollP, mDownY, y, velocity, (int) minY, (int) maxY,
- mOverscrollSize);
- mSv.invalidate();
- }
-
- // Reset the focused task after the user has scrolled, but we have no scrolling
- // in grid layout and therefore we don't want to reset the focus there.
- if (!mSv.mTouchExplorationEnabled && !mSv.useGridLayout()) {
- if (Recents.getConfiguration().isLowRamDevice) {
- mScroller.scrollToClosestTask(velocity);
- } else {
- mSv.resetFocusedTask(mSv.getFocusedTask());
- }
- }
- } else if (mActiveTaskView == null) {
- // This tap didn't start on a task.
- maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY());
- }
-
- mActivePointerId = INACTIVE_POINTER_ID;
- mIsScrolling = false;
- recycleVelocityTracker();
- break;
- }
- case MotionEvent.ACTION_CANCEL: {
- mActivePointerId = INACTIVE_POINTER_ID;
- mIsScrolling = false;
- recycleVelocityTracker();
- break;
- }
- }
- return mIsScrolling;
- }
-
- /** Hides recents if the up event at (x, y) is a tap on the background area. */
- void maybeHideRecentsFromBackgroundTap(int x, int y) {
- // Ignore the up event if it's too far from its start position. The user might have been
- // trying to scroll or swipe.
- int dx = Math.abs(mDownX - x);
- int dy = Math.abs(mDownY - y);
- if (dx > mScrollTouchSlop || dy > mScrollTouchSlop) {
- return;
- }
-
- // Shift the tap position toward the center of the task stack and check to see if it would
- // have hit a view. The user might have tried to tap on a task and missed slightly.
- int shiftedX = x;
- if (x > (mSv.getRight() - mSv.getLeft()) / 2) {
- shiftedX -= mWindowTouchSlop;
- } else {
- shiftedX += mWindowTouchSlop;
- }
- if (findViewAtPoint(shiftedX, y) != null) {
- return;
- }
-
- // Disallow tapping above and below the stack to dismiss recents
- if (x > mSv.mLayoutAlgorithm.mStackRect.left && x < mSv.mLayoutAlgorithm.mStackRect.right) {
- return;
- }
-
- // The user intentionally tapped on the background, which is like a tap on the "desktop".
- // Hide recents and transition to the launcher.
- EventBus.getDefault().send(new HideRecentsEvent(false, true));
- }
-
- /** Handles generic motion events */
- public boolean onGenericMotionEvent(MotionEvent ev) {
- if ((ev.getSource() & InputDevice.SOURCE_CLASS_POINTER) ==
- InputDevice.SOURCE_CLASS_POINTER) {
- int action = ev.getAction();
- switch (action & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_SCROLL:
- // Find the front most task and scroll the next task to the front
- float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
- if (vScroll > 0) {
- mSv.setRelativeFocusedTask(true, true /* stackTasksOnly */,
- false /* animated */);
- } else {
- mSv.setRelativeFocusedTask(false, true /* stackTasksOnly */,
- false /* animated */);
- }
- return true;
- }
- }
- return false;
- }
-
- /**** SwipeHelper Implementation ****/
-
- @Override
- public View getChildAtPosition(MotionEvent ev) {
- TaskView tv = findViewAtPoint((int) ev.getX(), (int) ev.getY());
- if (tv != null && canChildBeDismissed(tv)) {
- return tv;
- }
- return null;
- }
-
- @Override
- public boolean canChildBeDismissed(View v) {
- // Disallow dismissing an already dismissed task
- TaskView tv = (TaskView) v;
- Task task = tv.getTask();
- return !mSwipeHelperAnimations.containsKey(v) &&
- (mSv.getStack().indexOfTask(task) != -1);
- }
-
- /**
- * Starts a manual drag that goes through the same swipe helper path.
- */
- public void onBeginManualDrag(TaskView v) {
- mActiveTaskView = v;
- mSwipeHelperAnimations.put(v, null);
- onBeginDrag(v);
- }
-
- @Override
- public void onBeginDrag(View v) {
- TaskView tv = (TaskView) v;
-
- // Disable clipping with the stack while we are swiping
- tv.setClipViewInStack(false);
- // Disallow touch events from this task view
- tv.setTouchEnabled(false);
- // Disallow parents from intercepting touch events
- final ViewParent parent = mSv.getParent();
- if (parent != null) {
- parent.requestDisallowInterceptTouchEvent(true);
- }
-
- // Add this task to the set of tasks we are deleting
- mSv.addIgnoreTask(tv.getTask());
-
- // Determine if we are animating the other tasks while dismissing this task
- mCurrentTasks = new ArrayList<Task>(mSv.getStack().getTasks());
- MutableBoolean isFrontMostTask = new MutableBoolean(false);
- Task anchorTask = mSv.findAnchorTask(mCurrentTasks, isFrontMostTask);
- TaskStackLayoutAlgorithm layoutAlgorithm = mSv.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mSv.getScroller();
- if (anchorTask != null) {
- // Get the current set of task transforms
- mSv.getCurrentTaskTransforms(mCurrentTasks, mCurrentTaskTransforms);
-
- // Get the stack scroll of the task to anchor to (since we are removing something, the
- // front most task will be our anchor task)
- float prevAnchorTaskScroll = 0;
- boolean pullStackForward = mCurrentTasks.size() > 0;
- if (pullStackForward) {
- if (Recents.getConfiguration().isLowRamDevice) {
- float index = layoutAlgorithm.getStackScrollForTask(anchorTask);
- prevAnchorTaskScroll = mSv.getStackAlgorithm().mTaskStackLowRamLayoutAlgorithm
- .getScrollPForTask((int) index);
- } else {
- prevAnchorTaskScroll = layoutAlgorithm.getStackScrollForTask(anchorTask);
- }
- }
-
- // Calculate where the views would be without the deleting tasks
- mSv.updateLayoutAlgorithm(false /* boundScroll */);
-
- float newStackScroll = stackScroller.getStackScroll();
- if (isFrontMostTask.value) {
- // Bound the stack scroll to pull tasks forward if necessary
- newStackScroll = stackScroller.getBoundedStackScroll(newStackScroll);
- } else if (pullStackForward) {
- // Otherwise, offset the scroll by the movement of the anchor task
- float anchorTaskScroll =
- layoutAlgorithm.getStackScrollForTaskIgnoreOverrides(anchorTask);
- if (Recents.getConfiguration().isLowRamDevice) {
- float index = layoutAlgorithm.getStackScrollForTask(anchorTask);
- anchorTaskScroll = mSv.getStackAlgorithm().mTaskStackLowRamLayoutAlgorithm
- .getScrollPForTask((int) index);
- }
- float stackScrollOffset = (anchorTaskScroll - prevAnchorTaskScroll);
- if (layoutAlgorithm.getFocusState() != TaskStackLayoutAlgorithm.STATE_FOCUSED
- && !Recents.getConfiguration().isLowRamDevice) {
- // If we are focused, we don't want the front task to move, but otherwise, we
- // allow the back task to move up, and the front task to move back
- stackScrollOffset *= 0.75f;
- }
- newStackScroll = stackScroller.getBoundedStackScroll(stackScroller.getStackScroll()
- + stackScrollOffset);
- }
-
- // Pick up the newly visible views, not including the deleting tasks
- mSv.bindVisibleTaskViews(newStackScroll, true /* ignoreTaskOverrides */);
-
- // Get the final set of task transforms (with task removed)
- mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED,
- mCurrentTasks, true /* ignoreTaskOverrides */, mFinalTaskTransforms);
-
- // Set the target to scroll towards upon dismissal
- mTargetStackScroll = newStackScroll;
-
- /*
- * Post condition: All views that will be visible as a part of the gesture are retrieved
- * and at their initial positions. The stack is still at the current
- * scroll, but the layout is updated without the task currently being
- * dismissed. The final layout is in the unfocused stack state, which
- * will be applied when the current task is dismissed.
- */
- }
- }
-
- @Override
- public boolean updateSwipeProgress(View v, boolean dismissable, float swipeProgress) {
- // Only update the swipe progress for the surrounding tasks if the dismiss animation was not
- // preempted from a call to cancelNonDismissTaskAnimations
- if ((mActiveTaskView == v || mSwipeHelperAnimations.containsKey(v)) &&
- !Recents.getConfiguration().isLowRamDevice) {
- updateTaskViewTransforms(
- Interpolators.FAST_OUT_SLOW_IN.getInterpolation(swipeProgress));
- }
- return true;
- }
-
- /**
- * Called after the {@link TaskView} is finished animating away.
- */
- @Override
- public void onChildDismissed(View v) {
- TaskView tv = (TaskView) v;
-
- // Re-enable clipping with the stack (we will reuse this view)
- tv.setClipViewInStack(true);
- // Re-enable touch events from this task view
- tv.setTouchEnabled(true);
- // Update the scroll to the final scroll position before laying out the tasks during dismiss
- if (mSwipeHelperAnimations.containsKey(v)) {
- mSv.getScroller().setStackScroll(mTargetStackScroll, null);
- }
- // Remove the task view from the stack, ignoring the animation if we've started dragging
- // again
- EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv,
- mSwipeHelperAnimations.containsKey(v)
- ? new AnimationProps(TaskStackView.DEFAULT_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN)
- : null));
- // Only update the final scroll and layout state (set in onBeginDrag()) if the dismiss
- // animation was not preempted from a call to cancelNonDismissTaskAnimations
- if (mSwipeHelperAnimations.containsKey(v)) {
- // Update the focus state to the final focus state
- mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
- mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
- // Stop tracking this deletion animation
- mSwipeHelperAnimations.remove(v);
- }
- // Keep track of deletions by keyboard
- MetricsLogger.histogram(tv.getContext(), "overview_task_dismissed_source",
- Constants.Metrics.DismissSourceSwipeGesture);
- }
-
- /**
- * Called after the {@link TaskView} is finished animating back into the list.
- * onChildDismissed() calls.
- */
- @Override
- public void onChildSnappedBack(View v, float targetLeft) {
- TaskView tv = (TaskView) v;
-
- // Re-enable clipping with the stack
- tv.setClipViewInStack(true);
- // Re-enable touch events from this task view
- tv.setTouchEnabled(true);
-
- // Stop tracking this deleting task, and update the layout to include this task again. The
- // stack scroll does not need to be reset, since the scroll has not actually changed in
- // onBeginDrag().
- mSv.removeIgnoreTask(tv.getTask());
- mSv.updateLayoutAlgorithm(false /* boundScroll */);
- mSv.relayoutTaskViews(AnimationProps.IMMEDIATE);
- mSwipeHelperAnimations.remove(v);
- }
-
- @Override
- public void onDragCancelled(View v) {
- // Do nothing
- }
-
- @Override
- public boolean isAntiFalsingNeeded() {
- return false;
- }
-
- @Override
- public float getFalsingThresholdFactor() {
- return 0;
- }
-
- /**
- * Interpolates the non-deleting tasks to their final transforms from their current transforms.
- */
- private void updateTaskViewTransforms(float dismissFraction) {
- List<TaskView> taskViews = mSv.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = 0; i < taskViewCount; i++) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
-
- if (mSv.isIgnoredTask(task)) {
- continue;
- }
-
- int taskIndex = mCurrentTasks.indexOf(task);
- if (taskIndex == -1) {
- // If a task was added to the stack view after the start of the dismiss gesture,
- // just ignore it
- continue;
- }
-
- TaskViewTransform fromTransform = mCurrentTaskTransforms.get(taskIndex);
- TaskViewTransform toTransform = mFinalTaskTransforms.get(taskIndex);
-
- mTmpTransform.copyFrom(fromTransform);
- // We only really need to interpolate the bounds, progress and translation
- mTmpTransform.rect.set(Utilities.RECTF_EVALUATOR.evaluate(dismissFraction,
- fromTransform.rect, toTransform.rect));
- mTmpTransform.dimAlpha = fromTransform.dimAlpha + (toTransform.dimAlpha -
- fromTransform.dimAlpha) * dismissFraction;
- mTmpTransform.viewOutlineAlpha = fromTransform.viewOutlineAlpha +
- (toTransform.viewOutlineAlpha - fromTransform.viewOutlineAlpha) *
- dismissFraction;
- mTmpTransform.translationZ = fromTransform.translationZ +
- (toTransform.translationZ - fromTransform.translationZ) * dismissFraction;
-
- mSv.updateTaskViewToTransform(tv, mTmpTransform, AnimationProps.IMMEDIATE);
- }
- }
-
- /** Returns the view at the specified coordinates */
- private TaskView findViewAtPoint(int x, int y) {
- List<Task> tasks = mSv.getStack().getTasks();
- int taskCount = tasks.size();
- for (int i = taskCount - 1; i >= 0; i--) {
- TaskView tv = mSv.getChildViewForTask(tasks.get(i));
- if (tv != null && tv.getVisibility() == View.VISIBLE) {
- if (mSv.isTouchPointInView(x, y, tv)) {
- return tv;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the scaled size used to calculate the dismiss fraction.
- */
- public float getScaledDismissSize() {
- return 1.5f * Math.max(mSv.getWidth(), mSv.getHeight());
- }
-
- /**
- * Returns whether swiping is enabled.
- */
- private boolean isSwipingEnabled() {
- return !mSv.useGridLayout();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
deleted file mode 100644
index f0278a6..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Outline;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.FloatProperty;
-import android.util.Property;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewDebug;
-import android.view.ViewOutlineProvider;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivity;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.LaunchTaskEvent;
-import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
-import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndCancelledEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import com.android.systemui.shared.recents.view.AnimateableViewBounds;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-
-/**
- * A {@link TaskView} represents a fixed view of a task. Because the TaskView's layout is directed
- * solely by the {@link TaskStackView}, we make it a fixed size layout which allows relayouts down
- * the view hierarchy, but not upwards from any of its children (the TaskView will relayout itself
- * with the previous bounds if any child requests layout).
- */
-public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks,
- TaskStackAnimationHelper.Callbacks, View.OnClickListener, View.OnLongClickListener {
-
- /** The TaskView callbacks */
- interface TaskViewCallbacks {
- void onTaskViewClipStateChanged(TaskView tv);
- }
-
- /**
- * The dim overlay is generally calculated from the task progress, but occasionally (like when
- * launching) needs to be animated independently of the task progress. This call is only used
- * when animating the task into Recents, when the header dim is already applied
- */
- public static final Property<TaskView, Float> DIM_ALPHA_WITHOUT_HEADER =
- new FloatProperty<TaskView>("dimAlphaWithoutHeader") {
- @Override
- public void setValue(TaskView tv, float dimAlpha) {
- tv.setDimAlphaWithoutHeader(dimAlpha);
- }
-
- @Override
- public Float get(TaskView tv) {
- return tv.getDimAlpha();
- }
- };
-
- /**
- * The dim overlay is generally calculated from the task progress, but occasionally (like when
- * launching) needs to be animated independently of the task progress.
- */
- public static final Property<TaskView, Float> DIM_ALPHA =
- new FloatProperty<TaskView>("dimAlpha") {
- @Override
- public void setValue(TaskView tv, float dimAlpha) {
- tv.setDimAlpha(dimAlpha);
- }
-
- @Override
- public Float get(TaskView tv) {
- return tv.getDimAlpha();
- }
- };
-
- /**
- * The dim overlay is generally calculated from the task progress, but occasionally (like when
- * launching) needs to be animated independently of the task progress.
- */
- public static final Property<TaskView, Float> VIEW_OUTLINE_ALPHA =
- new FloatProperty<TaskView>("viewOutlineAlpha") {
- @Override
- public void setValue(TaskView tv, float alpha) {
- tv.getViewBounds().setAlpha(alpha);
- }
-
- @Override
- public Float get(TaskView tv) {
- return tv.getViewBounds().getAlpha();
- }
- };
-
- @ViewDebug.ExportedProperty(category="recents")
- private float mDimAlpha;
- private float mActionButtonTranslationZ;
-
- @ViewDebug.ExportedProperty(deepExport=true, prefix="task_")
- private Task mTask;
- private boolean mTaskBound;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mClipViewInStack = true;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mTouchExplorationEnabled;
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mIsDisabledInSafeMode;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="view_bounds_")
- private AnimateableViewBounds mViewBounds;
-
- private AnimatorSet mTransformAnimation;
- private ObjectAnimator mDimAnimator;
- private ObjectAnimator mOutlineAnimator;
- private final TaskViewTransform mTargetAnimationTransform = new TaskViewTransform();
- private ArrayList<Animator> mTmpAnimators = new ArrayList<>();
-
- @ViewDebug.ExportedProperty(deepExport=true, prefix="thumbnail_")
- protected TaskViewThumbnail mThumbnailView;
- @ViewDebug.ExportedProperty(deepExport=true, prefix="header_")
- protected TaskViewHeader mHeaderView;
- private View mActionButtonView;
- private View mIncompatibleAppToastView;
- private TaskViewCallbacks mCb;
-
- @ViewDebug.ExportedProperty(category="recents")
- private Point mDownTouchPos = new Point();
-
- private Toast mDisabledAppToast;
-
- public TaskView(Context context) {
- this(context, null);
- }
-
- public TaskView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- RecentsConfiguration config = Recents.getConfiguration();
- Resources res = context.getResources();
- mViewBounds = createOutlineProvider();
- if (config.fakeShadows) {
- setBackground(new FakeShadowDrawable(res, config));
- }
- setOutlineProvider(mViewBounds);
- setOnLongClickListener(this);
- setAccessibilityDelegate(new TaskViewAccessibilityDelegate(this));
- }
-
- /** Set callback */
- void setCallbacks(TaskViewCallbacks cb) {
- mCb = cb;
- }
-
- /**
- * Called from RecentsActivity when it is relaunched.
- */
- void onReload(boolean isResumingFromVisible) {
- resetNoUserInteractionState();
- if (!isResumingFromVisible) {
- resetViewProperties();
- }
- }
-
- /** Gets the task */
- public Task getTask() {
- return mTask;
- }
-
- /* Create an outline provider to clip and outline the view */
- protected AnimateableViewBounds createOutlineProvider() {
- return new AnimateableViewBounds(this, mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_task_view_shadow_rounded_corners_radius));
- }
-
- /** Returns the view bounds. */
- AnimateableViewBounds getViewBounds() {
- return mViewBounds;
- }
-
- @Override
- protected void onFinishInflate() {
- // Bind the views
- mHeaderView = findViewById(R.id.task_view_bar);
- mThumbnailView = findViewById(R.id.task_view_thumbnail);
- mThumbnailView.updateClipToTaskBar(mHeaderView);
- mActionButtonView = findViewById(R.id.lock_to_app_fab);
- mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- // Set the outline to match the FAB background
- outline.setOval(0, 0, mActionButtonView.getWidth(), mActionButtonView.getHeight());
- outline.setAlpha(0.35f);
- }
- });
- mActionButtonView.setOnClickListener(this);
- mActionButtonTranslationZ = mActionButtonView.getTranslationZ();
- }
-
- /**
- * Update the task view when the configuration changes.
- */
- protected void onConfigurationChanged() {
- mHeaderView.onConfigurationChanged();
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- if (w > 0 && h > 0) {
- mHeaderView.onTaskViewSizeChanged(w, h);
- mThumbnailView.onTaskViewSizeChanged(w, h);
-
- mActionButtonView.setTranslationX(w - getMeasuredWidth());
- mActionButtonView.setTranslationY(h - getMeasuredHeight());
- }
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mDownTouchPos.set((int) (ev.getX() * getScaleX()), (int) (ev.getY() * getScaleY()));
- }
- return super.onInterceptTouchEvent(ev);
- }
-
- @Override
- protected void measureContents(int width, int height) {
- int widthWithoutPadding = width - mPaddingLeft - mPaddingRight;
- int heightWithoutPadding = height - mPaddingTop - mPaddingBottom;
- int widthSpec = MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY);
- int heightSpec = MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY);
-
- // Measure the content
- measureChildren(widthSpec, heightSpec);
-
- setMeasuredDimension(width, height);
- }
-
- void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform,
- AnimationProps toAnimation, ValueAnimator.AnimatorUpdateListener updateCallback) {
- RecentsConfiguration config = Recents.getConfiguration();
- cancelTransformAnimation();
-
- // Compose the animations for the transform
- mTmpAnimators.clear();
- toTransform.applyToTaskView(this, mTmpAnimators, toAnimation, !config.fakeShadows);
- if (toAnimation.isImmediate()) {
- if (Float.compare(getDimAlpha(), toTransform.dimAlpha) != 0) {
- setDimAlpha(toTransform.dimAlpha);
- }
- if (Float.compare(mViewBounds.getAlpha(), toTransform.viewOutlineAlpha) != 0) {
- mViewBounds.setAlpha(toTransform.viewOutlineAlpha);
- }
- // Manually call back to the animator listener and update callback
- if (toAnimation.getListener() != null) {
- toAnimation.getListener().onAnimationEnd(null);
- }
- if (updateCallback != null) {
- updateCallback.onAnimationUpdate(null);
- }
- } else {
- // Both the progress and the update are a function of the bounds movement of the task
- if (Float.compare(getDimAlpha(), toTransform.dimAlpha) != 0) {
- mDimAnimator = ObjectAnimator.ofFloat(this, DIM_ALPHA, getDimAlpha(),
- toTransform.dimAlpha);
- mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, mDimAnimator));
- }
- if (Float.compare(mViewBounds.getAlpha(), toTransform.viewOutlineAlpha) != 0) {
- mOutlineAnimator = ObjectAnimator.ofFloat(this, VIEW_OUTLINE_ALPHA,
- mViewBounds.getAlpha(), toTransform.viewOutlineAlpha);
- mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, mOutlineAnimator));
- }
- if (updateCallback != null) {
- ValueAnimator updateCallbackAnim = ValueAnimator.ofInt(0, 1);
- updateCallbackAnim.addUpdateListener(updateCallback);
- mTmpAnimators.add(toAnimation.apply(AnimationProps.BOUNDS, updateCallbackAnim));
- }
-
- // Create the animator
- mTransformAnimation = toAnimation.createAnimator(mTmpAnimators);
- mTransformAnimation.start();
- mTargetAnimationTransform.copyFrom(toTransform);
- }
- }
-
- /** Resets this view's properties */
- void resetViewProperties() {
- cancelTransformAnimation();
- setDimAlpha(0);
- setVisibility(View.VISIBLE);
- getViewBounds().reset();
- getHeaderView().reset();
- TaskViewTransform.reset(this);
-
- mActionButtonView.setScaleX(1f);
- mActionButtonView.setScaleY(1f);
- mActionButtonView.setAlpha(0f);
- mActionButtonView.setTranslationX(0f);
- mActionButtonView.setTranslationY(0f);
- mActionButtonView.setTranslationZ(mActionButtonTranslationZ);
- if (mIncompatibleAppToastView != null) {
- mIncompatibleAppToastView.setVisibility(View.INVISIBLE);
- }
- }
-
- /**
- * @return whether we are animating towards {@param transform}
- */
- boolean isAnimatingTo(TaskViewTransform transform) {
- return mTransformAnimation != null && mTransformAnimation.isStarted()
- && mTargetAnimationTransform.isSame(transform);
- }
-
- /**
- * Cancels any current transform animations.
- */
- public void cancelTransformAnimation() {
- cancelDimAnimationIfExists();
- Utilities.cancelAnimationWithoutCallbacks(mTransformAnimation);
- Utilities.cancelAnimationWithoutCallbacks(mOutlineAnimator);
- }
-
- private void cancelDimAnimationIfExists() {
- if (mDimAnimator != null) {
- mDimAnimator.cancel();
- }
- }
-
- /** Enables/disables handling touch on this task view. */
- public void setTouchEnabled(boolean enabled) {
- setOnClickListener(enabled ? this : null);
- }
-
- /** Animates this task view if the user does not interact with the stack after a certain time. */
- public void startNoUserInteractionAnimation() {
- mHeaderView.startNoUserInteractionAnimation();
- }
-
- /** Mark this task view that the user does has not interacted with the stack after a certain time. */
- void setNoUserInteractionState() {
- mHeaderView.setNoUserInteractionState();
- }
-
- /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
- void resetNoUserInteractionState() {
- mHeaderView.resetNoUserInteractionState();
- }
-
- /** Dismisses this task. */
- void dismissTask() {
- // Animate out the view and call the callback
- final TaskView tv = this;
- DismissTaskViewEvent dismissEvent = new DismissTaskViewEvent(tv);
- dismissEvent.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- EventBus.getDefault().send(new TaskViewDismissedEvent(mTask, tv,
- new AnimationProps(TaskStackView.DEFAULT_SYNC_STACK_DURATION,
- Interpolators.FAST_OUT_SLOW_IN)));
- }
- });
- EventBus.getDefault().send(dismissEvent);
- }
-
- /**
- * Returns whether this view should be clipped, or any views below should clip against this
- * view.
- */
- boolean shouldClipViewInStack() {
- if (getVisibility() != View.VISIBLE || Recents.getConfiguration().isLowRamDevice) {
- return false;
- }
- return mClipViewInStack;
- }
-
- /** Sets whether this view should be clipped, or clipped against. */
- void setClipViewInStack(boolean clip) {
- if (clip != mClipViewInStack) {
- mClipViewInStack = clip;
- if (mCb != null) {
- mCb.onTaskViewClipStateChanged(this);
- }
- }
- }
-
- public TaskViewHeader getHeaderView() {
- return mHeaderView;
- }
-
- /**
- * Sets the current dim.
- */
- public void setDimAlpha(float dimAlpha) {
- mDimAlpha = dimAlpha;
- mThumbnailView.setDimAlpha(dimAlpha);
- mHeaderView.setDimAlpha(dimAlpha);
- }
-
- /**
- * Sets the current dim without updating the header's dim.
- */
- public void setDimAlphaWithoutHeader(float dimAlpha) {
- mDimAlpha = dimAlpha;
- mThumbnailView.setDimAlpha(dimAlpha);
- }
-
- /**
- * Returns the current dim.
- */
- public float getDimAlpha() {
- return mDimAlpha;
- }
-
- /**
- * Explicitly sets the focused state of this task.
- */
- public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
- if (isFocused) {
- if (requestViewFocus && !isFocused()) {
- requestFocus();
- }
- } else {
- if (isAccessibilityFocused() && mTouchExplorationEnabled) {
- clearAccessibilityFocus();
- }
- }
- }
-
- /**
- * Shows the action button.
- * @param fadeIn whether or not to animate the action button in.
- * @param fadeInDuration the duration of the action button animation, only used if
- * {@param fadeIn} is true.
- */
- public void showActionButton(boolean fadeIn, int fadeInDuration) {
- mActionButtonView.setVisibility(View.VISIBLE);
-
- if (fadeIn && mActionButtonView.getAlpha() < 1f) {
- mActionButtonView.animate()
- .alpha(1f)
- .scaleX(1f)
- .scaleY(1f)
- .setDuration(fadeInDuration)
- .setInterpolator(Interpolators.ALPHA_IN)
- .start();
- } else {
- mActionButtonView.setScaleX(1f);
- mActionButtonView.setScaleY(1f);
- mActionButtonView.setAlpha(1f);
- mActionButtonView.setTranslationZ(mActionButtonTranslationZ);
- }
- }
-
- /**
- * Immediately hides the action button.
- *
- * @param fadeOut whether or not to animate the action button out.
- */
- public void hideActionButton(boolean fadeOut, int fadeOutDuration, boolean scaleDown,
- final Animator.AnimatorListener animListener) {
- if (fadeOut && mActionButtonView.getAlpha() > 0f) {
- if (scaleDown) {
- float toScale = 0.9f;
- mActionButtonView.animate()
- .scaleX(toScale)
- .scaleY(toScale);
- }
- mActionButtonView.animate()
- .alpha(0f)
- .setDuration(fadeOutDuration)
- .setInterpolator(Interpolators.ALPHA_OUT)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- if (animListener != null) {
- animListener.onAnimationEnd(null);
- }
- mActionButtonView.setVisibility(View.INVISIBLE);
- }
- })
- .start();
- } else {
- mActionButtonView.setAlpha(0f);
- mActionButtonView.setVisibility(View.INVISIBLE);
- if (animListener != null) {
- animListener.onAnimationEnd(null);
- }
- }
- }
-
- /**** TaskStackAnimationHelper.Callbacks Implementation ****/
-
- @Override
- public void onPrepareLaunchTargetForEnterAnimation() {
- // These values will be animated in when onStartLaunchTargetEnterAnimation() is called
- setDimAlphaWithoutHeader(0);
- mActionButtonView.setAlpha(0f);
- if (mIncompatibleAppToastView != null &&
- mIncompatibleAppToastView.getVisibility() == View.VISIBLE) {
- mIncompatibleAppToastView.setAlpha(0f);
- }
- }
-
- @Override
- public void onStartLaunchTargetEnterAnimation(TaskViewTransform transform, int duration,
- boolean screenPinningEnabled, ReferenceCountedTrigger postAnimationTrigger) {
- cancelDimAnimationIfExists();
-
- // Dim the view after the app window transitions down into recents
- postAnimationTrigger.increment();
- AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
- mDimAnimator = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
- DIM_ALPHA_WITHOUT_HEADER, getDimAlpha(), transform.dimAlpha));
- mDimAnimator.addListener(postAnimationTrigger.decrementOnAnimationEnd());
- mDimAnimator.start();
-
- if (screenPinningEnabled) {
- showActionButton(true /* fadeIn */, duration /* fadeInDuration */);
- }
-
- if (mIncompatibleAppToastView != null &&
- mIncompatibleAppToastView.getVisibility() == View.VISIBLE) {
- mIncompatibleAppToastView.animate()
- .alpha(1f)
- .setDuration(duration)
- .setInterpolator(Interpolators.ALPHA_IN)
- .start();
- }
- }
-
- @Override
- public void onStartLaunchTargetLaunchAnimation(int duration, boolean screenPinningRequested,
- ReferenceCountedTrigger postAnimationTrigger) {
- Utilities.cancelAnimationWithoutCallbacks(mDimAnimator);
-
- // Un-dim the view before/while launching the target
- AnimationProps animation = new AnimationProps(duration, Interpolators.ALPHA_OUT);
- mDimAnimator = animation.apply(AnimationProps.DIM_ALPHA, ObjectAnimator.ofFloat(this,
- DIM_ALPHA, getDimAlpha(), 0));
- mDimAnimator.start();
-
- postAnimationTrigger.increment();
- hideActionButton(true /* fadeOut */, duration,
- !screenPinningRequested /* scaleDown */,
- postAnimationTrigger.decrementOnAnimationEnd());
- }
-
- @Override
- public void onStartFrontTaskEnterAnimation(boolean screenPinningEnabled) {
- if (screenPinningEnabled) {
- showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
- }
- }
-
- /**** TaskCallbacks Implementation ****/
-
- public void onTaskBound(Task t, boolean touchExplorationEnabled, int displayOrientation,
- Rect displayRect) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- mTouchExplorationEnabled = touchExplorationEnabled;
- mTask = t;
- mTaskBound = true;
- mTask.addCallback(this);
- mIsDisabledInSafeMode = !mTask.isSystemApp && ssp.isInSafeMode();
- mThumbnailView.bindToTask(mTask, mIsDisabledInSafeMode, displayOrientation, displayRect);
- mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
-
- if (!t.isDockable && ssp.hasDockedTask()) {
- if (mIncompatibleAppToastView == null) {
- mIncompatibleAppToastView = Utilities.findViewStubById(this,
- R.id.incompatible_app_toast_stub).inflate();
- TextView msg = findViewById(com.android.internal.R.id.message);
- msg.setText(R.string.dock_non_resizeble_failed_to_dock_text);
- }
- mIncompatibleAppToastView.setVisibility(View.VISIBLE);
- } else if (mIncompatibleAppToastView != null) {
- mIncompatibleAppToastView.setVisibility(View.INVISIBLE);
- }
- }
-
- @Override
- public void onTaskDataLoaded(Task task, ThumbnailData thumbnailData) {
- if (mTaskBound) {
- // Update each of the views to the new task data
- mThumbnailView.onTaskDataLoaded(thumbnailData);
- mHeaderView.onTaskDataLoaded();
- }
- }
-
- @Override
- public void onTaskDataUnloaded() {
- // Unbind each of the views from the task and remove the task callback
- mTask.removeCallback(this);
- mThumbnailView.unbindFromTask();
- mHeaderView.unbindFromTask(mTouchExplorationEnabled);
- mTaskBound = false;
- }
-
- @Override
- public void onTaskWindowingModeChanged() {
- // Force rebind the header, the thumbnail does not change due to stack changes
- mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
- mHeaderView.onTaskDataLoaded();
- }
-
- /**** View.OnClickListener Implementation ****/
-
- @Override
- public void onClick(final View v) {
- if (mIsDisabledInSafeMode) {
- Context context = getContext();
- String msg = context.getString(R.string.recents_launch_disabled_message, mTask.title);
- if (mDisabledAppToast != null) {
- mDisabledAppToast.cancel();
- }
- mDisabledAppToast = Toast.makeText(context, msg, Toast.LENGTH_SHORT);
- mDisabledAppToast.show();
- return;
- }
-
- boolean screenPinningRequested = false;
- if (v == mActionButtonView) {
- // Reset the translation of the action button before we animate it out
- mActionButtonView.setTranslationZ(0f);
- screenPinningRequested = true;
- }
- EventBus.getDefault().send(new LaunchTaskEvent(this, mTask, null, screenPinningRequested));
-
- MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
- mTask.key.getComponent().toString());
- }
-
- /**** View.OnLongClickListener Implementation ****/
-
- @Override
- public boolean onLongClick(View v) {
- if (!Recents.getConfiguration().dragToSplitEnabled) {
- return false;
- }
- SystemServicesProxy ssp = Recents.getSystemServices();
- boolean inBounds = false;
- Rect clipBounds = new Rect(mViewBounds.getClipBounds());
- if (!clipBounds.isEmpty()) {
- // If we are clipping the view to the bounds, manually do the hit test.
- clipBounds.scale(getScaleX());
- inBounds = clipBounds.contains(mDownTouchPos.x, mDownTouchPos.y);
- } else {
- // Otherwise just make sure we're within the view's bounds.
- inBounds = mDownTouchPos.x <= getWidth() && mDownTouchPos.y <= getHeight();
- }
- if (v == this && inBounds && !ssp.hasDockedTask()) {
- // Start listening for drag events
- setClipViewInStack(false);
-
- mDownTouchPos.x += ((1f - getScaleX()) * getWidth()) / 2;
- mDownTouchPos.y += ((1f - getScaleY()) * getHeight()) / 2;
-
- EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
- EventBus.getDefault().send(new DragStartEvent(mTask, this, mDownTouchPos));
- return true;
- }
- return false;
- }
-
- /**** Events ****/
-
- public final void onBusEvent(DragEndEvent event) {
- if (!(event.dropTarget instanceof DockState)) {
- event.addPostAnimationCallback(() -> {
- // Reset the clip state for the drag view after the end animation completes
- setClipViewInStack(true);
- });
- }
- EventBus.getDefault().unregister(this);
- }
-
- public final void onBusEvent(DragEndCancelledEvent event) {
- // Reset the clip state for the drag view after the cancel animation completes
- event.addPostAnimationCallback(() -> {
- setClipViewInStack(true);
- });
- }
-
- public void dump(String prefix, PrintWriter writer) {
- String innerPrefix = prefix + " ";
-
- writer.print(prefix); writer.print("TaskView");
- writer.print(" mTask="); writer.print(mTask.key.id);
- writer.println();
-
- mThumbnailView.dump(innerPrefix, writer);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
deleted file mode 100644
index 5bb5b2d..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.recents.views;
-
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.graphics.Point;
-import android.os.Bundle;
-import android.util.SparseArray;
-import android.view.View;
-import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
-import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-
-public class TaskViewAccessibilityDelegate extends View.AccessibilityDelegate {
- private static final String TAG = "TaskViewAccessibilityDelegate";
-
- private final TaskView mTaskView;
-
- protected static final int SPLIT_TASK_TOP = R.id.action_split_task_to_top;
- protected static final int SPLIT_TASK_LEFT = R.id.action_split_task_to_left;
- protected static final int SPLIT_TASK_RIGHT = R.id.action_split_task_to_right;
-
- protected final SparseArray<AccessibilityAction> mActions = new SparseArray<>();
-
- public TaskViewAccessibilityDelegate(TaskView taskView) {
- mTaskView = taskView;
- Context context = taskView.getContext();
- mActions.put(SPLIT_TASK_TOP, new AccessibilityAction(SPLIT_TASK_TOP,
- context.getString(R.string.recents_accessibility_split_screen_top)));
- mActions.put(SPLIT_TASK_LEFT, new AccessibilityAction(SPLIT_TASK_LEFT,
- context.getString(R.string.recents_accessibility_split_screen_left)));
- mActions.put(SPLIT_TASK_RIGHT, new AccessibilityAction(SPLIT_TASK_RIGHT,
- context.getString(R.string.recents_accessibility_split_screen_right)));
- }
-
- @Override
- public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
- super.onInitializeAccessibilityNodeInfo(host, info);
- if (ActivityTaskManager.supportsSplitScreenMultiWindow(mTaskView.getContext())
- && !Recents.getSystemServices().hasDockedTask()) {
- DockState[] dockStates = Recents.getConfiguration()
- .getDockStatesForCurrentOrientation();
- for (DockState dockState: dockStates) {
- if (dockState == DockState.TOP) {
- info.addAction(mActions.get(SPLIT_TASK_TOP));
- } else if (dockState == DockState.LEFT) {
- info.addAction(mActions.get(SPLIT_TASK_LEFT));
- } else if (dockState == DockState.RIGHT) {
- info.addAction(mActions.get(SPLIT_TASK_RIGHT));
- }
- }
- }
- }
-
- @Override
- public boolean performAccessibilityAction(View host, int action, Bundle args) {
- if (action == SPLIT_TASK_TOP) {
- simulateDragIntoMultiwindow(DockState.TOP);
- } else if (action == SPLIT_TASK_LEFT) {
- simulateDragIntoMultiwindow(DockState.LEFT);
- } else if (action == SPLIT_TASK_RIGHT) {
- simulateDragIntoMultiwindow(DockState.RIGHT);
- } else {
- return super.performAccessibilityAction(host, action, args);
- }
- return true;
- }
-
- /** Simulate a user drag event to split the screen to the respected side */
- private void simulateDragIntoMultiwindow(DockState dockState) {
- EventBus.getDefault().send(new DragStartEvent(mTaskView.getTask(), mTaskView,
- new Point(0,0), false /* isUserTouchInitiated */));
- EventBus.getDefault().send(new DragEndEvent(mTaskView.getTask(), mTaskView, dockState));
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
deleted file mode 100644
index de42914..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ /dev/null
@@ -1,685 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.annotation.Nullable;
-import android.app.AppGlobals;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
-import android.os.CountDownTimer;
-import androidx.core.graphics.ColorUtils;
-import android.util.AttributeSet;
-import android.util.IconDrawableFactory;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewAnimationUtils;
-import android.view.ViewDebug;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.LaunchTaskEvent;
-import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.shared.system.ActivityManagerWrapper;
-import com.android.systemui.shared.system.PackageManagerWrapper;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-
-/* The task bar view */
-public class TaskViewHeader extends FrameLayout
- implements View.OnClickListener, View.OnLongClickListener {
-
- private static IconDrawableFactory sDrawableFactory;
-
- private static final float HIGHLIGHT_LIGHTNESS_INCREMENT = 0.075f;
- private static final float OVERLAY_LIGHTNESS_INCREMENT = -0.0625f;
- private static final int OVERLAY_REVEAL_DURATION = 250;
- private static final long FOCUS_INDICATOR_INTERVAL_MS = 30;
-
- /**
- * A color drawable that draws a slight highlight at the top to help it stand out.
- */
- private class HighlightColorDrawable extends Drawable {
-
- private Paint mHighlightPaint = new Paint();
- private Paint mBackgroundPaint = new Paint();
- private int mColor;
- private float mDimAlpha;
-
- public HighlightColorDrawable() {
- mBackgroundPaint.setColor(Color.argb(255, 0, 0, 0));
- mBackgroundPaint.setAntiAlias(true);
- mHighlightPaint.setColor(Color.argb(255, 255, 255, 255));
- mHighlightPaint.setAntiAlias(true);
- }
-
- public void setColorAndDim(int color, float dimAlpha) {
- if (mColor != color || Float.compare(mDimAlpha, dimAlpha) != 0) {
- mColor = color;
- mDimAlpha = dimAlpha;
- if (mShouldDarkenBackgroundColor) {
- color = getSecondaryColor(color, false /* useLightOverlayColor */);
- }
- mBackgroundPaint.setColor(color);
-
- ColorUtils.colorToHSL(color, mTmpHSL);
- // TODO: Consider using the saturation of the color to adjust the lightness as well
- mTmpHSL[2] = Math.min(1f,
- mTmpHSL[2] + HIGHLIGHT_LIGHTNESS_INCREMENT * (1.0f - dimAlpha));
- mHighlightPaint.setColor(ColorUtils.HSLToColor(mTmpHSL));
-
- invalidateSelf();
- }
- }
-
- @Override
- public void setColorFilter(@Nullable ColorFilter colorFilter) {
- // Do nothing
- }
-
- @Override
- public void setAlpha(int alpha) {
- // Do nothing
- }
-
- @Override
- public void draw(Canvas canvas) {
- // Draw the highlight at the top edge (but put the bottom edge just out of view)
- canvas.drawRoundRect(0, 0, mTaskViewRect.width(),
- 2 * Math.max(mHighlightHeight, mCornerRadius),
- mCornerRadius, mCornerRadius, mHighlightPaint);
-
- // Draw the background with the rounded corners
- canvas.drawRoundRect(0, mHighlightHeight, mTaskViewRect.width(),
- getHeight() + mCornerRadius,
- mCornerRadius, mCornerRadius, mBackgroundPaint);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.OPAQUE;
- }
-
- public int getColor() {
- return mColor;
- }
- }
-
- Task mTask;
-
- // Header views
- ImageView mIconView;
- TextView mTitleView;
- ImageView mMoveTaskButton;
- ImageView mDismissButton;
- FrameLayout mAppOverlayView;
- ImageView mAppIconView;
- ImageView mAppInfoView;
- TextView mAppTitleView;
- ProgressBar mFocusTimerIndicator;
-
- // Header drawables
- @ViewDebug.ExportedProperty(category="recents")
- Rect mTaskViewRect = new Rect();
- int mHeaderBarHeight;
- int mHeaderButtonPadding;
- int mCornerRadius;
- int mHighlightHeight;
- @ViewDebug.ExportedProperty(category="recents")
- float mDimAlpha;
- Drawable mLightDismissDrawable;
- Drawable mDarkDismissDrawable;
- Drawable mLightFullscreenIcon;
- Drawable mDarkFullscreenIcon;
- Drawable mLightInfoIcon;
- Drawable mDarkInfoIcon;
- int mTaskBarViewLightTextColor;
- int mTaskBarViewDarkTextColor;
- int mDisabledTaskBarBackgroundColor;
- String mDismissDescFormat;
- String mAppInfoDescFormat;
- int mTaskWindowingMode = WINDOWING_MODE_UNDEFINED;
-
- // Header background
- private HighlightColorDrawable mBackground;
- private HighlightColorDrawable mOverlayBackground;
- private float[] mTmpHSL = new float[3];
-
- // Header dim, which is only used when task view hardware layers are not used
- private Paint mDimLayerPaint = new Paint();
-
- // Whether the background color should be darkened to differentiate from the primary color.
- // Used in grid layout.
- private boolean mShouldDarkenBackgroundColor = false;
-
- private CountDownTimer mFocusTimerCountDown;
-
- public TaskViewHeader(Context context) {
- this(context, null);
- }
-
- public TaskViewHeader(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- setWillNotDraw(false);
-
- // Load the dismiss resources
- Resources res = context.getResources();
- mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
- mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
- mCornerRadius = Recents.getConfiguration().isGridEnabled ?
- res.getDimensionPixelSize(R.dimen.recents_grid_task_view_rounded_corners_radius) :
- res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
- mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
- mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
- mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
- mLightFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_light);
- mDarkFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_dark);
- mLightInfoIcon = context.getDrawable(R.drawable.recents_info_light);
- mDarkInfoIcon = context.getDrawable(R.drawable.recents_info_dark);
- mDisabledTaskBarBackgroundColor =
- context.getColor(R.color.recents_task_bar_disabled_background_color);
- mDismissDescFormat = mContext.getString(
- R.string.accessibility_recents_item_will_be_dismissed);
- mAppInfoDescFormat = mContext.getString(R.string.accessibility_recents_item_open_app_info);
-
- // Configure the background and dim
- mBackground = new HighlightColorDrawable();
- mBackground.setColorAndDim(Color.argb(255, 0, 0, 0), 0f);
- setBackground(mBackground);
- mOverlayBackground = new HighlightColorDrawable();
- mDimLayerPaint.setColor(Color.argb(255, 0, 0, 0));
- mDimLayerPaint.setAntiAlias(true);
- }
-
- /**
- * Resets this header along with the TaskView.
- */
- public void reset() {
- hideAppOverlay(true /* immediate */);
- }
-
- @Override
- protected void onFinishInflate() {
- SystemServicesProxy ssp = Recents.getSystemServices();
-
- // Initialize the icon and description views
- mIconView = findViewById(R.id.icon);
- mIconView.setOnLongClickListener(this);
- mTitleView = findViewById(R.id.title);
- mDismissButton = findViewById(R.id.dismiss_task);
-
- onConfigurationChanged();
- }
-
- /**
- * Programmatically sets the layout params for a header bar layout. This is necessary because
- * we can't get resources based on the current configuration, but instead need to get them
- * based on the device configuration.
- */
- private void updateLayoutParams(View icon, View title, View secondaryButton, View button) {
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, mHeaderBarHeight, Gravity.TOP);
- setLayoutParams(lp);
- lp = new FrameLayout.LayoutParams(mHeaderBarHeight, mHeaderBarHeight, Gravity.START);
- icon.setLayoutParams(lp);
- lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL);
- lp.setMarginStart(mHeaderBarHeight);
- lp.setMarginEnd(mMoveTaskButton != null
- ? 2 * mHeaderBarHeight
- : mHeaderBarHeight);
- title.setLayoutParams(lp);
- if (secondaryButton != null) {
- lp = new FrameLayout.LayoutParams(mHeaderBarHeight, mHeaderBarHeight, Gravity.END);
- lp.setMarginEnd(mHeaderBarHeight);
- secondaryButton.setLayoutParams(lp);
- secondaryButton.setPadding(mHeaderButtonPadding, mHeaderButtonPadding,
- mHeaderButtonPadding, mHeaderButtonPadding);
- }
- lp = new FrameLayout.LayoutParams(mHeaderBarHeight, mHeaderBarHeight, Gravity.END);
- button.setLayoutParams(lp);
- button.setPadding(mHeaderButtonPadding, mHeaderButtonPadding, mHeaderButtonPadding,
- mHeaderButtonPadding);
- }
-
- /**
- * Update the header view when the configuration changes.
- */
- public void onConfigurationChanged() {
- // Update the dimensions of everything in the header. We do this because we need to use
- // resources for the display, and not the current configuration.
- Resources res = getResources();
- int headerBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(getContext(),
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height_tablet_land,
- R.dimen.recents_task_view_header_height,
- R.dimen.recents_task_view_header_height_tablet_land,
- R.dimen.recents_grid_task_view_header_height);
- int headerButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(getContext(),
- R.dimen.recents_task_view_header_button_padding,
- R.dimen.recents_task_view_header_button_padding,
- R.dimen.recents_task_view_header_button_padding,
- R.dimen.recents_task_view_header_button_padding_tablet_land,
- R.dimen.recents_task_view_header_button_padding,
- R.dimen.recents_task_view_header_button_padding_tablet_land,
- R.dimen.recents_grid_task_view_header_button_padding);
- if (headerBarHeight != mHeaderBarHeight || headerButtonPadding != mHeaderButtonPadding) {
- mHeaderBarHeight = headerBarHeight;
- mHeaderButtonPadding = headerButtonPadding;
- updateLayoutParams(mIconView, mTitleView, mMoveTaskButton, mDismissButton);
- if (mAppOverlayView != null) {
- updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView);
- }
- }
- }
-
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
-
- // Since we update the position of children based on the width of the parent and this view
- // recompute these changes with the new view size
- onTaskViewSizeChanged(mTaskViewRect.width(), mTaskViewRect.height());
- }
-
- /**
- * Called when the task view frame changes, allowing us to move the contents of the header
- * to match the frame changes.
- */
- public void onTaskViewSizeChanged(int width, int height) {
- mTaskViewRect.set(0, 0, width, height);
-
- boolean showTitle = true;
- boolean showMoveIcon = true;
- boolean showDismissIcon = true;
- int rightInset = width - getMeasuredWidth();
-
- mTitleView.setVisibility(showTitle ? View.VISIBLE : View.INVISIBLE);
- if (mMoveTaskButton != null) {
- mMoveTaskButton.setVisibility(showMoveIcon ? View.VISIBLE : View.INVISIBLE);
- mMoveTaskButton.setTranslationX(rightInset);
- }
- mDismissButton.setVisibility(showDismissIcon ? View.VISIBLE : View.INVISIBLE);
- mDismissButton.setTranslationX(rightInset);
-
- setLeftTopRightBottom(0, 0, width, getMeasuredHeight());
- }
-
- @Override
- public void onDrawForeground(Canvas canvas) {
- super.onDrawForeground(canvas);
-
- // Draw the dim layer with the rounded corners
- canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight() + mCornerRadius,
- mCornerRadius, mCornerRadius, mDimLayerPaint);
- }
-
- /** Starts the focus timer. */
- public void startFocusTimerIndicator(int duration) {
- if (mFocusTimerIndicator == null) {
- return;
- }
-
- mFocusTimerIndicator.setVisibility(View.VISIBLE);
- mFocusTimerIndicator.setMax(duration);
- mFocusTimerIndicator.setProgress(duration);
- if (mFocusTimerCountDown != null) {
- mFocusTimerCountDown.cancel();
- }
- mFocusTimerCountDown = new CountDownTimer(duration,
- FOCUS_INDICATOR_INTERVAL_MS) {
- public void onTick(long millisUntilFinished) {
- mFocusTimerIndicator.setProgress((int) millisUntilFinished);
- }
-
- public void onFinish() {
- // Do nothing
- }
- }.start();
- }
-
- /** Cancels the focus timer. */
- public void cancelFocusTimerIndicator() {
- if (mFocusTimerIndicator == null) {
- return;
- }
-
- if (mFocusTimerCountDown != null) {
- mFocusTimerCountDown.cancel();
- mFocusTimerIndicator.setProgress(0);
- mFocusTimerIndicator.setVisibility(View.INVISIBLE);
- }
- }
-
- /** Only exposed for the workaround for b/27815919. */
- public ImageView getIconView() {
- return mIconView;
- }
-
- /** Returns the secondary color for a primary color. */
- int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
- int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
- return Utilities.getColorWithOverlay(primaryColor, overlayColor, 0.8f);
- }
-
- /**
- * Sets the dim alpha, only used when we are not using hardware layers.
- * (see RecentsConfiguration.useHardwareLayers)
- */
- public void setDimAlpha(float dimAlpha) {
- if (Float.compare(mDimAlpha, dimAlpha) != 0) {
- mDimAlpha = dimAlpha;
- mTitleView.setAlpha(1f - dimAlpha);
- updateBackgroundColor(mBackground.getColor(), dimAlpha);
- }
- }
-
- /**
- * Updates the background and highlight colors for this header.
- */
- private void updateBackgroundColor(int color, float dimAlpha) {
- if (mTask != null) {
- mBackground.setColorAndDim(color, dimAlpha);
- // TODO: Consider using the saturation of the color to adjust the lightness as well
- ColorUtils.colorToHSL(color, mTmpHSL);
- mTmpHSL[2] = Math.min(1f, mTmpHSL[2] + OVERLAY_LIGHTNESS_INCREMENT * (1.0f - dimAlpha));
- mOverlayBackground.setColorAndDim(ColorUtils.HSLToColor(mTmpHSL), dimAlpha);
- mDimLayerPaint.setAlpha((int) (dimAlpha * 255));
- invalidate();
- }
- }
-
- /**
- * Sets whether the background color should be darkened to differentiate from the primary color.
- */
- public void setShouldDarkenBackgroundColor(boolean flag) {
- mShouldDarkenBackgroundColor = flag;
- }
-
- /**
- * Binds the bar view to the task.
- */
- public void bindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
- mTask = t;
-
- int primaryColor = disabledInSafeMode
- ? mDisabledTaskBarBackgroundColor
- : t.colorPrimary;
- if (mBackground.getColor() != primaryColor) {
- updateBackgroundColor(primaryColor, mDimAlpha);
- }
- if (!mTitleView.getText().toString().equals(t.title)) {
- mTitleView.setText(t.title);
- }
- mTitleView.setContentDescription(t.titleDescription);
- mTitleView.setTextColor(t.useLightOnPrimaryColor ?
- mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
- mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
- mLightDismissDrawable : mDarkDismissDrawable);
- mDismissButton.setContentDescription(String.format(mDismissDescFormat, t.titleDescription));
- mDismissButton.setOnClickListener(this);
- mDismissButton.setClickable(false);
- ((RippleDrawable) mDismissButton.getBackground()).setForceSoftware(true);
-
- // In accessibility, a single click on the focused app info button will show it
- if (touchExplorationEnabled) {
- mIconView.setContentDescription(String.format(mAppInfoDescFormat, t.titleDescription));
- mIconView.setOnClickListener(this);
- mIconView.setClickable(true);
- }
- }
-
- /**
- * Called when the bound task's data has loaded and this view should update to reflect the
- * changes.
- */
- public void onTaskDataLoaded() {
- if (mTask != null && mTask.icon != null) {
- mIconView.setImageDrawable(mTask.icon);
- }
- }
-
- /** Unbinds the bar view from the task */
- void unbindFromTask(boolean touchExplorationEnabled) {
- mTask = null;
- mIconView.setImageDrawable(null);
- if (touchExplorationEnabled) {
- mIconView.setClickable(false);
- }
- }
-
- /** Animates this task bar if the user does not interact with the stack after a certain time. */
- void startNoUserInteractionAnimation() {
- int duration = getResources().getInteger(R.integer.recents_task_enter_from_app_duration);
- mDismissButton.setVisibility(View.VISIBLE);
- mDismissButton.setClickable(true);
- if (mDismissButton.getVisibility() == VISIBLE) {
- mDismissButton.animate()
- .alpha(1f)
- .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
- .setDuration(duration)
- .start();
- } else {
- mDismissButton.setAlpha(1f);
- }
- if (mMoveTaskButton != null) {
- if (mMoveTaskButton.getVisibility() == VISIBLE) {
- mMoveTaskButton.setVisibility(View.VISIBLE);
- mMoveTaskButton.setClickable(true);
- mMoveTaskButton.animate()
- .alpha(1f)
- .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
- .setDuration(duration)
- .start();
- } else {
- mMoveTaskButton.setAlpha(1f);
- }
- }
- }
-
- /**
- * Mark this task view that the user does has not interacted with the stack after a certain
- * time.
- */
- public void setNoUserInteractionState() {
- mDismissButton.setVisibility(View.VISIBLE);
- mDismissButton.animate().cancel();
- mDismissButton.setAlpha(1f);
- mDismissButton.setClickable(true);
- if (mMoveTaskButton != null) {
- mMoveTaskButton.setVisibility(View.VISIBLE);
- mMoveTaskButton.animate().cancel();
- mMoveTaskButton.setAlpha(1f);
- mMoveTaskButton.setClickable(true);
- }
- }
-
- /**
- * Resets the state tracking that the user has not interacted with the stack after a certain
- * time.
- */
- void resetNoUserInteractionState() {
- mDismissButton.setVisibility(View.INVISIBLE);
- mDismissButton.setAlpha(0f);
- mDismissButton.setClickable(false);
- if (mMoveTaskButton != null) {
- mMoveTaskButton.setVisibility(View.INVISIBLE);
- mMoveTaskButton.setAlpha(0f);
- mMoveTaskButton.setClickable(false);
- }
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
-
- // Don't forward our state to the drawable - we do it manually in onTaskViewFocusChanged.
- // This is to prevent layer trashing when the view is pressed.
- return new int[] {};
- }
-
- @Override
- public void onClick(View v) {
- if (v == mIconView) {
- // In accessibility, a single click on the focused app info button will show it
- EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
- } else if (v == mDismissButton) {
- TaskView tv = Utilities.findParent(this, TaskView.class);
- tv.dismissTask();
-
- // Keep track of deletions by the dismiss button
- MetricsLogger.histogram(getContext(), "overview_task_dismissed_source",
- Constants.Metrics.DismissSourceHeaderButton);
- } else if (v == mMoveTaskButton) {
- TaskView tv = Utilities.findParent(this, TaskView.class);
- EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, null, false,
- mTaskWindowingMode, ACTIVITY_TYPE_UNDEFINED));
- } else if (v == mAppInfoView) {
- EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
- } else if (v == mAppIconView) {
- hideAppOverlay(false /* immediate */);
- }
- }
-
- @Override
- public boolean onLongClick(View v) {
- if (v == mIconView) {
- showAppOverlay();
- return true;
- } else if (v == mAppIconView) {
- hideAppOverlay(false /* immediate */);
- return true;
- }
- return false;
- }
-
- /**
- * Shows the application overlay.
- */
- private void showAppOverlay() {
- // Skip early if the task is invalid
- SystemServicesProxy ssp = Recents.getSystemServices();
- ComponentName cn = mTask.key.getComponent();
- int userId = mTask.key.userId;
- ActivityInfo activityInfo = PackageManagerWrapper.getInstance().getActivityInfo(cn, userId);
- if (activityInfo == null) {
- return;
- }
-
- // Inflate the overlay if necessary
- if (mAppOverlayView == null) {
- mAppOverlayView = (FrameLayout) Utilities.findViewStubById(this,
- R.id.app_overlay_stub).inflate();
- mAppOverlayView.setBackground(mOverlayBackground);
- mAppIconView = (ImageView) mAppOverlayView.findViewById(R.id.app_icon);
- mAppIconView.setOnClickListener(this);
- mAppIconView.setOnLongClickListener(this);
- mAppInfoView = (ImageView) mAppOverlayView.findViewById(R.id.app_info);
- mAppInfoView.setOnClickListener(this);
- mAppTitleView = (TextView) mAppOverlayView.findViewById(R.id.app_title);
- updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView);
- }
-
- // Update the overlay contents for the current app
- mAppTitleView.setText(ActivityManagerWrapper.getInstance().getBadgedApplicationLabel(
- activityInfo.applicationInfo, userId));
- mAppTitleView.setTextColor(mTask.useLightOnPrimaryColor ?
- mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
- mAppIconView.setImageDrawable(getIconDrawableFactory().getBadgedIcon(
- activityInfo.applicationInfo, userId));
- mAppInfoView.setImageDrawable(mTask.useLightOnPrimaryColor
- ? mLightInfoIcon
- : mDarkInfoIcon);
- mAppOverlayView.setVisibility(View.VISIBLE);
-
- int x = mIconView.getLeft() + mIconView.getWidth() / 2;
- int y = mIconView.getTop() + mIconView.getHeight() / 2;
- Animator revealAnim = ViewAnimationUtils.createCircularReveal(mAppOverlayView, x, y, 0,
- getWidth());
- revealAnim.setDuration(OVERLAY_REVEAL_DURATION);
- revealAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- revealAnim.start();
- }
-
- /**
- * Hide the application overlay.
- */
- private void hideAppOverlay(boolean immediate) {
- // Skip if we haven't even loaded the overlay yet
- if (mAppOverlayView == null) {
- return;
- }
-
- if (immediate) {
- mAppOverlayView.setVisibility(View.GONE);
- } else {
- int x = mIconView.getLeft() + mIconView.getWidth() / 2;
- int y = mIconView.getTop() + mIconView.getHeight() / 2;
- Animator revealAnim = ViewAnimationUtils.createCircularReveal(mAppOverlayView, x, y,
- getWidth(), 0);
- revealAnim.setDuration(OVERLAY_REVEAL_DURATION);
- revealAnim.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- revealAnim.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mAppOverlayView.setVisibility(View.GONE);
- }
- });
- revealAnim.start();
- }
- }
-
- private static IconDrawableFactory getIconDrawableFactory() {
- if (sDrawableFactory == null) {
- sDrawableFactory = IconDrawableFactory.newInstance(AppGlobals.getInitialApplication());
- }
- return sDrawableFactory;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
deleted file mode 100644
index 4152b05..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapShader;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.LightingColorFilter;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Shader;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewDebug;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.ui.TaskSnapshotChangedEvent;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.shared.recents.model.ThumbnailData;
-import java.io.PrintWriter;
-
-
-/**
- * The task thumbnail view. It implements an image view that allows for animating the dim and
- * alpha of the thumbnail image.
- */
-public class TaskViewThumbnail extends View {
-
- private static final ColorMatrix TMP_FILTER_COLOR_MATRIX = new ColorMatrix();
- private static final ColorMatrix TMP_BRIGHTNESS_COLOR_MATRIX = new ColorMatrix();
-
- private Task mTask;
-
- private int mDisplayOrientation = Configuration.ORIENTATION_UNDEFINED;
- private Rect mDisplayRect = new Rect();
-
- // Drawing
- @ViewDebug.ExportedProperty(category="recents")
- protected Rect mTaskViewRect = new Rect();
- @ViewDebug.ExportedProperty(category="recents")
- protected Rect mThumbnailRect = new Rect();
- @ViewDebug.ExportedProperty(category="recents")
- protected float mThumbnailScale;
- private float mFullscreenThumbnailScale = 1f;
- /** The height, in pixels, of the task view's title bar. */
- private int mTitleBarHeight;
- private boolean mSizeToFit = false;
- private boolean mOverlayHeaderOnThumbnailActionBar = true;
- private ThumbnailData mThumbnailData;
-
- protected int mCornerRadius;
- @ViewDebug.ExportedProperty(category="recents")
- private float mDimAlpha;
- private Matrix mMatrix = new Matrix();
- private Paint mDrawPaint = new Paint();
- protected Paint mLockedPaint = new Paint();
- protected Paint mBgFillPaint = new Paint();
- protected BitmapShader mBitmapShader;
- protected boolean mUserLocked = false;
- private LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
-
- // Clip the top of the thumbnail against the opaque header bar that overlaps this view
- private View mTaskBar;
-
- // Visibility optimization, if the thumbnail height is less than the height of the header
- // bar for the task view, then just mark this thumbnail view as invisible
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mInvisible;
-
- @ViewDebug.ExportedProperty(category="recents")
- private boolean mDisabledInSafeMode;
-
- public TaskViewThumbnail(Context context) {
- this(context, null);
- }
-
- public TaskViewThumbnail(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mDrawPaint.setColorFilter(mLightingColorFilter);
- mDrawPaint.setFilterBitmap(true);
- mDrawPaint.setAntiAlias(true);
- Resources res = getResources();
- mCornerRadius = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
- mBgFillPaint.setColor(Color.WHITE);
- mLockedPaint.setColor(Color.WHITE);
- mTitleBarHeight = res.getDimensionPixelSize(R.dimen.recents_grid_task_view_header_height);
- }
-
- /**
- * Called when the task view frame changes, allowing us to move the contents of the header
- * to match the frame changes.
- */
- public void onTaskViewSizeChanged(int width, int height) {
- // Return early if the bounds have not changed
- if (mTaskViewRect.width() == width && mTaskViewRect.height() == height) {
- return;
- }
-
- mTaskViewRect.set(0, 0, width, height);
- setLeftTopRightBottom(0, 0, width, height);
- updateThumbnailMatrix();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- if (mInvisible) {
- return;
- }
-
- int viewWidth = mTaskViewRect.width();
- int viewHeight = mTaskViewRect.height();
- int thumbnailWidth = Math.min(viewWidth,
- (int) (mThumbnailRect.width() * mThumbnailScale));
- int thumbnailHeight = Math.min(viewHeight,
- (int) (mThumbnailRect.height() * mThumbnailScale));
-
- if (mUserLocked) {
- canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius,
- mLockedPaint);
- } else if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
- int topOffset = 0;
- if (mTaskBar != null && mOverlayHeaderOnThumbnailActionBar) {
- topOffset = mTaskBar.getHeight() - mCornerRadius;
- }
-
- // Draw the background, there will be some small overdraw with the thumbnail
- if (thumbnailWidth < viewWidth) {
- // Portrait thumbnail on a landscape task view
- canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), topOffset,
- viewWidth, viewHeight,
- mCornerRadius, mCornerRadius, mBgFillPaint);
- }
- if (thumbnailHeight < viewHeight) {
- // Landscape thumbnail on a portrait task view
- canvas.drawRoundRect(0, Math.max(topOffset, thumbnailHeight - mCornerRadius),
- viewWidth, viewHeight,
- mCornerRadius, mCornerRadius, mBgFillPaint);
- }
-
- // Draw the thumbnail
- canvas.drawRoundRect(0, topOffset, thumbnailWidth, thumbnailHeight,
- mCornerRadius, mCornerRadius, mDrawPaint);
- } else {
- canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius,
- mBgFillPaint);
- }
- }
-
- /** Sets the thumbnail to a given bitmap. */
- void setThumbnail(ThumbnailData thumbnailData) {
- if (thumbnailData != null && thumbnailData.thumbnail != null) {
- Bitmap bm = thumbnailData.thumbnail;
- bm.prepareToDraw();
- mFullscreenThumbnailScale = thumbnailData.scale;
- mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
- mDrawPaint.setShader(mBitmapShader);
- mThumbnailRect.set(0, 0,
- bm.getWidth() - thumbnailData.insets.left - thumbnailData.insets.right,
- bm.getHeight() - thumbnailData.insets.top - thumbnailData.insets.bottom);
- mThumbnailData = thumbnailData;
- updateThumbnailMatrix();
- updateThumbnailPaintFilter();
- } else {
- mBitmapShader = null;
- mDrawPaint.setShader(null);
- mThumbnailRect.setEmpty();
- mThumbnailData = null;
- }
- }
-
- /** Updates the paint to draw the thumbnail. */
- void updateThumbnailPaintFilter() {
- if (mInvisible) {
- return;
- }
- int mul = (int) ((1.0f - mDimAlpha) * 255);
- if (mBitmapShader != null) {
- if (mDisabledInSafeMode) {
- // Brightness: C-new = C-old*(1-amount) + amount
- TMP_FILTER_COLOR_MATRIX.setSaturation(0);
- float scale = 1f - mDimAlpha;
- float[] mat = TMP_BRIGHTNESS_COLOR_MATRIX.getArray();
- mat[0] = scale;
- mat[6] = scale;
- mat[12] = scale;
- mat[4] = mDimAlpha * 255f;
- mat[9] = mDimAlpha * 255f;
- mat[14] = mDimAlpha * 255f;
- TMP_FILTER_COLOR_MATRIX.preConcat(TMP_BRIGHTNESS_COLOR_MATRIX);
- ColorMatrixColorFilter filter = new ColorMatrixColorFilter(TMP_FILTER_COLOR_MATRIX);
- mDrawPaint.setColorFilter(filter);
- mBgFillPaint.setColorFilter(filter);
- mLockedPaint.setColorFilter(filter);
- } else {
- mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul));
- mDrawPaint.setColorFilter(mLightingColorFilter);
- mDrawPaint.setColor(0xFFffffff);
- mBgFillPaint.setColorFilter(mLightingColorFilter);
- mLockedPaint.setColorFilter(mLightingColorFilter);
- }
- } else {
- int grey = mul;
- mDrawPaint.setColorFilter(null);
- mDrawPaint.setColor(Color.argb(255, grey, grey, grey));
- }
- if (!mInvisible) {
- invalidate();
- }
- }
-
- /**
- * Updates the scale of the bitmap relative to this view.
- */
- public void updateThumbnailMatrix() {
- mThumbnailScale = 1f;
- if (mBitmapShader != null && mThumbnailData != null) {
- if (mTaskViewRect.isEmpty()) {
- // If we haven't measured , skip the thumbnail drawing and only draw the background
- // color
- mThumbnailScale = 0f;
- } else if (mSizeToFit) {
- // Make sure we fill the entire space regardless of the orientation.
- float viewAspectRatio = (float) mTaskViewRect.width() /
- (float) (mTaskViewRect.height() - mTitleBarHeight);
- float thumbnailAspectRatio =
- (float) mThumbnailRect.width() / (float) mThumbnailRect.height();
- if (viewAspectRatio > thumbnailAspectRatio) {
- mThumbnailScale =
- (float) mTaskViewRect.width() / (float) mThumbnailRect.width();
- } else {
- mThumbnailScale = (float) (mTaskViewRect.height() - mTitleBarHeight)
- / (float) mThumbnailRect.height();
- }
- } else {
- float invThumbnailScale = 1f / mFullscreenThumbnailScale;
- if (mDisplayOrientation == Configuration.ORIENTATION_PORTRAIT) {
- if (mThumbnailData.orientation == Configuration.ORIENTATION_PORTRAIT) {
- // If we are in the same orientation as the screenshot, just scale it to the
- // width of the task view
- mThumbnailScale = (float) mTaskViewRect.width() / mThumbnailRect.width();
- } else {
- // Scale the landscape thumbnail up to app size, then scale that to the task
- // view size to match other portrait screenshots
- mThumbnailScale = invThumbnailScale *
- ((float) mTaskViewRect.width() / mDisplayRect.width());
- }
- } else {
- // Otherwise, scale the screenshot to fit 1:1 in the current orientation
- mThumbnailScale = invThumbnailScale;
- }
- }
- mMatrix.setTranslate(-mThumbnailData.insets.left * mFullscreenThumbnailScale,
- -mThumbnailData.insets.top * mFullscreenThumbnailScale);
- mMatrix.postScale(mThumbnailScale, mThumbnailScale);
- mBitmapShader.setLocalMatrix(mMatrix);
- }
- if (!mInvisible) {
- invalidate();
- }
- }
-
- /** Sets whether the thumbnail should be resized to fit the task view in all orientations. */
- public void setSizeToFit(boolean flag) {
- mSizeToFit = flag;
- }
-
- /**
- * Sets whether the header should overlap (and hide) the action bar in the thumbnail, or
- * be stacked just above it.
- */
- public void setOverlayHeaderOnThumbnailActionBar(boolean flag) {
- mOverlayHeaderOnThumbnailActionBar = flag;
- }
-
- /** Updates the clip rect based on the given task bar. */
- void updateClipToTaskBar(View taskBar) {
- mTaskBar = taskBar;
- invalidate();
- }
-
- /** Updates the visibility of the the thumbnail. */
- void updateThumbnailVisibility(int clipBottom) {
- boolean invisible = mTaskBar != null && (getHeight() - clipBottom) <= mTaskBar.getHeight();
- if (invisible != mInvisible) {
- mInvisible = invisible;
- if (!mInvisible) {
- updateThumbnailPaintFilter();
- }
- }
- }
-
- /**
- * Sets the dim alpha, only used when we are not using hardware layers.
- * (see RecentsConfiguration.useHardwareLayers)
- */
- public void setDimAlpha(float dimAlpha) {
- mDimAlpha = dimAlpha;
- updateThumbnailPaintFilter();
- }
-
- /**
- * Returns the {@link Paint} used to draw a task screenshot, or {@link #mLockedPaint} if the
- * thumbnail shouldn't be drawn because it belongs to a locked user.
- */
- protected Paint getDrawPaint() {
- if (mUserLocked) {
- return mLockedPaint;
- }
- return mDrawPaint;
- }
-
- /**
- * Binds the thumbnail view to the task.
- */
- void bindToTask(Task t, boolean disabledInSafeMode, int displayOrientation, Rect displayRect) {
- mTask = t;
- mDisabledInSafeMode = disabledInSafeMode;
- mDisplayOrientation = displayOrientation;
- mDisplayRect.set(displayRect);
- if (t.colorBackground != 0) {
- mBgFillPaint.setColor(t.colorBackground);
- }
- if (t.colorPrimary != 0) {
- mLockedPaint.setColor(t.colorPrimary);
- }
- mUserLocked = t.isLocked;
- EventBus.getDefault().register(this);
- }
-
- /**
- * Called when the bound task's data has loaded and this view should update to reflect the
- * changes.
- */
- void onTaskDataLoaded(ThumbnailData thumbnailData) {
- setThumbnail(thumbnailData);
- }
-
- /** Unbinds the thumbnail view from the task */
- void unbindFromTask() {
- mTask = null;
- setThumbnail(null);
- EventBus.getDefault().unregister(this);
- }
-
- public final void onBusEvent(TaskSnapshotChangedEvent event) {
- if (mTask == null || event.taskId != mTask.key.id || event.thumbnailData == null
- || event.thumbnailData.thumbnail == null) {
- return;
- }
- setThumbnail(event.thumbnailData);
- }
-
- public void dump(String prefix, PrintWriter writer) {
- writer.print(prefix); writer.print("TaskViewThumbnail");
- writer.print(" mTaskViewRect="); writer.print(Utilities.dumpRect(mTaskViewRect));
- writer.print(" mThumbnailRect="); writer.print(Utilities.dumpRect(mThumbnailRect));
- writer.print(" mThumbnailScale="); writer.print(mThumbnailScale);
- writer.print(" mDimAlpha="); writer.print(mDimAlpha);
- writer.println();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
deleted file mode 100644
index 9b717e0..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.util.Property;
-import android.view.View;
-
-import com.android.systemui.shared.recents.utilities.AnimationProps;
-import com.android.systemui.shared.recents.utilities.Utilities;
-
-import java.util.ArrayList;
-
-/**
- * The visual properties for a {@link TaskView}.
- */
-public class TaskViewTransform {
-
- public static final Property<View, Rect> LTRB =
- new Property<View, Rect>(Rect.class, "leftTopRightBottom") {
-
- private Rect mTmpRect = new Rect();
-
- @Override
- public void set(View v, Rect ltrb) {
- v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom);
- }
-
- @Override
- public Rect get(View v) {
- mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
- return mTmpRect;
- }
- };
-
- public float translationZ = 0;
- public float scale = 1f;
- public float alpha = 1f;
- public float dimAlpha = 0f;
- public float viewOutlineAlpha = 0f;
-
- public boolean visible = false;
-
- // This is a window-space rect used for positioning the task in the stack
- public RectF rect = new RectF();
-
- /**
- * Fills int this transform from the state of the given TaskView.
- */
- public void fillIn(TaskView tv) {
- translationZ = tv.getTranslationZ();
- scale = tv.getScaleX();
- alpha = tv.getAlpha();
- visible = true;
- dimAlpha = tv.getDimAlpha();
- viewOutlineAlpha = tv.getViewBounds().getAlpha();
- rect.set(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
- }
-
- /**
- * Copies the transform state from another {@link TaskViewTransform}.
- */
- public void copyFrom(TaskViewTransform other) {
- translationZ = other.translationZ;
- scale = other.scale;
- alpha = other.alpha;
- visible = other.visible;
- dimAlpha = other.dimAlpha;
- viewOutlineAlpha = other.viewOutlineAlpha;
- rect.set(other.rect);
- }
-
- /**
- * @return whether {@param other} is the same transform as this
- */
- public boolean isSame(TaskViewTransform other) {
- return translationZ == other.translationZ
- && scale == other.scale
- && other.alpha == alpha
- && dimAlpha == other.dimAlpha
- && visible == other.visible
- && rect.equals(other.rect);
- }
-
- /**
- * Resets the current transform.
- */
- public void reset() {
- translationZ = 0;
- scale = 1f;
- alpha = 1f;
- dimAlpha = 0f;
- viewOutlineAlpha = 0f;
- visible = false;
- rect.setEmpty();
- }
-
- /** Convenience functions to compare against current property values */
- public boolean hasAlphaChangedFrom(float v) {
- return (Float.compare(alpha, v) != 0);
- }
-
- public boolean hasScaleChangedFrom(float v) {
- return (Float.compare(scale, v) != 0);
- }
-
- public boolean hasTranslationZChangedFrom(float v) {
- return (Float.compare(translationZ, v) != 0);
- }
-
- public boolean hasRectChangedFrom(View v) {
- return ((int) rect.left != v.getLeft()) || ((int) rect.right != v.getRight()) ||
- ((int) rect.top != v.getTop()) || ((int) rect.bottom != v.getBottom());
- }
-
- /**
- * Applies this transform to a view.
- */
- public void applyToTaskView(TaskView v, ArrayList<Animator> animators,
- AnimationProps animation, boolean allowShadows) {
- // Return early if not visible
- if (!visible) {
- return;
- }
-
- if (animation.isImmediate()) {
- if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
- v.setTranslationZ(translationZ);
- }
- if (hasScaleChangedFrom(v.getScaleX())) {
- v.setScaleX(scale);
- v.setScaleY(scale);
- }
- if (hasAlphaChangedFrom(v.getAlpha())) {
- v.setAlpha(alpha);
- }
- if (hasRectChangedFrom(v)) {
- v.setLeftTopRightBottom((int) rect.left, (int) rect.top, (int) rect.right,
- (int) rect.bottom);
- }
- } else {
- if (allowShadows && hasTranslationZChangedFrom(v.getTranslationZ())) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.TRANSLATION_Z,
- v.getTranslationZ(), translationZ);
- animators.add(animation.apply(AnimationProps.TRANSLATION_Z, anim));
- }
- if (hasScaleChangedFrom(v.getScaleX())) {
- ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
- PropertyValuesHolder.ofFloat(View.SCALE_X, v.getScaleX(), scale),
- PropertyValuesHolder.ofFloat(View.SCALE_Y, v.getScaleX(), scale));
- animators.add(animation.apply(AnimationProps.SCALE, anim));
- }
- if (hasAlphaChangedFrom(v.getAlpha())) {
- ObjectAnimator anim = ObjectAnimator.ofFloat(v, View.ALPHA, v.getAlpha(), alpha);
- animators.add(animation.apply(AnimationProps.ALPHA, anim));
- }
- if (hasRectChangedFrom(v)) {
- Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
- Rect toViewRect = new Rect();
- rect.round(toViewRect);
- ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v,
- PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR,
- fromViewRect, toViewRect));
- animators.add(animation.apply(AnimationProps.BOUNDS, anim));
- }
- }
- }
-
- /** Reset the transform on a view. */
- public static void reset(TaskView v) {
- v.setTranslationX(0f);
- v.setTranslationY(0f);
- v.setTranslationZ(0f);
- v.setScaleX(1f);
- v.setScaleY(1f);
- v.setAlpha(1f);
- v.getViewBounds().setClipBottom(0);
- v.setLeftTopRightBottom(0, 0, 0, 0);
- }
-
- @Override
- public String toString() {
- return "R: " + rect + " V: " + visible;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
deleted file mode 100644
index a287fe6..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewPool.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.content.Context;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-
-/* A view pool to manage more views than we can visibly handle */
-public class ViewPool<V, T> {
-
- /* An interface to the consumer of a view pool */
- public interface ViewPoolConsumer<V, T> {
- public V createView(Context context);
- public void onReturnViewToPool(V v);
- public void onPickUpViewFromPool(V v, T prepareData, boolean isNewView);
- public boolean hasPreferredData(V v, T preferredData);
- }
-
- Context mContext;
- ViewPoolConsumer<V, T> mViewCreator;
- LinkedList<V> mPool = new LinkedList<V>();
-
- /** Initializes the pool with a fixed predetermined pool size */
- public ViewPool(Context context, ViewPoolConsumer<V, T> viewCreator) {
- mContext = context;
- mViewCreator = viewCreator;
- }
-
- /** Returns a view into the pool */
- void returnViewToPool(V v) {
- mViewCreator.onReturnViewToPool(v);
- mPool.push(v);
- }
-
- /** Gets a view from the pool and prepares it */
- V pickUpViewFromPool(T preferredData, T prepareData) {
- V v = null;
- boolean isNewView = false;
- if (mPool.isEmpty()) {
- v = mViewCreator.createView(mContext);
- isNewView = true;
- } else {
- // Try and find a preferred view
- Iterator<V> iter = mPool.iterator();
- while (iter.hasNext()) {
- V vpv = iter.next();
- if (mViewCreator.hasPreferredData(vpv, preferredData)) {
- v = vpv;
- iter.remove();
- break;
- }
- }
- // Otherwise, just grab the first view
- if (v == null) {
- v = mPool.pop();
- }
- }
- mViewCreator.onPickUpViewFromPool(v, prepareData, isNewView);
- return v;
- }
-
- /**
- * Returns the list of views in the pool.
- */
- List<V> getViews() {
- return mPool;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
deleted file mode 100644
index 3bdad31..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/AnimateableGridViewBounds.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views.grid;
-
-import android.view.View;
-import com.android.systemui.shared.recents.view.AnimateableViewBounds;
-
-/* An outline provider for grid-based task views. */
-class AnimateableGridViewBounds extends AnimateableViewBounds {
-
- public AnimateableGridViewBounds(View source, int cornerRadius) {
- super(source, cornerRadius);
- }
-
- @Override
- protected void updateClipBounds() {
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
deleted file mode 100644
index 0d51154..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskView.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views.grid;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import com.android.systemui.R;
-import com.android.systemui.shared.recents.view.AnimateableViewBounds;
-import com.android.systemui.recents.views.TaskView;
-
-public class GridTaskView extends TaskView {
-
- /** The height, in pixels, of the header view. */
- private int mHeaderHeight;
-
- public GridTaskView(Context context) {
- this(context, null);
- }
-
- public GridTaskView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public GridTaskView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public GridTaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mHeaderHeight = context.getResources().getDimensionPixelSize(
- R.dimen.recents_grid_task_view_header_height);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- // Show the full thumbnail and don't overlap with the header.
- mThumbnailView.setSizeToFit(true);
- mThumbnailView.setOverlayHeaderOnThumbnailActionBar(false);
- mThumbnailView.updateThumbnailMatrix();
- mThumbnailView.setTranslationY(mHeaderHeight);
- mHeaderView.setShouldDarkenBackgroundColor(true);
- }
-
- @Override
- protected AnimateableViewBounds createOutlineProvider() {
- return new AnimateableGridViewBounds(this, mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_task_view_shadow_rounded_corners_radius));
- }
-
- @Override
- protected void onConfigurationChanged() {
- super.onConfigurationChanged();
- mHeaderHeight = mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_grid_task_view_header_height);
- mThumbnailView.setTranslationY(mHeaderHeight);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
deleted file mode 100644
index 2d7cfb1..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/GridTaskViewThumbnail.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views.grid;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Path;
-import android.util.AttributeSet;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.views.TaskViewThumbnail;
-
-public class GridTaskViewThumbnail extends TaskViewThumbnail {
-
- private final Path mThumbnailOutline = new Path();
- private final Path mRestBackgroundOutline = new Path();
- // True if either this view's size or thumbnail scale has changed and mThumbnailOutline should
- // be updated.
- private boolean mUpdateThumbnailOutline = true;
-
- public GridTaskViewThumbnail(Context context) {
- this(context, null);
- }
-
- public GridTaskViewThumbnail(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public GridTaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mCornerRadius = getResources().getDimensionPixelSize(
- R.dimen.recents_grid_task_view_rounded_corners_radius);
- }
-
- /**
- * Called when the task view frame changes, allowing us to move the contents of the header
- * to match the frame changes.
- */
- public void onTaskViewSizeChanged(int width, int height) {
- mUpdateThumbnailOutline = true;
- super.onTaskViewSizeChanged(width, height);
- }
-
- /**
- * Updates the scale of the bitmap relative to this view.
- */
- public void updateThumbnailMatrix() {
- mUpdateThumbnailOutline = true;
- super.updateThumbnailMatrix();
- }
-
- private void updateThumbnailOutline() {
- final int titleHeight = getResources().getDimensionPixelSize(
- R.dimen.recents_grid_task_view_header_height);
- final int viewWidth = mTaskViewRect.width();
- final int viewHeight = mTaskViewRect.height() - titleHeight;
- final int thumbnailWidth = Math.min(viewWidth,
- (int) (mThumbnailRect.width() * mThumbnailScale));
- final int thumbnailHeight = Math.min(viewHeight,
- (int) (mThumbnailRect.height() * mThumbnailScale));
-
- if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
- // Draw the thumbnail, we only round the bottom corners:
- //
- // outerLeft outerRight
- // <-----------------------> mRestBackgroundOutline
- // _________________________ (thumbnailWidth < viewWidth)
- // |_______________________| outerTop A ____ B
- // | | ↑ | |
- // | | | | |
- // | | | | |
- // | | | | | C
- // \_______________________/ ↓ |__/
- // mCornerRadius outerBottom E D
- //
- // mRestBackgroundOutline (thumbnailHeight < viewHeight)
- // A _________________________ B
- // | | C
- // F \_______________________/
- // E D
- final int outerLeft = 0;
- final int outerTop = 0;
- final int outerRight = outerLeft + thumbnailWidth;
- final int outerBottom = outerTop + thumbnailHeight;
- createThumbnailPath(outerLeft, outerTop, outerRight, outerBottom, mThumbnailOutline);
-
- if (thumbnailWidth < viewWidth) {
- final int l = Math.max(0, outerRight - mCornerRadius);
- final int r = outerRight;
- final int t = outerTop;
- final int b = outerBottom;
- mRestBackgroundOutline.reset();
- mRestBackgroundOutline.moveTo(l, t); // A
- mRestBackgroundOutline.lineTo(r, t); // B
- mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
- mRestBackgroundOutline.arcTo(r - 2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
- 0, 90, false); // D
- mRestBackgroundOutline.lineTo(l, b); // E
- mRestBackgroundOutline.lineTo(l, t); // A
- mRestBackgroundOutline.close();
-
- }
- if (thumbnailHeight < viewHeight) {
- final int l = outerLeft;
- final int r = outerRight;
- final int t = Math.max(0, thumbnailHeight - mCornerRadius);
- final int b = outerBottom;
- mRestBackgroundOutline.reset();
- mRestBackgroundOutline.moveTo(l, t); // A
- mRestBackgroundOutline.lineTo(r, t); // B
- mRestBackgroundOutline.lineTo(r, b - mCornerRadius); // C
- mRestBackgroundOutline.arcTo(r - 2 * mCornerRadius, b - 2 * mCornerRadius, r, b,
- 0, 90, false); // D
- mRestBackgroundOutline.lineTo(l + mCornerRadius, b); // E
- mRestBackgroundOutline.arcTo(l, b - 2 * mCornerRadius, l + 2 * mCornerRadius, b,
- 90, 90, false); // F
- mRestBackgroundOutline.lineTo(l, t); // A
- mRestBackgroundOutline.close();
- }
- } else {
- createThumbnailPath(0, 0, viewWidth, viewHeight, mThumbnailOutline);
- }
- }
-
- private void createThumbnailPath(int outerLeft, int outerTop, int outerRight, int outerBottom,
- Path outPath) {
- outPath.reset();
- outPath.moveTo(outerLeft, outerTop);
- outPath.lineTo(outerRight, outerTop);
- outPath.lineTo(outerRight, outerBottom - mCornerRadius);
- outPath.arcTo(outerRight - 2 * mCornerRadius, outerBottom - 2 * mCornerRadius, outerRight,
- outerBottom, 0, 90, false);
- outPath.lineTo(outerLeft + mCornerRadius, outerBottom);
- outPath.arcTo(outerLeft, outerBottom - 2 * mCornerRadius, outerLeft + 2 * mCornerRadius,
- outerBottom, 90, 90, false);
- outPath.lineTo(outerLeft, outerTop);
- outPath.close();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- final int titleHeight = getResources().getDimensionPixelSize(
- R.dimen.recents_grid_task_view_header_height);
- final int viewWidth = mTaskViewRect.width();
- final int viewHeight = mTaskViewRect.height() - titleHeight;
- final int thumbnailWidth = Math.min(viewWidth,
- (int) (mThumbnailRect.width() * mThumbnailScale));
- final int thumbnailHeight = Math.min(viewHeight,
- (int) (mThumbnailRect.height() * mThumbnailScale));
-
- if (mUpdateThumbnailOutline) {
- updateThumbnailOutline();
- mUpdateThumbnailOutline = false;
- }
-
- if (mUserLocked) {
- canvas.drawPath(mThumbnailOutline, mLockedPaint);
- } else if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) {
- // Draw the background, there will be some small overdraw with the thumbnail
- if (thumbnailWidth < viewWidth) {
- // Portrait thumbnail on a landscape task view
- canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
- }
- if (thumbnailHeight < viewHeight) {
- // Landscape thumbnail on a portrait task view
- canvas.drawPath(mRestBackgroundOutline, mBgFillPaint);
- }
- canvas.drawPath(mThumbnailOutline, getDrawPaint());
- } else {
- canvas.drawPath(mThumbnailOutline, mBgFillPaint);
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
deleted file mode 100644
index ccda4b5..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views.grid;
-
-import static com.android.systemui.recents.views.TaskStackLayoutAlgorithm.*;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.view.WindowManager;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.events.ui.focus.NavigateTaskViewEvent.Direction;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
-import com.android.systemui.recents.views.TaskViewTransform;
-
-import java.util.ArrayList;
-
-public class TaskGridLayoutAlgorithm {
-
- private final String TAG = "TaskGridLayoutAlgorithm";
- public static final int MAX_LAYOUT_TASK_COUNT = 8;
-
- /** The horizontal padding around the whole recents view. */
- private int mPaddingLeftRight;
- /** The vertical padding around the whole recents view. */
- private int mPaddingTopBottom;
- /** The padding between task views. */
- private int mPaddingTaskView;
-
- private Rect mWindowRect;
- private Point mScreenSize = new Point();
-
- private Rect mTaskGridRect;
-
- /** The height, in pixels, of each task view's title bar. */
- private int mTitleBarHeight;
-
- /** The aspect ratio of each task thumbnail, without the title bar. */
- private float mAppAspectRatio;
- private Rect mSystemInsets = new Rect();
-
- /** The thickness of the focused task view frame. */
- private int mFocusedFrameThickness;
-
- /**
- * When the amount of tasks is determined, the size and position of every task view can be
- * decided. Each instance of TaskGridRectInfo store the task view information for a certain
- * amount of tasks.
- */
- class TaskGridRectInfo {
- Rect size;
- int[] xOffsets;
- int[] yOffsets;
- int tasksPerLine;
- int lines;
-
- TaskGridRectInfo(int taskCount) {
- size = new Rect();
- xOffsets = new int[taskCount];
- yOffsets = new int[taskCount];
-
- int layoutTaskCount = Math.min(MAX_LAYOUT_TASK_COUNT, taskCount);
- tasksPerLine = getTasksPerLine(layoutTaskCount);
- lines = layoutTaskCount < 4 ? 1 : 2;
-
- // A couple of special cases.
- boolean landscapeWindow = mWindowRect.width() > mWindowRect.height();
- boolean landscapeTaskView = mAppAspectRatio > 1;
- // If we're in portrait but task views are landscape, show more lines of fewer tasks.
- if (!landscapeWindow && landscapeTaskView) {
- tasksPerLine = layoutTaskCount < 2 ? 1 : 2;
- lines = layoutTaskCount < 3 ? 1 : (
- layoutTaskCount < 5 ? 2 : (
- layoutTaskCount < 7 ? 3 : 4));
- }
- // If we're in landscape but task views are portrait, show fewer lines of more tasks.
- if (landscapeWindow && !landscapeTaskView) {
- tasksPerLine = layoutTaskCount < 7 ? layoutTaskCount : 6;
- lines = layoutTaskCount < 7 ? 1 : 2;
- }
-
- int taskWidth, taskHeight;
- int maxTaskWidth = (mWindowRect.width() - 2 * mPaddingLeftRight
- - (tasksPerLine - 1) * mPaddingTaskView) / tasksPerLine;
- int maxTaskHeight = (mWindowRect.height() - 2 * mPaddingTopBottom
- - (lines - 1) * mPaddingTaskView) / lines;
-
- if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) {
- // Width bound.
- taskWidth = maxTaskWidth;
- // Here we should round the height to the nearest integer.
- taskHeight = (int) (maxTaskWidth / mAppAspectRatio + mTitleBarHeight + 0.5);
- } else {
- // Height bound.
- taskHeight = maxTaskHeight;
- // Here we should round the width to the nearest integer.
- taskWidth = (int) ((taskHeight - mTitleBarHeight) * mAppAspectRatio + 0.5);
- }
- size.set(0, 0, taskWidth, taskHeight);
-
- int emptySpaceX = mWindowRect.width() - 2 * mPaddingLeftRight
- - (tasksPerLine * taskWidth) - (tasksPerLine - 1) * mPaddingTaskView;
- int emptySpaceY = mWindowRect.height() - 2 * mPaddingTopBottom
- - (lines * taskHeight) - (lines - 1) * mPaddingTaskView;
- for (int taskIndex = 0; taskIndex < taskCount; taskIndex++) {
- // We also need to invert the index in order to display the most recent tasks first.
- int taskLayoutIndex = taskCount - taskIndex - 1;
-
- int xIndex = taskLayoutIndex % tasksPerLine;
- int yIndex = taskLayoutIndex / tasksPerLine;
- xOffsets[taskIndex] = mWindowRect.left +
- emptySpaceX / 2 + mPaddingLeftRight + (taskWidth + mPaddingTaskView) * xIndex;
- yOffsets[taskIndex] = mWindowRect.top +
- emptySpaceY / 2 + mPaddingTopBottom + (taskHeight + mPaddingTaskView) * yIndex;
- }
- }
-
- private int getTasksPerLine(int taskCount) {
- switch(taskCount) {
- case 0:
- return 0;
- case 1:
- return 1;
- case 2:
- case 4:
- return 2;
- case 3:
- case 5:
- case 6:
- return 3;
- case 7:
- case 8:
- return 4;
- default:
- throw new IllegalArgumentException("Unsupported task count " + taskCount);
- }
- }
- }
-
- /**
- * We can find task view sizes and positions from mTaskGridRectInfoList[k - 1] when there
- * are k tasks.
- */
- private TaskGridRectInfo[] mTaskGridRectInfoList;
-
- public TaskGridLayoutAlgorithm(Context context) {
- reloadOnConfigurationChange(context);
- }
-
- public void reloadOnConfigurationChange(Context context) {
- Resources res = context.getResources();
- mPaddingTaskView = res.getDimensionPixelSize(R.dimen.recents_grid_padding_task_view);
- mFocusedFrameThickness = res.getDimensionPixelSize(
- R.dimen.recents_grid_task_view_focused_frame_thickness);
-
- mTaskGridRect = new Rect();
- mTitleBarHeight = res.getDimensionPixelSize(R.dimen.recents_grid_task_view_header_height);
-
- WindowManager windowManager = (WindowManager) context
- .getSystemService(Context.WINDOW_SERVICE);
- windowManager.getDefaultDisplay().getRealSize(mScreenSize);
-
- updateAppAspectRatio();
- }
-
- /**
- * Returns the proper task view transform of a certain task view, according to its index and the
- * amount of task views.
- * @param taskIndex The index of the task view whose transform we want. It's never greater
- * than {@link MAX_LAYOUT_TASK_COUNT}.
- * @param taskCount The current amount of task views.
- * @param transformOut The result transform that this method returns.
- * @param stackLayout The base stack layout algorithm.
- * @return The expected transform of the (taskIndex)th task view.
- */
- public TaskViewTransform getTransform(int taskIndex, int taskCount,
- TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) {
- if (taskCount == 0) {
- transformOut.reset();
- return transformOut;
- }
-
- TaskGridRectInfo gridInfo = mTaskGridRectInfoList[taskCount - 1];
- mTaskGridRect.set(gridInfo.size);
-
- int x = gridInfo.xOffsets[taskIndex];
- int y = gridInfo.yOffsets[taskIndex];
- float z = stackLayout.mMaxTranslationZ;
-
- // We always set the dim alpha to 0, since we don't want grid task views to dim.
- float dimAlpha = 0f;
- // We always set the alpha of the view outline to 1, to make sure the shadow is visible.
- float viewOutlineAlpha = 1f;
-
- // We also need to invert the index in order to display the most recent tasks first.
- int taskLayoutIndex = taskCount - taskIndex - 1;
- boolean isTaskViewVisible = taskLayoutIndex < MAX_LAYOUT_TASK_COUNT;
-
- // Fill out the transform
- transformOut.scale = 1f;
- transformOut.alpha = isTaskViewVisible ? 1f : 0f;
- transformOut.translationZ = z;
- transformOut.dimAlpha = dimAlpha;
- transformOut.viewOutlineAlpha = viewOutlineAlpha;
- transformOut.rect.set(mTaskGridRect);
- transformOut.rect.offset(x, y);
- Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
- // We only show the 8 most recent tasks.
- transformOut.visible = isTaskViewVisible;
- return transformOut;
- }
-
- /**
- * Return the proper task index to focus for arrow key navigation.
- * @param taskCount The amount of tasks.
- * @param currentFocusedIndex The index of the currently focused task.
- * @param direction The direction we're navigating.
- * @return The index of the task that should get the focus.
- */
- public int navigateFocus(int taskCount, int currentFocusedIndex, Direction direction) {
- if (taskCount < 1 || taskCount > MAX_LAYOUT_TASK_COUNT) {
- return -1;
- }
- if (currentFocusedIndex == -1) {
- return 0;
- }
- int newIndex = currentFocusedIndex;
- final TaskGridRectInfo gridInfo = mTaskGridRectInfoList[taskCount - 1];
- final int currentLine = (taskCount - 1 - currentFocusedIndex) / gridInfo.tasksPerLine;
- switch (direction) {
- case UP:
- newIndex += gridInfo.tasksPerLine;
- newIndex = newIndex >= taskCount ? currentFocusedIndex : newIndex;
- break;
- case DOWN:
- newIndex -= gridInfo.tasksPerLine;
- newIndex = newIndex < 0 ? currentFocusedIndex : newIndex;
- break;
- case LEFT:
- newIndex++;
- final int leftMostIndex = (taskCount - 1) - currentLine * gridInfo.tasksPerLine;
- newIndex = newIndex > leftMostIndex ? currentFocusedIndex : newIndex;
- break;
- case RIGHT:
- newIndex--;
- int rightMostIndex =
- (taskCount - 1) - (currentLine + 1) * gridInfo.tasksPerLine + 1;
- rightMostIndex = rightMostIndex < 0 ? 0 : rightMostIndex;
- newIndex = newIndex < rightMostIndex ? currentFocusedIndex : newIndex;
- break;
- }
- return newIndex;
- }
-
- public void initialize(Rect windowRect) {
- mWindowRect = windowRect;
- // Define paddings in terms of percentage of the total area.
- mPaddingLeftRight = (int) (0.025f * Math.min(mWindowRect.width(), mWindowRect.height()));
- mPaddingTopBottom = (int) (0.1 * mWindowRect.height());
-
- // Pre-calculate the positions and offsets of task views so that we can reuse them directly
- // in the future.
- mTaskGridRectInfoList = new TaskGridRectInfo[MAX_LAYOUT_TASK_COUNT];
- for (int i = 0; i < MAX_LAYOUT_TASK_COUNT; i++) {
- mTaskGridRectInfoList[i] = new TaskGridRectInfo(i + 1);
- }
- }
-
- public void setSystemInsets(Rect systemInsets) {
- mSystemInsets = systemInsets;
- updateAppAspectRatio();
- }
-
- private void updateAppAspectRatio() {
- int usableWidth = mScreenSize.x - mSystemInsets.left - mSystemInsets.right;
- int usableHeight = mScreenSize.y - mSystemInsets.top - mSystemInsets.bottom;
- mAppAspectRatio = (float) usableWidth / (float) usableHeight;
- }
-
- public Rect getStackActionButtonRect() {
- Rect buttonRect = new Rect(mWindowRect);
- buttonRect.right -= mPaddingLeftRight;
- buttonRect.left += mPaddingLeftRight;
- buttonRect.bottom = buttonRect.top + mPaddingTopBottom;
- return buttonRect;
- }
-
- public void updateTaskGridRect(int taskCount) {
- if (taskCount > 0) {
- TaskGridRectInfo gridInfo = mTaskGridRectInfoList[taskCount - 1];
- mTaskGridRect.set(gridInfo.size);
- }
- }
-
- public Rect getTaskGridRect() {
- return mTaskGridRect;
- }
-
- public int getFocusFrameThickness() {
- return mFocusedFrameThickness;
- }
-
- public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
- int visibleCount = Math.min(TaskGridLayoutAlgorithm.MAX_LAYOUT_TASK_COUNT, tasks.size());
- return new VisibilityReport(visibleCount, visibleCount);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
deleted file mode 100644
index fe6bafb..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskViewFocusFrame.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views.grid;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-
-import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
-import com.android.systemui.R;
-import com.android.systemui.shared.recents.model.TaskStack;
-import com.android.systemui.recents.views.TaskStackView;
-
-public class TaskViewFocusFrame extends View implements OnGlobalFocusChangeListener {
-
- private TaskStackView mSv;
- private TaskGridLayoutAlgorithm mTaskGridLayoutAlgorithm;
- public TaskViewFocusFrame(Context context) {
- this(context, null);
- }
-
- public TaskViewFocusFrame(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public TaskViewFocusFrame(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public TaskViewFocusFrame(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- setBackground(mContext.getDrawable(
- R.drawable.recents_grid_task_view_focus_frame_background));
- setFocusable(false);
- hide();
- }
-
- public TaskViewFocusFrame(Context context, TaskStackView stackView,
- TaskGridLayoutAlgorithm taskGridLayoutAlgorithm) {
- this(context);
- mSv = stackView;
- mTaskGridLayoutAlgorithm = taskGridLayoutAlgorithm;
- }
-
- /**
- * Measure the width and height of the focus frame according to the current grid task view size.
- */
- public void measure() {
- int thickness = mTaskGridLayoutAlgorithm.getFocusFrameThickness();
- Rect rect = mTaskGridLayoutAlgorithm.getTaskGridRect();
- measure(
- MeasureSpec.makeMeasureSpec(rect.width() + thickness * 2, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(rect.height() + thickness * 2, MeasureSpec.EXACTLY));
- }
-
- /**
- * Layout the focus frame with its size.
- */
- public void layout() {
- layout(0, 0, getMeasuredWidth(), getMeasuredHeight());
- }
-
- /**
- * Update the current size of grid task view and the focus frame.
- */
- public void resize() {
- if (mSv.useGridLayout()) {
- mTaskGridLayoutAlgorithm.updateTaskGridRect(mSv.getStack().getTaskCount());
- measure();
- requestLayout();
- }
- }
-
- /**
- * Move the task view focus frame to surround the newly focused view. If it's {@code null} or
- * it's not an instance of GridTaskView, we hide the focus frame.
- * @param newFocus The newly focused view.
- */
- public void moveGridTaskViewFocus(View newFocus) {
- if (mSv.useGridLayout()) {
- // The frame only shows up in the grid layout. It shouldn't show up in the stack
- // layout including when we're in the split screen.
- if (newFocus instanceof GridTaskView) {
- // If the focus goes to a GridTaskView, we show the frame and layout it.
- int[] location = new int[2];
- newFocus.getLocationInWindow(location);
- int thickness = mTaskGridLayoutAlgorithm.getFocusFrameThickness();
- setTranslationX(location[0] - thickness);
- setTranslationY(location[1] - thickness);
- show();
- } else {
- // If focus goes to other views, we hide the frame.
- hide();
- }
- }
- }
-
- @Override
- public void onGlobalFocusChanged(View oldFocus, View newFocus) {
- if (!mSv.useGridLayout()) {
- return;
- }
- if (newFocus == null) {
- // We're going to touch mode, unset the focus.
- moveGridTaskViewFocus(null);
- return;
- }
- if (oldFocus == null) {
- // We're returning from touch mode, set the focus to the previously focused task.
- final TaskStack stack = mSv.getStack();
- final int taskCount = stack.getTaskCount();
- final int k = stack.indexOfTask(mSv.getFocusedTask());
- final int taskIndexToFocus = k == -1 ? (taskCount - 1) : (k % taskCount);
- mSv.setFocusedTask(taskIndexToFocus, false, true);
- }
- }
-
- private void show() {
- setAlpha(1f);
- }
-
- private void hide() {
- setAlpha(0f);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
deleted file mode 100644
index 49cac26..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/lowram/TaskStackLowRamLayoutAlgorithm.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views.lowram;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.view.ViewConfiguration;
-
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.shared.recents.utilities.Utilities;
-import com.android.systemui.shared.recents.model.Task;
-import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
-import com.android.systemui.recents.views.TaskViewTransform;
-
-import java.util.ArrayList;
-
-import static com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport;
-
-public class TaskStackLowRamLayoutAlgorithm {
-
- private static final String TAG = "TaskStackLowRamLayoutAlgorithm";
- private static final float MAX_OVERSCROLL = 0.2f / 0.3f;
-
- public static final int MAX_LAYOUT_TASK_COUNT = 9;
- public static final int NUM_TASK_VISIBLE_LAUNCHED_FROM_HOME = 2;
- public static final int NUM_TASK_VISIBLE_LAUNCHED_FROM_APP =
- NUM_TASK_VISIBLE_LAUNCHED_FROM_HOME + 1;
- private Rect mWindowRect;
-
- private int mFlingThreshold;
- private int mPadding;
- private int mPaddingLeftRight;
- private int mTopOffset;
- private int mPaddingEndTopBottom;
- private Rect mTaskRect = new Rect();
- private Rect mSystemInsets = new Rect();
-
- public TaskStackLowRamLayoutAlgorithm(Context context) {
- reloadOnConfigurationChange(context);
- }
-
- public void reloadOnConfigurationChange(Context context) {
- mPadding = context.getResources()
- .getDimensionPixelSize(R.dimen.recents_layout_side_margin_phone);
- mFlingThreshold = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
- }
-
- public void initialize(Rect windowRect) {
- mWindowRect = windowRect;
- if (mWindowRect.height() > 0) {
- int windowHeight = mWindowRect.height() - mSystemInsets.bottom;
- int windowWidth = mWindowRect.width() - mSystemInsets.right - mSystemInsets.left;
- int width = Math.min(windowWidth, windowHeight) - mPadding * 2;
- boolean isLandscape = windowWidth > windowHeight;
- mTaskRect.set(0, 0, width, isLandscape ? width * 2 / 3 : width);
- mPaddingLeftRight = (windowWidth - mTaskRect.width()) / 2;
- mPaddingEndTopBottom = (windowHeight - mTaskRect.height()) / 2;
-
- // Compute the top offset to center tasks in the middle of the screen
- mTopOffset = (getTotalHeightOfTasks(MAX_LAYOUT_TASK_COUNT) - windowHeight) / 2;
- }
- }
-
- public void setSystemInsets(Rect systemInsets) {
- mSystemInsets = systemInsets;
- }
-
- public VisibilityReport computeStackVisibilityReport(ArrayList<Task> tasks) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- int maxVisible = launchState.launchedFromHome || launchState.launchedFromPipApp
- || launchState.launchedWithNextPipApp
- ? NUM_TASK_VISIBLE_LAUNCHED_FROM_HOME
- : NUM_TASK_VISIBLE_LAUNCHED_FROM_APP;
- int visibleCount = Math.min(maxVisible, tasks.size());
- return new VisibilityReport(visibleCount, visibleCount);
- }
-
- public void getFrontOfStackTransform(TaskViewTransform transformOut,
- TaskStackLayoutAlgorithm stackLayout) {
- if (mWindowRect == null) {
- transformOut.reset();
- return;
- }
-
- // Calculate the static task y position 2 tasks after/below the middle/current task
- int windowHeight = mWindowRect.height() - mSystemInsets.bottom;
- int bottomOfCurrentTask = (windowHeight + mTaskRect.height()) / 2;
- int y = bottomOfCurrentTask + mTaskRect.height() + mPadding * 2;
- fillStackTransform(transformOut, y, stackLayout.mMaxTranslationZ, true);
- }
-
- public void getBackOfStackTransform(TaskViewTransform transformOut,
- TaskStackLayoutAlgorithm stackLayout) {
- if (mWindowRect == null) {
- transformOut.reset();
- return;
- }
-
- // Calculate the static task y position 2 tasks before/above the middle/current task
- int windowHeight = mWindowRect.height() - mSystemInsets.bottom;
- int topOfCurrentTask = (windowHeight - mTaskRect.height()) / 2;
- int y = topOfCurrentTask - (mTaskRect.height() + mPadding) * 2;
- fillStackTransform(transformOut, y, stackLayout.mMaxTranslationZ, true);
- }
-
- public TaskViewTransform getTransform(int taskIndex, float stackScroll,
- TaskViewTransform transformOut, int taskCount, TaskStackLayoutAlgorithm stackLayout) {
- if (taskCount == 0) {
- transformOut.reset();
- return transformOut;
- }
- boolean visible = true;
- int y;
- if (taskCount > 1) {
- y = getTaskTopFromIndex(taskIndex) - percentageToScroll(stackScroll);
-
- // Check visibility from the bottom of the task
- visible = y + mPadding + getTaskRect().height() > 0;
- } else {
- int windowHeight = mWindowRect.height() - mSystemInsets.bottom;
- y = (windowHeight - mTaskRect.height()) / 2 - percentageToScroll(stackScroll);
- }
- fillStackTransform(transformOut, y, stackLayout.mMaxTranslationZ, visible);
- return transformOut;
- }
-
- /**
- * Finds the closest task to the scroll percentage in the y axis and returns the percentage of
- * the task to scroll to.
- * @param scrollP percentage to find nearest to
- * @param numTasks number of tasks in recents stack
- * @param velocity speed of fling
- */
- public float getClosestTaskP(float scrollP, int numTasks, int velocity) {
- int y = percentageToScroll(scrollP);
-
- int lastY = getTaskTopFromIndex(0) - mPaddingEndTopBottom;
- for (int i = 1; i < numTasks; i++) {
- int taskY = getTaskTopFromIndex(i) - mPaddingEndTopBottom;
- int diff = taskY - y;
- if (diff > 0) {
- int diffPrev = Math.abs(y - lastY);
- boolean useNext = diff > diffPrev;
- if (Math.abs(velocity) > mFlingThreshold) {
- useNext = velocity > 0;
- }
- return useNext
- ? scrollToPercentage(lastY) : scrollToPercentage(taskY);
- }
- lastY = taskY;
- }
- return scrollToPercentage(lastY);
- }
-
- /**
- * Convert a scroll value to a percentage
- * @param scroll a scroll value
- * @return a percentage that represents the scroll from the total height of tasks
- */
- public float scrollToPercentage(int scroll) {
- return (float) scroll / (mTaskRect.height() + mPadding);
- }
-
- /**
- * Converts a percentage to the scroll value from the total height of tasks
- * @param p a percentage that represents the scroll value
- * @return a scroll value in pixels
- */
- public int percentageToScroll(float p) {
- return (int) (p * (mTaskRect.height() + mPadding));
- }
-
- /**
- * Get the min scroll progress for low ram layout. This computes the top position of the
- * first task and reduce by the end padding to center the first task
- * @return position of max scroll
- */
- public float getMinScrollP() {
- return getScrollPForTask(0);
- }
-
- /**
- * Get the max scroll progress for low ram layout. This computes the top position of the last
- * task and reduce by the end padding to center the last task
- * @param taskCount the amount of tasks in the recents stack
- * @return position of max scroll
- */
- public float getMaxScrollP(int taskCount) {
- return getScrollPForTask(taskCount - 1);
- }
-
- /**
- * Get the initial scroll value whether launched from home or from an app.
- * @param taskCount the amount of tasks currently in recents
- * @param fromHome if launching recents from home or not
- * @return from home it will return max value and from app it will return 2nd last task
- */
- public float getInitialScrollP(int taskCount, boolean fromHome) {
- if (fromHome) {
- return getMaxScrollP(taskCount);
- }
- if (taskCount < 2) {
- return 0;
- }
- return getScrollPForTask(taskCount - 2);
- }
-
- /**
- * Get the scroll progress for any task
- * @param taskIndex task index to get the scroll progress of
- * @return scroll progress of task
- */
- public float getScrollPForTask(int taskIndex) {
- return scrollToPercentage(getTaskTopFromIndex(taskIndex) - mPaddingEndTopBottom);
- }
-
- public Rect getTaskRect() {
- return mTaskRect;
- }
-
- public float getMaxOverscroll() {
- return MAX_OVERSCROLL;
- }
-
- private int getTaskTopFromIndex(int index) {
- return getTotalHeightOfTasks(index) - mTopOffset;
- }
-
- private int getTotalHeightOfTasks(int taskCount) {
- return taskCount * mTaskRect.height() + (taskCount + 1) * mPadding;
- }
-
- private void fillStackTransform(TaskViewTransform transformOut, int y, int translationZ,
- boolean visible) {
- transformOut.scale = 1f;
- transformOut.alpha = 1f;
- transformOut.translationZ = translationZ;
- transformOut.dimAlpha = 0f;
- transformOut.viewOutlineAlpha = 1f;
- transformOut.rect.set(getTaskRect());
- transformOut.rect.offset(mPaddingLeftRight + mSystemInsets.left, y);
- Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
- transformOut.visible = visible;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 178c5c5..38011d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -44,11 +44,10 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationData;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 59c15f1..329a33d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -19,7 +19,7 @@
import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
import static android.app.StatusBarManager.windowStateToString;
-import static com.android.systemui.OverviewProxyService.OverviewProxyListener;
+import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener;
import static com.android.systemui.shared.system.NavigationBarCompat.InteractionType;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
@@ -74,7 +74,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 52134d9..22b6ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -34,7 +34,7 @@
import android.widget.Space;
import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.shared.plugins.PluginManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 2ab5958..6728f08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -57,7 +57,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.Interpolators;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.PluginListener;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
index fd5403f..3980126 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickStepController.java
@@ -20,8 +20,8 @@
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
import static com.android.systemui.Interpolators.ALPHA_IN;
import static com.android.systemui.Interpolators.ALPHA_OUT;
-import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
-import static com.android.systemui.OverviewProxyService.TAG_OPS;
+import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
+import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
@@ -56,7 +56,7 @@
import android.view.WindowManagerGlobal;
import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index 855592f..c6e98e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -44,8 +44,8 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
-import com.android.systemui.recents.misc.SysUiTaskStackChangeListener;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
import com.android.systemui.statusbar.policy.RotationLockController;
@@ -400,7 +400,7 @@
}
}
- private class TaskStackListenerImpl extends SysUiTaskStackChangeListener {
+ private class TaskStackListenerImpl extends TaskStackChangeListener {
// Invalidate any rotation suggestion on task change or activity orientation change
// Note: all callbacks happen on main thread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 37eccb5..b2a04ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -135,7 +135,6 @@
import com.android.systemui.Interpolators;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.RecentsComponent;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
@@ -4121,7 +4120,7 @@
protected Display mDisplay;
- protected RecentsComponent mRecents;
+ protected Recents mRecents;
protected NotificationShelf mNotificationShelf;
protected EmptyShadeView mEmptyShadeView;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 298a93e..6fa73ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -34,7 +34,6 @@
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.TypedValue;
-import android.view.Display;
import android.view.HapticFeedbackConstants;
import android.view.InputDevice;
import android.view.KeyCharacterMap;
@@ -49,7 +48,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
-import com.android.systemui.OverviewProxyService;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.R;
import com.android.systemui.plugins.statusbar.phone.NavBarButtonProvider.ButtonInterface;
import com.android.systemui.shared.system.NavigationBarCompat;