QuickSwitch Compat Q to U (#3948)
Initial support quickstep, Android versions from Q to U, ensuring a smooth and efficient user experience. Enjoy effortless navigation and swift app switching on your Android device with QuickSwitch's compatibility across the Q, R, S, T, and U. Co-authored-by: Goooler <wangzongler@gmail.com> Co-authored-by: 无言 <57122860+liu-wanshun@users.noreply.github.com>
This commit is contained in:
111 files changed
+4547
-602
No files matched your search
+23
-2
@@ -92,6 +92,9 @@ allprojects {
|
||||
libraries.from(files(frameworkJar))
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
compileOnly files(frameworkJar)
|
||||
}
|
||||
}
|
||||
|
||||
compileOnlyCommonJars = {
|
||||
@@ -99,7 +102,13 @@ allprojects {
|
||||
compileOnly fileTree(dir: FRAMEWORK_PREBUILTS_DIR, include: 'SystemUI-core.jar')
|
||||
compileOnly fileTree(dir: FRAMEWORK_PREBUILTS_DIR, include: 'SystemUI-statsd.jar')
|
||||
compileOnly fileTree(dir: FRAMEWORK_PREBUILTS_DIR, include: 'WindowManager-Shell-14.jar')
|
||||
compileOnly fileTree(dir: FRAMEWORK_PREBUILTS_DIR, include: 'framework-14.jar')
|
||||
|
||||
compileOnly projects.compatLib
|
||||
compileOnly projects.compatLib.compatLibVQ
|
||||
compileOnly projects.compatLib.compatLibVR
|
||||
compileOnly projects.compatLib.compatLibVS
|
||||
compileOnly projects.compatLib.compatLibVT
|
||||
compileOnly projects.compatLib.compatLibVU
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +128,7 @@ final def releaseName = "Beta 1"
|
||||
final def versionDisplayName = "${version} ${isReleaseBuild ? releaseName : devReleaseName}"
|
||||
final def majorVersion = versionDisplayName.split("\\.")[0]
|
||||
|
||||
final def quickstepMinSdk = "34"
|
||||
final def quickstepMinSdk = "29"
|
||||
final def quickstepMaxSdk = "34"
|
||||
|
||||
android {
|
||||
@@ -320,6 +329,14 @@ dependencies {
|
||||
withQuickstepImplementation projects.systemUIPluginCore
|
||||
withQuickstepCompileOnly projects.systemUICommon
|
||||
|
||||
// QuickSwitch Compat
|
||||
withQuickstepImplementation projects.compatLib
|
||||
withQuickstepImplementation projects.compatLib.compatLibVQ
|
||||
withQuickstepImplementation projects.compatLib.compatLibVR
|
||||
withQuickstepImplementation projects.compatLib.compatLibVS
|
||||
withQuickstepImplementation projects.compatLib.compatLibVT
|
||||
withQuickstepImplementation projects.compatLib.compatLibVU
|
||||
|
||||
implementation fileTree(dir: FRAMEWORK_PREBUILTS_DIR, include: 'SystemUI-statsd-14.jar')
|
||||
|
||||
implementation fileTree(dir: FRAMEWORK_PREBUILTS_DIR, include: 'WindowManager-Shell-14.jar')
|
||||
@@ -398,6 +415,10 @@ ksp {
|
||||
}
|
||||
|
||||
spotless {
|
||||
java {
|
||||
target("compatLib/**/src/**/*.java")
|
||||
googleJavaFormat().aosp()
|
||||
}
|
||||
kotlin {
|
||||
target("lawnchair/src/**/*.kt")
|
||||
ktlint().customRuleSets([
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# Lawnchair Quickstep Compat Lib
|
||||
+11
-1
@@ -4,6 +4,16 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace "app.lawnchair.compatlib"
|
||||
|
||||
buildFeatures {
|
||||
aidl true
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
aidl.srcDirs = ['src/main/java']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addFrameworkJar('framework-12.jar')
|
||||
addFrameworkJar('framework-14.jar')
|
||||
@@ -0,0 +1,14 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "app.lawnchair.compatlib.ten"
|
||||
}
|
||||
|
||||
addFrameworkJar('framework-10.jar')
|
||||
|
||||
dependencies {
|
||||
implementation projects.compatLib
|
||||
implementation projects.compatLib.compatLibVR
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
package app.lawnchair.compatlib.ten;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerCompat;
|
||||
import app.lawnchair.compatlib.eleven.ActivityManagerCompatVR;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityManagerCompatVQ extends ActivityManagerCompatVR {
|
||||
|
||||
@Override
|
||||
public void invalidateHomeTaskSnapshot(Activity homeActivity) {
|
||||
// do nothing ,android Q not support
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
|
||||
|
||||
int ignoreActivityType = WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
if (filterOnlyVisibleRecents) {
|
||||
ignoreActivityType = WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
ActivityTaskManager.getService()
|
||||
.getFilteredTasks(
|
||||
NUM_RECENT_ACTIVITIES_REQUEST,
|
||||
ignoreActivityType,
|
||||
WindowConfiguration.WINDOWING_MODE_PINNED);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.toArray(new ActivityManager.RunningTaskInfo[tasks.size()]);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationRunnerCompat runnerCompat) {
|
||||
|
||||
IRecentsAnimationRunner runner = null;
|
||||
if (runnerCompat != null) {
|
||||
runner =
|
||||
new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(
|
||||
IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps,
|
||||
Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
runnerCompat.onAnimationStart(
|
||||
controller, apps, null, homeContentInsets, minimizedHomeBounds);
|
||||
}
|
||||
|
||||
public void reportAllDrawn() {}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(boolean deferredWithScreenshot) {
|
||||
runnerCompat.onAnimationCanceled(deferredWithScreenshot);
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
ActivityTaskManager.getService().startRecentsActivity(intent, null, runner);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
|
||||
|
||||
int ignoreActivityType = WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
if (filterOnlyVisibleRecents) {
|
||||
ignoreActivityType = WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
||||
}
|
||||
try {
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
ActivityTaskManager.getService()
|
||||
.getFilteredTasks(
|
||||
1,
|
||||
ignoreActivityType,
|
||||
WindowConfiguration.WINDOWING_MODE_PINNED);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.get(0);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThumbnailData makeThumbnailData(ActivityManager.TaskSnapshot snapshot) {
|
||||
ThumbnailData data = new ThumbnailData();
|
||||
data.thumbnail =
|
||||
Bitmap.wrapHardwareBuffer(snapshot.getSnapshot(), snapshot.getColorSpace());
|
||||
data.insets = new Rect(snapshot.getContentInsets());
|
||||
data.orientation = snapshot.getOrientation();
|
||||
data.reducedResolution = snapshot.isReducedResolution();
|
||||
// TODO(b/149579527): Pass task size instead of computing scale.
|
||||
// Assume width and height were scaled the same; compute scale only for width
|
||||
data.scale = snapshot.getScale();
|
||||
data.isRealSnapshot = snapshot.isRealSnapshot();
|
||||
data.isTranslucent = snapshot.isTranslucent();
|
||||
data.windowingMode = snapshot.getWindowingMode();
|
||||
data.systemUiVisibility = snapshot.getSystemUiVisibility();
|
||||
return data;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package app.lawnchair.compatlib.ten;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
|
||||
public class ActivityOptionsCompatVQ extends ActivityOptionsCompat {
|
||||
@Override
|
||||
public ActivityOptions makeCustomAnimation(
|
||||
Context context,
|
||||
int enterResId,
|
||||
int exitResId,
|
||||
Runnable callback,
|
||||
Handler callbackHandler) {
|
||||
return ActivityOptions.makeCustomAnimation(
|
||||
context,
|
||||
enterResId,
|
||||
exitResId,
|
||||
callbackHandler,
|
||||
new ActivityOptions.OnAnimationStartedListener() {
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
if (callback != null) {
|
||||
callbackHandler.post(callback);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapter remoteAnimationAdapter,
|
||||
Object remoteTransition,
|
||||
String debugName) {
|
||||
return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package app.lawnchair.compatlib.ten;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
import app.lawnchair.compatlib.eleven.QuickstepCompatFactoryVR;
|
||||
|
||||
public class QuickstepCompatFactoryVQ extends QuickstepCompatFactoryVR {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVQ();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityOptionsCompat getActivityOptionsCompat() {
|
||||
return new ActivityOptionsCompatVQ();
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+71
-29
@@ -4,6 +4,7 @@ import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
import static android.graphics.Bitmap.Config.ARGB_8888;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.Intent;
|
||||
@@ -18,41 +19,63 @@ import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerCompat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerStub;
|
||||
|
||||
public class ActivityManagerCompatVR extends ActivityManagerCompat {
|
||||
|
||||
private static final String TAG = "ActivityManagerCompatVR";
|
||||
|
||||
@Override
|
||||
public void startRecentsActivity(Intent intent, long eventTime, RecentsAnimationRunnerStub runner) throws RemoteException {
|
||||
IRecentsAnimationRunner wrappedRunner = null;
|
||||
if (runner != null) {
|
||||
wrappedRunner = new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds) {
|
||||
runner.onAnimationStart(controller, apps, wallpapers, homeContentInsets, minimizedHomeBounds);
|
||||
}
|
||||
public void invalidateHomeTaskSnapshot(Activity homeActivity) {
|
||||
try {
|
||||
ActivityTaskManager.getService()
|
||||
.invalidateHomeTaskSnapshot(homeActivity.getActivityToken());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to invalidate home snapshot", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(ActivityManager.TaskSnapshot taskSnapshot) {
|
||||
runner.onAnimationCanceled(taskSnapshot);
|
||||
}
|
||||
@Override
|
||||
public void startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationRunnerCompat runnerCompat) {
|
||||
IRecentsAnimationRunner runner = null;
|
||||
if (runnerCompat != null) {
|
||||
runner =
|
||||
new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(
|
||||
IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
runnerCompat.onAnimationStart(
|
||||
controller,
|
||||
apps,
|
||||
wallpapers,
|
||||
homeContentInsets,
|
||||
minimizedHomeBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
runner.onTaskAppeared(app);
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void onAnimationCanceled(ActivityManager.TaskSnapshot taskSnapshot) {
|
||||
runnerCompat.onAnimationCanceled(taskSnapshot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
runnerCompat.onTaskAppeared(app);
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
getService().startRecentsActivity(intent, null, runner);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to cancel recents animation", e);
|
||||
}
|
||||
getService().startRecentsActivity(intent, null, wrappedRunner);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,14 +96,31 @@ public class ActivityManagerCompatVR extends ActivityManagerCompat {
|
||||
@Override
|
||||
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
try {
|
||||
return ActivityTaskManager.getService().getRecentTasks(numTasks,
|
||||
RECENT_IGNORE_UNAVAILABLE, userId).getList();
|
||||
return ActivityTaskManager.getService()
|
||||
.getRecentTasks(numTasks, RECENT_IGNORE_UNAVAILABLE, userId)
|
||||
.getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to get recent tasks", e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
|
||||
try {
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
ActivityTaskManager.getService()
|
||||
.getFilteredTasks(
|
||||
NUM_RECENT_ACTIVITIES_REQUEST, filterOnlyVisibleRecents);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.toArray(new ActivityManager.RunningTaskInfo[tasks.size()]);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
|
||||
ActivityManager.TaskSnapshot snapshot = null;
|
||||
try {
|
||||
@@ -95,7 +135,8 @@ public class ActivityManagerCompatVR extends ActivityManagerCompat {
|
||||
}
|
||||
}
|
||||
|
||||
public ThumbnailData takeScreenshot(IRecentsAnimationController animationController, int taskId) {
|
||||
public ThumbnailData takeScreenshot(
|
||||
IRecentsAnimationController animationController, int taskId) {
|
||||
try {
|
||||
ActivityManager.TaskSnapshot snapshot = animationController.screenshotTask(taskId);
|
||||
return snapshot != null ? makeThumbnailData(snapshot) : new ThumbnailData();
|
||||
@@ -110,8 +151,9 @@ public class ActivityManagerCompatVR extends ActivityManagerCompat {
|
||||
final GraphicBuffer buffer = snapshot.getSnapshot();
|
||||
if (buffer == null || (buffer.getUsage() & HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE) == 0) {
|
||||
// TODO(b/157562905): Workaround for a crash when we get a snapshot without this state
|
||||
Log.e("ThumbnailData", "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: "
|
||||
+ buffer);
|
||||
Log.e(
|
||||
"ThumbnailData",
|
||||
"Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: " + buffer);
|
||||
Point taskSize = snapshot.getTaskSize();
|
||||
data.thumbnail = Bitmap.createBitmap(taskSize.x, taskSize.y, ARGB_8888);
|
||||
data.thumbnail.eraseColor(Color.BLACK);
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package app.lawnchair.compatlib.eleven;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
|
||||
public class ActivityOptionsCompatVR extends ActivityOptionsCompat {
|
||||
private static final String TAG = "ActivityOptionsCompatVR";
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeCustomAnimation(
|
||||
Context context,
|
||||
int enterResId,
|
||||
int exitResId,
|
||||
Runnable callback,
|
||||
Handler callbackHandler) {
|
||||
return ActivityOptions.makeCustomAnimation(
|
||||
context,
|
||||
enterResId,
|
||||
exitResId,
|
||||
callbackHandler,
|
||||
new ActivityOptions.OnAnimationStartedListener() {
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
if (callback != null) {
|
||||
callbackHandler.post(callback);
|
||||
}
|
||||
}
|
||||
},
|
||||
null /* finishedListener */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapter remoteAnimationAdapter,
|
||||
Object remoteTransition,
|
||||
String debugName) {
|
||||
Log.e(TAG, "makeRemoteAnimation: " + debugName);
|
||||
return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter);
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package app.lawnchair.compatlib.eleven;
|
||||
|
||||
import android.app.IApplicationThread;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.RemoteTransition;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
import app.lawnchair.compatlib.QuickstepCompatFactory;
|
||||
import app.lawnchair.compatlib.RemoteTransitionCompat;
|
||||
|
||||
public class QuickstepCompatFactoryVR extends QuickstepCompatFactory {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVR();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityOptionsCompat getActivityOptionsCompat() {
|
||||
return new ActivityOptionsCompatVR();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RemoteTransitionCompat getRemoteTransitionCompat() {
|
||||
return new RemoteTransitionCompat() {
|
||||
@Override
|
||||
public RemoteTransition getRemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition,
|
||||
@Nullable IApplicationThread appThread,
|
||||
@Nullable String debugName) {
|
||||
return new RemoteTransition(remoteTransition, appThread, debugName);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package app.lawnchair.compatlib.eleven;
|
||||
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT;
|
||||
|
||||
import android.app.WindowConfiguration;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
public class WindowManagerCompatVR {
|
||||
public static final int NAV_BAR_POS_INVALID = NAV_BAR_INVALID;
|
||||
public static final int NAV_BAR_POS_LEFT = NAV_BAR_LEFT;
|
||||
public static final int NAV_BAR_POS_RIGHT = NAV_BAR_RIGHT;
|
||||
public static final int NAV_BAR_POS_BOTTOM = NAV_BAR_BOTTOM;
|
||||
|
||||
public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY =
|
||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
|
||||
public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY =
|
||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
|
||||
public static int getNavBarPosition(int displayId) {
|
||||
try {
|
||||
return WindowManagerGlobal.getWindowManagerService().getNavBarPosition(displayId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w("WindowManagerCompatVR", "Failed to get nav bar position");
|
||||
}
|
||||
return NAV_BAR_POS_INVALID;
|
||||
}
|
||||
}
|
||||
File renamed without changes.
+112
@@ -0,0 +1,112 @@
|
||||
package app.lawnchair.compatlib.twelve;
|
||||
|
||||
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityClient;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.TaskSnapshot;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerCompat;
|
||||
import java.util.List;
|
||||
|
||||
public class ActivityManagerCompatVS extends ActivityManagerCompat {
|
||||
|
||||
private static final String TAG = "ActivityManagerCompatVS";
|
||||
private final ActivityTaskManager mAtm = ActivityTaskManager.getInstance();
|
||||
|
||||
@Override
|
||||
public void invalidateHomeTaskSnapshot(Activity homeActivity) {
|
||||
try {
|
||||
ActivityClient.getInstance()
|
||||
.invalidateHomeTaskSnapshot(
|
||||
homeActivity == null ? null : homeActivity.getActivityToken());
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed to invalidate home snapshot", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TaskSnapshot getTaskSnapshot(
|
||||
int taskId, boolean isLowResolution, boolean takeSnapshotIfNeeded) {
|
||||
try {
|
||||
return getService().getTaskSnapshot(taskId, isLowResolution);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to getTaskSnapshot", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationRunnerCompat runnerCompat) {
|
||||
IRecentsAnimationRunner runner = null;
|
||||
if (runnerCompat != null) {
|
||||
runner =
|
||||
new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(
|
||||
IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
runnerCompat.onAnimationStart(
|
||||
controller,
|
||||
apps,
|
||||
wallpapers,
|
||||
homeContentInsets,
|
||||
minimizedHomeBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(TaskSnapshot taskSnapshot) {
|
||||
runnerCompat.onAnimationCanceled(taskSnapshot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
runnerCompat.onTaskAppeared(app);
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
getService().startRecentsActivity(intent, eventTime, runner);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to cancel recents animation", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
|
||||
// Note: The set of running tasks from the system is ordered by recency
|
||||
List<ActivityManager.RunningTaskInfo> tasks = mAtm.getTasks(1, filterOnlyVisibleRecents);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
return mAtm.getRecentTasks(numTasks, RECENT_IGNORE_UNAVAILABLE, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RunningTaskInfo[] getRunningTasks(boolean filterOnlyVisibleRecents) {
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
mAtm.getTasks(NUM_RECENT_ACTIVITIES_REQUEST, filterOnlyVisibleRecents);
|
||||
return tasks.toArray(new ActivityManager.RunningTaskInfo[tasks.size()]);
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package app.lawnchair.compatlib.twelve;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
|
||||
public class ActivityOptionsCompatVS extends ActivityOptionsCompat {
|
||||
private static final String TAG = "ActivityOptionsCompatVS";
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeCustomAnimation(
|
||||
Context context,
|
||||
int enterResId,
|
||||
int exitResId,
|
||||
Runnable callback,
|
||||
Handler callbackHandler) {
|
||||
return ActivityOptions.makeCustomTaskAnimation(
|
||||
context,
|
||||
enterResId,
|
||||
exitResId,
|
||||
callbackHandler,
|
||||
new ActivityOptions.OnAnimationStartedListener() {
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
if (callback != null) {
|
||||
callbackHandler.post(callback);
|
||||
}
|
||||
}
|
||||
},
|
||||
null /* finishedListener */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapter remoteAnimationAdapter,
|
||||
Object remoteTransition,
|
||||
String debugName) {
|
||||
Log.e(TAG, "makeRemoteAnimation: " + debugName);
|
||||
return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
package app.lawnchair.compatlib.twelve;
|
||||
|
||||
import android.app.IApplicationThread;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.RemoteTransition;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
import app.lawnchair.compatlib.QuickstepCompatFactory;
|
||||
import app.lawnchair.compatlib.RemoteTransitionCompat;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
public class QuickstepCompatFactoryVS extends QuickstepCompatFactory {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVS();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityOptionsCompat getActivityOptionsCompat() {
|
||||
return new ActivityOptionsCompatVS();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RemoteTransitionCompat getRemoteTransitionCompat() {
|
||||
return new RemoteTransitionCompat() {
|
||||
@Override
|
||||
public RemoteTransition getRemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition,
|
||||
@Nullable IApplicationThread appThread,
|
||||
@Nullable String debugName) {
|
||||
return createRemoteTransition(remoteTransition, appThread, debugName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TODO remove this as it causing glitches on first launch opening/closing app
|
||||
private RemoteTransition createRemoteTransition(
|
||||
IRemoteTransition remoteTransition, IApplicationThread appThread, String debugName) {
|
||||
try {
|
||||
Class<?> remoteTransitionClass = Class.forName("android.window.RemoteTransition");
|
||||
Constructor<?> constructor =
|
||||
remoteTransitionClass.getConstructor(
|
||||
IRemoteTransition.class, IApplicationThread.class, String.class);
|
||||
return (RemoteTransition) constructor.newInstance(remoteTransition, appThread);
|
||||
} catch (ClassNotFoundException
|
||||
| IllegalAccessException
|
||||
| InstantiationException
|
||||
| InvocationTargetException
|
||||
| NoSuchMethodException e) {
|
||||
throw new RuntimeException("Error creating RemoteTransitionCompat" + debugName, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'app.lawnchair.compatlib.thirteen'
|
||||
}
|
||||
|
||||
addFrameworkJar('framework-13.jar')
|
||||
|
||||
dependencies {
|
||||
implementation projects.compatLib
|
||||
implementation projects.compatLib.compatLibVS
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
package app.lawnchair.compatlib.thirteen;
|
||||
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.TaskSnapshot;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerCompat;
|
||||
import app.lawnchair.compatlib.twelve.ActivityManagerCompatVS;
|
||||
|
||||
public class ActivityManagerCompatVT extends ActivityManagerCompatVS {
|
||||
|
||||
private static final String TAG = "ActivityManagerCompatVT";
|
||||
private final ActivityTaskManager mAtm = ActivityTaskManager.getInstance();
|
||||
|
||||
@Override
|
||||
public void startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationRunnerCompat runnerCompat) {
|
||||
IRecentsAnimationRunner runner = null;
|
||||
if (runnerCompat != null) {
|
||||
runner =
|
||||
new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(
|
||||
IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
runnerCompat.onAnimationStart(
|
||||
controller,
|
||||
apps,
|
||||
wallpapers,
|
||||
homeContentInsets,
|
||||
minimizedHomeBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(
|
||||
int[] taskIds, TaskSnapshot[] taskSnapshots) {
|
||||
runnerCompat.onAnimationCanceled(taskIds, taskSnapshots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTasksAppeared(RemoteAnimationTarget[] apps) {
|
||||
runnerCompat.onTasksAppeared(apps);
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
getService().startRecentsActivity(intent, eventTime, runner);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to cancel recents animation", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskSnapshot getTaskSnapshot(
|
||||
int taskId, boolean isLowResolution, boolean takeSnapshotIfNeeded) {
|
||||
try {
|
||||
// android13 qpr1
|
||||
return getService()
|
||||
.getTaskSnapshot(taskId, isLowResolution, true /* takeSnapshotIfNeeded */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to getTaskSnapshot", e);
|
||||
return null;
|
||||
} catch (NoSuchMethodError e) {
|
||||
// android13/12
|
||||
return super.getTaskSnapshot(taskId, isLowResolution, takeSnapshotIfNeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package app.lawnchair.compatlib.thirteen;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import android.window.RemoteTransition;
|
||||
import app.lawnchair.compatlib.twelve.ActivityOptionsCompatVS;
|
||||
|
||||
public class ActivityOptionsCompatVT extends ActivityOptionsCompatVS {
|
||||
|
||||
private static final String TAG = "ActivityOptionsCompatVT";
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeCustomAnimation(
|
||||
Context context,
|
||||
int enterResId,
|
||||
int exitResId,
|
||||
Runnable callback,
|
||||
Handler callbackHandler) {
|
||||
return super.makeCustomAnimation(context, enterResId, exitResId, callback, callbackHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapter remoteAnimationAdapter,
|
||||
Object remoteTransition,
|
||||
String debugName) {
|
||||
Log.e(TAG, "makeRemoteAnimation: " + debugName);
|
||||
return ActivityOptions.makeRemoteAnimation(
|
||||
remoteAnimationAdapter, (RemoteTransition) remoteTransition);
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package app.lawnchair.compatlib.thirteen;
|
||||
|
||||
import android.app.IApplicationThread;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.RemoteTransition;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
import app.lawnchair.compatlib.RemoteTransitionCompat;
|
||||
import app.lawnchair.compatlib.twelve.QuickstepCompatFactoryVS;
|
||||
|
||||
public class QuickstepCompatFactoryVT extends QuickstepCompatFactoryVS {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVT();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityOptionsCompat getActivityOptionsCompat() {
|
||||
return new ActivityOptionsCompatVT();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RemoteTransitionCompat getRemoteTransitionCompat() {
|
||||
return new RemoteTransitionCompat() {
|
||||
@Override
|
||||
public RemoteTransition getRemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition,
|
||||
@Nullable IApplicationThread appThread,
|
||||
@Nullable String debugName) {
|
||||
return new RemoteTransition(remoteTransition, appThread);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'app.lawnchair.compatlib.fourteen'
|
||||
}
|
||||
|
||||
addFrameworkJar('framework-14.jar')
|
||||
|
||||
dependencies {
|
||||
implementation projects.compatLib
|
||||
implementation projects.compatLib.compatLibVS
|
||||
implementation projects.compatLib.compatLibVT
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package app.lawnchair.compatlib.fourteen;
|
||||
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.TaskSnapshot;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerCompat;
|
||||
import app.lawnchair.compatlib.thirteen.ActivityManagerCompatVT;
|
||||
|
||||
public class ActivityManagerCompatVU extends ActivityManagerCompatVT {
|
||||
|
||||
private static final String TAG = "ActivityManagerCompatVU";
|
||||
|
||||
@Override
|
||||
public void startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationRunnerCompat runnerCompat) {
|
||||
IRecentsAnimationRunner runner = null;
|
||||
if (runnerCompat != null) {
|
||||
runner =
|
||||
new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(
|
||||
IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds) {
|
||||
runnerCompat.onAnimationStart(
|
||||
controller,
|
||||
apps,
|
||||
wallpapers,
|
||||
homeContentInsets,
|
||||
minimizedHomeBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(
|
||||
int[] taskIds, TaskSnapshot[] taskSnapshots) {
|
||||
runnerCompat.onAnimationCanceled(taskIds, taskSnapshots);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTasksAppeared(RemoteAnimationTarget[] apps) {
|
||||
runnerCompat.onTasksAppeared(apps);
|
||||
}
|
||||
};
|
||||
}
|
||||
try {
|
||||
getService().startRecentsActivity(intent, eventTime, runner);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to cancel recents animation", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TaskSnapshot getTaskSnapshot(
|
||||
int taskId, boolean isLowResolution, boolean takeSnapshotIfNeeded) {
|
||||
try {
|
||||
return getService()
|
||||
.getTaskSnapshot(taskId, isLowResolution, true /* takeSnapshotIfNeeded */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to getTaskSnapshot", e);
|
||||
return null;
|
||||
} catch (NoSuchMethodError e) {
|
||||
return super.getTaskSnapshot(taskId, isLowResolution, takeSnapshotIfNeeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package app.lawnchair.compatlib.fourteen;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import android.window.RemoteTransition;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
|
||||
public class ActivityOptionsCompatVU extends ActivityOptionsCompat {
|
||||
@Override
|
||||
public ActivityOptions makeCustomAnimation(
|
||||
Context context,
|
||||
int enterResId,
|
||||
int exitResId,
|
||||
Runnable callback,
|
||||
Handler callbackHandler) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapter remoteAnimationAdapter,
|
||||
Object remoteTransition,
|
||||
String debugName) {
|
||||
return ActivityOptions.makeRemoteAnimation(
|
||||
remoteAnimationAdapter, (RemoteTransition) remoteTransition);
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
package app.lawnchair.compatlib.fourteen;
|
||||
|
||||
import android.app.IApplicationThread;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.RemoteTransition;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat;
|
||||
import app.lawnchair.compatlib.RemoteTransitionCompat;
|
||||
import app.lawnchair.compatlib.thirteen.QuickstepCompatFactoryVT;
|
||||
|
||||
public class QuickstepCompatFactoryVU extends QuickstepCompatFactoryVT {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVU();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityOptionsCompat getActivityOptionsCompat() {
|
||||
return new ActivityOptionsCompatVU();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public RemoteTransitionCompat getRemoteTransitionCompat() {
|
||||
return new RemoteTransitionCompat() {
|
||||
@Override
|
||||
public RemoteTransition getRemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition,
|
||||
@Nullable IApplicationThread appThread,
|
||||
@Nullable String debugName) {
|
||||
return new RemoteTransition(remoteTransition, appThread, debugName);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.window;
|
||||
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.IRemoteTransitionFinishedCallback;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
/**
|
||||
* Interface allowing remote processes to play transition animations.
|
||||
* The usage flow is as follows:
|
||||
* <p><ol>
|
||||
* <li>The remote tags a lifecycle event with an IRemoteTransition (via a parameter in
|
||||
* ActivityOptions#makeRemoteAnimation) or a transition matches a filter registered via
|
||||
* Transitions#registerRemote.
|
||||
* <li>Shell then associates the transition for the event with the IRemoteTransition
|
||||
* <li>Shell receives onTransitionReady and delegates the animation to the IRemoteTransition
|
||||
* via {@link #startAnimation}.
|
||||
* <li>Once the IRemoteTransition is done animating, it will call the finishCallback.
|
||||
* <li>Shell/Core finish-up the transition.
|
||||
* </ul>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
|
||||
oneway interface IRemoteTransition {
|
||||
/**
|
||||
* Starts a transition animation. Once complete, the implementation should call
|
||||
* `finishCallback`.
|
||||
*
|
||||
* @param token An identifier for the transition that should be animated.
|
||||
*/
|
||||
void startAnimation(in IBinder token, in TransitionInfo info, in SurfaceControl.Transaction t,
|
||||
in IRemoteTransitionFinishedCallback finishCallback);
|
||||
/**
|
||||
* Attempts to merge a transition animation into the animation that is currently
|
||||
* being played by this remote. If merge is not possible/supported, this should be a no-op.
|
||||
* If it *is* merged, the implementation should call `finishCallback` immediately.
|
||||
*
|
||||
* @param transition An identifier for the transition that wants to be merged.
|
||||
* @param mergeTarget The transition that is currently being animated by this remote.
|
||||
* If it can be merged, call `finishCallback`; otherwise, do
|
||||
* nothing.
|
||||
*/
|
||||
void mergeAnimation(in IBinder transition, in TransitionInfo info,
|
||||
in SurfaceControl.Transaction t, in IBinder mergeTarget,
|
||||
in IRemoteTransitionFinishedCallback finishCallback);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
package android.window;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.WindowContainerTransaction;
|
||||
/**
|
||||
* Interface to be invoked by the controlling process when a remote transition has finished.
|
||||
*
|
||||
* @see IRemoteTransition
|
||||
* @param wct An optional WindowContainerTransaction to apply before the transition finished.
|
||||
* @param sct An optional Surface Transaction that is added to the end of the finish/cleanup
|
||||
* transaction. This is applied by shell.Transitions (before submitting the wct).
|
||||
* {@hide}
|
||||
*/
|
||||
interface IRemoteTransitionFinishedCallback {
|
||||
void onTransitionFinished(in WindowContainerTransaction wct, in SurfaceControl.Transaction sct);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 android.window;
|
||||
|
||||
parcelable RemoteTransition;
|
||||
@@ -0,0 +1,199 @@
|
||||
package android.window;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.IApplicationThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import com.android.internal.util.DataClass;
|
||||
|
||||
/**
|
||||
* Represents a remote transition animation and information required to run it (eg. the app thread
|
||||
* that needs to be boosted).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@DataClass(genToString = true, genSetters = true, genAidl = true)
|
||||
public class RemoteTransition implements Parcelable {
|
||||
/** The actual remote-transition interface used to run the transition animation. */
|
||||
private @NonNull IRemoteTransition mRemoteTransition;
|
||||
|
||||
/** The application thread that will be running the remote transition. */
|
||||
private @Nullable IApplicationThread mAppThread;
|
||||
|
||||
/** A name for this that can be used for debugging. */
|
||||
private @Nullable String mDebugName;
|
||||
|
||||
/** Constructs with no app thread (animation runs in shell). */
|
||||
public RemoteTransition(@NonNull IRemoteTransition remoteTransition) {
|
||||
this(remoteTransition, null /* appThread */, null /* debugName */);
|
||||
}
|
||||
|
||||
/** Constructs with no app thread (animation runs in shell). */
|
||||
public RemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition, @Nullable String debugName) {
|
||||
this(remoteTransition, null /* appThread */, debugName);
|
||||
}
|
||||
|
||||
/** Get the IBinder associated with the underlying IRemoteTransition. */
|
||||
public @Nullable IBinder asBinder() {
|
||||
return mRemoteTransition.asBinder();
|
||||
}
|
||||
|
||||
// Code below generated by codegen v1.0.23.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
//
|
||||
// To regenerate run:
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/window/RemoteTransition.java
|
||||
//
|
||||
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||||
// Settings > Editor > Code Style > Formatter Control
|
||||
// @formatter:off
|
||||
/**
|
||||
* Creates a new RemoteTransition.
|
||||
*
|
||||
* @param remoteTransition The actual remote-transition interface used to run the transition
|
||||
* animation.
|
||||
* @param appThread The application thread that will be running the remote transition.
|
||||
* @param debugName A name for this that can be used for debugging.
|
||||
*/
|
||||
@DataClass.Generated.Member
|
||||
public RemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition,
|
||||
@Nullable IApplicationThread appThread,
|
||||
@Nullable String debugName) {
|
||||
this.mRemoteTransition = remoteTransition;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mRemoteTransition);
|
||||
this.mAppThread = appThread;
|
||||
this.mDebugName = debugName;
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
/** The actual remote-transition interface used to run the transition animation. */
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull IRemoteTransition getRemoteTransition() {
|
||||
return mRemoteTransition;
|
||||
}
|
||||
|
||||
/** The application thread that will be running the remote transition. */
|
||||
@DataClass.Generated.Member
|
||||
public @Nullable IApplicationThread getAppThread() {
|
||||
return mAppThread;
|
||||
}
|
||||
|
||||
/** A name for this that can be used for debugging. */
|
||||
@DataClass.Generated.Member
|
||||
public @Nullable String getDebugName() {
|
||||
return mDebugName;
|
||||
}
|
||||
|
||||
/** The actual remote-transition interface used to run the transition animation. */
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull RemoteTransition setRemoteTransition(@NonNull IRemoteTransition value) {
|
||||
mRemoteTransition = value;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mRemoteTransition);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** The application thread that will be running the remote transition. */
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull RemoteTransition setAppThread(@NonNull IApplicationThread value) {
|
||||
mAppThread = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** A name for this that can be used for debugging. */
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull RemoteTransition setDebugName(@NonNull String value) {
|
||||
mDebugName = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public String toString() {
|
||||
// You can override field toString logic by defining methods like:
|
||||
// String fieldNameToString() { ... }
|
||||
return "RemoteTransition { "
|
||||
+ "remoteTransition = "
|
||||
+ mRemoteTransition
|
||||
+ ", "
|
||||
+ "appThread = "
|
||||
+ mAppThread
|
||||
+ ", "
|
||||
+ "debugName = "
|
||||
+ mDebugName
|
||||
+ " }";
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
|
||||
// You can override field parcelling by defining methods like:
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
byte flg = 0;
|
||||
if (mAppThread != null) flg |= 0x2;
|
||||
if (mDebugName != null) flg |= 0x4;
|
||||
dest.writeByte(flg);
|
||||
dest.writeStrongInterface(mRemoteTransition);
|
||||
if (mAppThread != null) dest.writeStrongInterface(mAppThread);
|
||||
if (mDebugName != null) dest.writeString(mDebugName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||||
@DataClass.Generated.Member
|
||||
protected RemoteTransition(@NonNull android.os.Parcel in) {
|
||||
// You can override field unparcelling by defining methods like:
|
||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||
byte flg = in.readByte();
|
||||
IRemoteTransition remoteTransition =
|
||||
IRemoteTransition.Stub.asInterface(in.readStrongBinder());
|
||||
IApplicationThread appThread =
|
||||
(flg & 0x2) == 0
|
||||
? null
|
||||
: IApplicationThread.Stub.asInterface(in.readStrongBinder());
|
||||
String debugName = (flg & 0x4) == 0 ? null : in.readString();
|
||||
this.mRemoteTransition = remoteTransition;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mRemoteTransition);
|
||||
this.mAppThread = appThread;
|
||||
this.mDebugName = debugName;
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public static final @NonNull Parcelable.Creator<RemoteTransition> CREATOR =
|
||||
new Parcelable.Creator<RemoteTransition>() {
|
||||
@Override
|
||||
public RemoteTransition[] newArray(int size) {
|
||||
return new RemoteTransition[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteTransition createFromParcel(@NonNull android.os.Parcel in) {
|
||||
return new RemoteTransition(in);
|
||||
}
|
||||
};
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1678926409863L,
|
||||
codegenVersion = "1.0.23",
|
||||
sourceFile = "frameworks/base/core/java/android/window/RemoteTransition.java",
|
||||
inputSignatures =
|
||||
"private @android.annotation.NonNull android.window.IRemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.app.IApplicationThread mAppThread\nprivate @android.annotation.Nullable java.lang.String mDebugName\npublic @android.annotation.Nullable android.os.IBinder asBinder()\nclass RemoteTransition extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
// @formatter:on
|
||||
// End of generated code
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.window;
|
||||
|
||||
parcelable TransitionFilter;
|
||||
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.window;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.view.WindowManager.TransitionType;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.ComponentName;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.WindowManager;
|
||||
|
||||
/**
|
||||
* A parcelable filter that can be used for rerouting transitions to a remote. This is a local
|
||||
* representation so that the transition system doesn't need to make blocking queries over binder.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class TransitionFilter implements Parcelable {
|
||||
/** The associated requirement doesn't care about the z-order. */
|
||||
public static final int CONTAINER_ORDER_ANY = 0;
|
||||
|
||||
/** The associated requirement only matches the top-most (z-order) container. */
|
||||
public static final int CONTAINER_ORDER_TOP = 1;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(
|
||||
prefix = {"CONTAINER_ORDER_"},
|
||||
value = {
|
||||
CONTAINER_ORDER_ANY,
|
||||
CONTAINER_ORDER_TOP,
|
||||
})
|
||||
public @interface ContainerOrder {}
|
||||
|
||||
/**
|
||||
* When non-null: this is a list of transition types that this filter applies to. This filter
|
||||
* will fail for transitions that aren't one of these types.
|
||||
*/
|
||||
@Nullable public @TransitionType int[] mTypeSet = null;
|
||||
|
||||
/** All flags must be set on a transition. */
|
||||
public @WindowManager.TransitionFlags int mFlags = 0;
|
||||
|
||||
/** All flags must NOT be set on a transition. */
|
||||
public @WindowManager.TransitionFlags int mNotFlags = 0;
|
||||
|
||||
/** A list of required changes. To pass, a transition must meet all requirements. */
|
||||
@Nullable public Requirement[] mRequirements = null;
|
||||
|
||||
public TransitionFilter() {}
|
||||
|
||||
private TransitionFilter(Parcel in) {
|
||||
mTypeSet = in.createIntArray();
|
||||
mFlags = in.readInt();
|
||||
mNotFlags = in.readInt();
|
||||
mRequirements = in.createTypedArray(Requirement.CREATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if `info` meets all the requirements to pass this filter.
|
||||
*/
|
||||
public boolean matches(@NonNull TransitionInfo info) {
|
||||
if (mTypeSet != null) {
|
||||
// non-null typeset, so make sure info is one of the types.
|
||||
boolean typePass = false;
|
||||
for (int i = 0; i < mTypeSet.length; ++i) {
|
||||
if (info.getType() == mTypeSet[i]) {
|
||||
typePass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!typePass) return false;
|
||||
}
|
||||
if ((info.getFlags() & mFlags) != mFlags) {
|
||||
return false;
|
||||
}
|
||||
if ((info.getFlags() & mNotFlags) != 0) {
|
||||
return false;
|
||||
}
|
||||
// Make sure info meets all of the requirements.
|
||||
if (mRequirements != null) {
|
||||
for (int i = 0; i < mRequirements.length; ++i) {
|
||||
final boolean matches = mRequirements[i].matches(info);
|
||||
if (matches == mRequirements[i].mNot) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
/** @hide */
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeIntArray(mTypeSet);
|
||||
dest.writeInt(mFlags);
|
||||
dest.writeInt(mNotFlags);
|
||||
dest.writeTypedArray(mRequirements, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<TransitionFilter> CREATOR =
|
||||
new Creator<TransitionFilter>() {
|
||||
@Override
|
||||
public TransitionFilter createFromParcel(Parcel in) {
|
||||
return new TransitionFilter(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransitionFilter[] newArray(int size) {
|
||||
return new TransitionFilter[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
/** @hide */
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("{types=[");
|
||||
if (mTypeSet != null) {
|
||||
for (int i = 0; i < mTypeSet.length; ++i) {
|
||||
sb.append((i == 0 ? "" : ",") + WindowManager.transitTypeToString(mTypeSet[i]));
|
||||
}
|
||||
}
|
||||
sb.append("] flags=0x" + Integer.toHexString(mFlags));
|
||||
sb.append("] notFlags=0x" + Integer.toHexString(mNotFlags));
|
||||
sb.append(" checks=[");
|
||||
if (mRequirements != null) {
|
||||
for (int i = 0; i < mRequirements.length; ++i) {
|
||||
sb.append((i == 0 ? "" : ",") + mRequirements[i]);
|
||||
}
|
||||
}
|
||||
return sb.append("]}").toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches a change that a transition must contain to pass this filter. All requirements in a
|
||||
* filter must be met to pass the filter.
|
||||
*/
|
||||
public static final class Requirement implements Parcelable {
|
||||
public int mActivityType = ACTIVITY_TYPE_UNDEFINED;
|
||||
|
||||
/** This only matches if the change is independent of its parents. */
|
||||
public boolean mMustBeIndependent = true;
|
||||
|
||||
/** If this matches, the parent filter will fail */
|
||||
public boolean mNot = false;
|
||||
|
||||
public int[] mModes = null;
|
||||
|
||||
/** Matches only if all the flags here are set on the change. */
|
||||
public @TransitionInfo.ChangeFlags int mFlags = 0;
|
||||
|
||||
/** If this needs to be a task. */
|
||||
public boolean mMustBeTask = false;
|
||||
|
||||
public @ContainerOrder int mOrder = CONTAINER_ORDER_ANY;
|
||||
public ComponentName mTopActivity;
|
||||
|
||||
public Requirement() {}
|
||||
|
||||
private Requirement(Parcel in) {
|
||||
mActivityType = in.readInt();
|
||||
mMustBeIndependent = in.readBoolean();
|
||||
mNot = in.readBoolean();
|
||||
mModes = in.createIntArray();
|
||||
mFlags = in.readInt();
|
||||
mMustBeTask = in.readBoolean();
|
||||
mOrder = in.readInt();
|
||||
mTopActivity = in.readTypedObject(ComponentName.CREATOR);
|
||||
}
|
||||
|
||||
/** Go through changes and find if at-least one change matches this filter */
|
||||
boolean matches(@NonNull TransitionInfo info) {
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (mMustBeIndependent && !TransitionInfo.isIndependent(change, info)) {
|
||||
// Only look at independent animating windows.
|
||||
continue;
|
||||
}
|
||||
if (mOrder == CONTAINER_ORDER_TOP && i > 0) {
|
||||
continue;
|
||||
}
|
||||
if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
|
||||
if (change.getTaskInfo() == null
|
||||
|| change.getTaskInfo().getActivityType() != mActivityType) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!matchesTopActivity(change.getTaskInfo())) continue;
|
||||
if (mModes != null) {
|
||||
boolean pass = false;
|
||||
for (int m = 0; m < mModes.length; ++m) {
|
||||
if (mModes[m] == change.getMode()) {
|
||||
pass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pass) continue;
|
||||
}
|
||||
if ((change.getFlags() & mFlags) != mFlags) {
|
||||
continue;
|
||||
}
|
||||
if (mMustBeTask && change.getTaskInfo() == null) {
|
||||
continue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchesTopActivity(ActivityManager.RunningTaskInfo info) {
|
||||
if (mTopActivity == null) return true;
|
||||
if (info == null) return false;
|
||||
final ComponentName component = info.topActivity;
|
||||
return mTopActivity.equals(component);
|
||||
}
|
||||
|
||||
/** Check if the request matches this filter. It may generate false positives */
|
||||
boolean matches(@NonNull TransitionRequestInfo request) {
|
||||
// Can't check modes/order since the transition hasn't been built at this point.
|
||||
if (mActivityType == ACTIVITY_TYPE_UNDEFINED) return true;
|
||||
return request.getTriggerTask() != null
|
||||
&& request.getTriggerTask().getActivityType() == mActivityType
|
||||
&& matchesTopActivity(request.getTriggerTask());
|
||||
}
|
||||
|
||||
@Override
|
||||
/** @hide */
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(mActivityType);
|
||||
dest.writeBoolean(mMustBeIndependent);
|
||||
dest.writeBoolean(mNot);
|
||||
dest.writeIntArray(mModes);
|
||||
dest.writeInt(mFlags);
|
||||
dest.writeBoolean(mMustBeTask);
|
||||
dest.writeInt(mOrder);
|
||||
dest.writeTypedObject(mTopActivity, flags);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static final Creator<Requirement> CREATOR =
|
||||
new Creator<Requirement>() {
|
||||
@Override
|
||||
public Requirement createFromParcel(Parcel in) {
|
||||
return new Requirement(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Requirement[] newArray(int size) {
|
||||
return new Requirement[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
/** @hide */
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append('{');
|
||||
if (mNot) out.append("NOT ");
|
||||
out.append("atype=" + WindowConfiguration.activityTypeToString(mActivityType));
|
||||
out.append(" independent=" + mMustBeIndependent);
|
||||
out.append(" modes=[");
|
||||
if (mModes != null) {
|
||||
for (int i = 0; i < mModes.length; ++i) {
|
||||
out.append((i == 0 ? "" : ",") + TransitionInfo.modeToString(mModes[i]));
|
||||
}
|
||||
}
|
||||
out.append("]");
|
||||
out.append(" flags=" + TransitionInfo.flagsToString(mFlags));
|
||||
out.append(" mustBeTask=" + mMustBeTask);
|
||||
out.append(" order=" + containerOrderToString(mOrder));
|
||||
out.append(" topActivity=").append(mTopActivity);
|
||||
out.append("}");
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private static String containerOrderToString(int order) {
|
||||
switch (order) {
|
||||
case CONTAINER_ORDER_ANY:
|
||||
return "ANY";
|
||||
case CONTAINER_ORDER_TOP:
|
||||
return "TOP";
|
||||
}
|
||||
return "UNKNOWN(" + order + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package android.window;
|
||||
parcelable TransitionInfo;
|
||||
parcelable TransitionInfo.Change;
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,17 +1,40 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Intent;
|
||||
import android.os.RemoteException;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
|
||||
import android.window.TaskSnapshot;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ActivityManagerCompat {
|
||||
|
||||
public abstract void startRecentsActivity(Intent intent, long eventTime, RecentsAnimationRunnerStub runner) throws RemoteException;
|
||||
public static final int NUM_RECENT_ACTIVITIES_REQUEST = 3;
|
||||
|
||||
public abstract ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents);
|
||||
public abstract void invalidateHomeTaskSnapshot(final Activity homeActivity);
|
||||
|
||||
/**
|
||||
* Called only in S+ platform
|
||||
*
|
||||
* @param taskId
|
||||
* @param isLowResolution
|
||||
* @param takeSnapshotIfNeeded
|
||||
* @return
|
||||
*/
|
||||
@Nullable
|
||||
public TaskSnapshot getTaskSnapshot(
|
||||
int taskId, boolean isLowResolution, boolean takeSnapshotIfNeeded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationRunnerCompat runnerCompat);
|
||||
|
||||
public abstract ActivityManager.RunningTaskInfo getRunningTask(
|
||||
boolean filterOnlyVisibleRecents);
|
||||
|
||||
public abstract List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId);
|
||||
|
||||
public abstract ActivityManager.RunningTaskInfo[] getRunningTasks(
|
||||
boolean filterOnlyVisibleRecents);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
|
||||
public abstract class ActivityOptionsCompat {
|
||||
public abstract ActivityOptions makeCustomAnimation(
|
||||
Context context,
|
||||
int enterResId,
|
||||
int exitResId,
|
||||
final Runnable callback,
|
||||
final Handler callbackHandler);
|
||||
|
||||
public abstract ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapter remoteAnimationAdapter,
|
||||
Object remoteTransition,
|
||||
String debugName);
|
||||
}
|
||||
@@ -1,10 +1,5 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.view.AppTransitionAnimationSpec;
|
||||
import android.view.IRemoteAnimationRunner;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
public abstract class QuickstepCompatFactory {
|
||||
@@ -12,7 +7,9 @@ public abstract class QuickstepCompatFactory {
|
||||
@NonNull
|
||||
public abstract ActivityManagerCompat getActivityManagerCompat();
|
||||
|
||||
public abstract IRemoteAnimationRunner.Stub wrapRemoteAnimationRunnerStub(RemoteAnimationRunnerStub compatStub);
|
||||
@NonNull
|
||||
public abstract ActivityOptionsCompat getActivityOptionsCompat();
|
||||
|
||||
public abstract AppTransitionAnimationSpec createAppTransitionAnimationSpec(int taskId, Bitmap buffer, Rect rect);
|
||||
@NonNull
|
||||
public abstract RemoteTransitionCompat getRemoteTransitionCompat();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
public interface RecentsAnimationRunnerCompat {
|
||||
|
||||
void onAnimationStart(
|
||||
IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets,
|
||||
Rect minimizedHomeBounds);
|
||||
|
||||
/** Called only in T platform */
|
||||
void onAnimationCanceled(int[] taskIds, TaskSnapshot[] taskSnapshots);
|
||||
|
||||
/** Called only in Q/R/S platform */
|
||||
void onAnimationCanceled(Object taskSnapshot);
|
||||
|
||||
/** Called only in R/S platform */
|
||||
void onTaskAppeared(RemoteAnimationTarget app);
|
||||
|
||||
/** Called only in T+ platform */
|
||||
void onTasksAppeared(RemoteAnimationTarget[] apps);
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
|
||||
public interface RecentsAnimationRunnerStub {
|
||||
void onAnimationStart(IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds);
|
||||
|
||||
void onAnimationCanceled(Object taskSnapshot);
|
||||
|
||||
void onTaskAppeared(RemoteAnimationTarget app);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.IRemoteAnimationFinishedCallback;
|
||||
|
||||
public interface RemoteAnimationRunnerStub {
|
||||
|
||||
void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
|
||||
final IRemoteAnimationFinishedCallback finishedCallback);
|
||||
|
||||
void onAnimationCancelled();
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.IApplicationThread;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.RemoteTransition;
|
||||
|
||||
public abstract class RemoteTransitionCompat {
|
||||
|
||||
public abstract RemoteTransition getRemoteTransition(
|
||||
@NonNull IRemoteTransition remoteTransition,
|
||||
@Nullable IApplicationThread appThread,
|
||||
@Nullable String debugName);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.IRemoteTransitionFinishedCallback;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
public interface RemoteTransitionStub {
|
||||
/**
|
||||
* Starts a transition animation. Once complete, the implementation should call
|
||||
* `finishCallback`.
|
||||
*
|
||||
* @param token An identifier for the transition that should be animated.
|
||||
*/
|
||||
void startAnimation(IBinder token, TransitionInfo info, SurfaceControl.Transaction t,
|
||||
IRemoteTransitionFinishedCallback finishCallback);
|
||||
|
||||
/**
|
||||
* Attempts to merge a transition animation into the animation that is currently
|
||||
* being played by this remote. If merge is not possible/supported, this should be a no-op.
|
||||
* If it *is* merged, the implementation should call `finishCallback` immediately.
|
||||
*
|
||||
* @param transition An identifier for the transition that wants to be merged.
|
||||
* @param mergeTarget The transition that is currently being animated by this remote.
|
||||
* If it can be merged, call `finishCallback`; otherwise, do
|
||||
* nothing.
|
||||
*/
|
||||
void mergeAnimation(IBinder transition, TransitionInfo info,
|
||||
SurfaceControl.Transaction t, IBinder mergeTarget,
|
||||
IRemoteTransitionFinishedCallback finishCallback);
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package app.lawnchair.compatlib;
|
||||
|
||||
public class TaskSnapshotCompat {
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package app.lawnchair.compatlib.utils;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.ColorSpace;
|
||||
import android.graphics.ParcelableColorSpace;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.os.Bundle;
|
||||
import java.util.Objects;
|
||||
|
||||
/** Utils for working with Bitmaps. */
|
||||
public final class BitmapUtil {
|
||||
private static final String KEY_BUFFER = "bitmap_util_buffer";
|
||||
private static final String KEY_COLOR_SPACE = "bitmap_util_color_space";
|
||||
|
||||
private BitmapUtil() {}
|
||||
|
||||
/**
|
||||
* Creates a Bundle that represents the given Bitmap.
|
||||
*
|
||||
* <p>The Bundle will contain a wrapped version of the Bitmaps HardwareBuffer, so will avoid
|
||||
* copies when passing across processes, only pass to processes you trust.
|
||||
*
|
||||
* <p>Returns a new Bundle rather than modifying an exiting one to avoid key collisions, the
|
||||
* returned Bundle should be treated as a standalone object.
|
||||
*
|
||||
* @param bitmap to convert to bundle
|
||||
* @return a Bundle representing the bitmap, should only be parsed by {@link
|
||||
* #bundleToHardwareBitmap(Bundle)}
|
||||
*/
|
||||
public static Bundle hardwareBitmapToBundle(Bitmap bitmap) {
|
||||
if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
|
||||
throw new IllegalArgumentException(
|
||||
"Passed bitmap must have hardware config, found: " + bitmap.getConfig());
|
||||
}
|
||||
// Bitmap assumes SRGB for null color space
|
||||
ParcelableColorSpace colorSpace =
|
||||
bitmap.getColorSpace() == null
|
||||
? new ParcelableColorSpace(ColorSpace.get(ColorSpace.Named.SRGB))
|
||||
: new ParcelableColorSpace(bitmap.getColorSpace());
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(KEY_BUFFER, bitmap.getHardwareBuffer());
|
||||
bundle.putParcelable(KEY_COLOR_SPACE, colorSpace);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the Bitmap added to a Bundle with {@link #hardwareBitmapToBundle(Bitmap)} .}
|
||||
*
|
||||
* <p>This Bitmap contains the HardwareBuffer from the original caller, be careful passing this
|
||||
* Bitmap on to any other source.
|
||||
*
|
||||
* @param bundle containing the bitmap
|
||||
* @return a hardware Bitmap
|
||||
*/
|
||||
public static Bitmap bundleToHardwareBitmap(Bundle bundle) {
|
||||
if (!bundle.containsKey(KEY_BUFFER) || !bundle.containsKey(KEY_COLOR_SPACE)) {
|
||||
throw new IllegalArgumentException("Bundle does not contain a hardware bitmap");
|
||||
}
|
||||
HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER);
|
||||
ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE);
|
||||
return Bitmap.wrapHardwareBuffer(
|
||||
Objects.requireNonNull(buffer), colorSpace.getColorSpace());
|
||||
}
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
package app.lawnchair.compatlib.eleven;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.view.AppTransitionAnimationSpec;
|
||||
import android.view.IRemoteAnimationFinishedCallback;
|
||||
import android.view.IRemoteAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.QuickstepCompatFactory;
|
||||
import app.lawnchair.compatlib.RemoteAnimationRunnerStub;
|
||||
|
||||
public class QuickstepCompatFactoryVR extends QuickstepCompatFactory {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVR();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteAnimationRunner.Stub wrapRemoteAnimationRunnerStub(RemoteAnimationRunnerStub compatStub) {
|
||||
return new IRemoteAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
final IRemoteAnimationFinishedCallback finishedCallback) {
|
||||
compatStub.onAnimationStart(0 /* transit */, apps, wallpapers, null, finishedCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
compatStub.onAnimationCancelled();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppTransitionAnimationSpec createAppTransitionAnimationSpec(int taskId, Bitmap buffer, Rect rect) {
|
||||
return new AppTransitionAnimationSpec(taskId,
|
||||
buffer != null ? buffer.createGraphicBufferHandle() : null, rect);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package app.lawnchair.compatlib.twelve;
|
||||
|
||||
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.IRecentsAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerStub;
|
||||
|
||||
public class ActivityManagerCompatVS extends ActivityManagerCompat {
|
||||
|
||||
private final ActivityTaskManager mAtm = ActivityTaskManager.getInstance();
|
||||
|
||||
@Override
|
||||
public void startRecentsActivity(Intent intent, long eventTime, RecentsAnimationRunnerStub runner) throws RemoteException {
|
||||
IRecentsAnimationRunner wrappedRunner = null;
|
||||
if (runner != null) {
|
||||
wrappedRunner = new IRecentsAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds) {
|
||||
runner.onAnimationStart(controller, apps, wallpapers, homeContentInsets, minimizedHomeBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(TaskSnapshot taskSnapshot) {
|
||||
runner.onAnimationCanceled(taskSnapshot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
runner.onTaskAppeared(app);
|
||||
}
|
||||
};
|
||||
}
|
||||
getService().startRecentsActivity(intent, eventTime, wrappedRunner);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
|
||||
// Note: The set of running tasks from the system is ordered by recency
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
mAtm.getTasks(1, filterOnlyVisibleRecents);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
return mAtm.getRecentTasks(numTasks, RECENT_IGNORE_UNAVAILABLE, userId);
|
||||
}
|
||||
}
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
package app.lawnchair.compatlib.twelve;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.view.AppTransitionAnimationSpec;
|
||||
import android.view.IRemoteAnimationFinishedCallback;
|
||||
import android.view.IRemoteAnimationRunner;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.IRemoteTransitionFinishedCallback;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat;
|
||||
import app.lawnchair.compatlib.QuickstepCompatFactory;
|
||||
import app.lawnchair.compatlib.RemoteAnimationRunnerStub;
|
||||
import app.lawnchair.compatlib.RemoteTransitionStub;
|
||||
|
||||
public class QuickstepCompatFactoryVS extends QuickstepCompatFactory {
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ActivityManagerCompat getActivityManagerCompat() {
|
||||
return new ActivityManagerCompatVS();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRemoteAnimationRunner.Stub wrapRemoteAnimationRunnerStub(RemoteAnimationRunnerStub compatStub) {
|
||||
return new IRemoteAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(int transit,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
RemoteAnimationTarget[] nonApps,
|
||||
final IRemoteAnimationFinishedCallback finishedCallback) {
|
||||
compatStub.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancelled() {
|
||||
compatStub.onAnimationCancelled();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppTransitionAnimationSpec createAppTransitionAnimationSpec(int taskId, Bitmap buffer, Rect rect) {
|
||||
return new AppTransitionAnimationSpec(taskId,
|
||||
buffer != null ? buffer.getHardwareBuffer() : null, rect);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="taskbar_size">60dp</dimen>
|
||||
</resources>
|
||||
@@ -21,9 +21,12 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentSender
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.view.Display
|
||||
import android.view.View
|
||||
import android.view.ViewTreeObserver
|
||||
import androidx.activity.OnBackPressedDispatcher
|
||||
import androidx.activity.OnBackPressedDispatcherOwner
|
||||
@@ -46,6 +49,7 @@ import androidx.savedstate.SavedStateRegistry
|
||||
import androidx.savedstate.SavedStateRegistryController
|
||||
import androidx.savedstate.SavedStateRegistryOwner
|
||||
import app.lawnchair.LawnchairApp.Companion.showQuickstepWarningIfNecessary
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat
|
||||
import app.lawnchair.factory.LawnchairWidgetHolder
|
||||
import app.lawnchair.gestures.GestureController
|
||||
import app.lawnchair.gestures.VerticalSwipeTouchController
|
||||
@@ -61,11 +65,13 @@ import app.lawnchair.util.getThemedIconPacksInstalled
|
||||
import app.lawnchair.util.unsafeLazy
|
||||
import com.android.launcher3.AbstractFloatingView
|
||||
import com.android.launcher3.BaseActivity
|
||||
import com.android.launcher3.BubbleTextView
|
||||
import com.android.launcher3.GestureNavContract
|
||||
import com.android.launcher3.LauncherAppState
|
||||
import com.android.launcher3.LauncherState
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import com.android.launcher3.model.data.ItemInfo
|
||||
import com.android.launcher3.popup.SystemShortcut
|
||||
import com.android.launcher3.statemanager.StateManager
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher
|
||||
@@ -342,9 +348,9 @@ class LawnchairLauncher :
|
||||
|
||||
override fun makeDefaultActivityOptions(splashScreenStyle: Int): ActivityOptionsWrapper {
|
||||
val callbacks = RunnableList()
|
||||
val options = if (Utilities.ATLEAST_P || Utilities.ATLEAST_Q) {
|
||||
val options = if (!Utilities.ATLEAST_R) {
|
||||
ActivityOptions.makeBasic()
|
||||
} else {
|
||||
} else if (Utilities.ATLEAST_T) {
|
||||
ActivityOptions.makeCustomAnimation(
|
||||
this,
|
||||
0,
|
||||
@@ -353,6 +359,9 @@ class LawnchairLauncher :
|
||||
Executors.MAIN_EXECUTOR.handler,
|
||||
null,
|
||||
) { _ -> callbacks.executeAllAndDestroy() }
|
||||
} else {
|
||||
LawnchairQuickstepCompat.activityOptionsCompat
|
||||
.makeCustomAnimation(this, 0, 0, null, Executors.MAIN_EXECUTOR.handler)
|
||||
}
|
||||
if (Utilities.ATLEAST_T) {
|
||||
options.setSplashScreenStyle(splashScreenStyle)
|
||||
@@ -362,6 +371,46 @@ class LawnchairLauncher :
|
||||
return ActivityOptionsWrapper(options, callbacks)
|
||||
}
|
||||
|
||||
override fun getActivityLaunchOptions(v: View?, item: ItemInfo?): ActivityOptionsWrapper {
|
||||
return runCatching {
|
||||
super.getActivityLaunchOptions(v, item)
|
||||
}.getOrElse {
|
||||
getActivityLaunchOptionsDefault(v, item)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getActivityLaunchOptionsDefault(v: View?, item: ItemInfo?): ActivityOptionsWrapper {
|
||||
var left = 0
|
||||
var top = 0
|
||||
var width = v!!.measuredWidth
|
||||
var height = v.measuredHeight
|
||||
if (v is BubbleTextView) {
|
||||
// Launch from center of icon, not entire view
|
||||
val icon: Drawable? = v.icon
|
||||
if (icon != null) {
|
||||
val bounds = icon.bounds
|
||||
left = (width - bounds.width()) / 2
|
||||
top = v.getPaddingTop()
|
||||
width = bounds.width()
|
||||
height = bounds.height()
|
||||
}
|
||||
}
|
||||
val options = Utilities.allowBGLaunch(
|
||||
ActivityOptions.makeClipRevealAnimation(
|
||||
v,
|
||||
left,
|
||||
top,
|
||||
width,
|
||||
height,
|
||||
),
|
||||
)
|
||||
options.setLaunchDisplayId(
|
||||
if (v != null && v.display != null) v.display.displayId else Display.DEFAULT_DISPLAY,
|
||||
)
|
||||
val callback = RunnableList()
|
||||
return ActivityOptionsWrapper(options, callback)
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START)
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.text.style.ForegroundColorSpan
|
||||
import android.util.AttributeSet
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.View.OnFocusChangeListener
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageButton
|
||||
@@ -33,7 +34,6 @@ import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView
|
||||
import com.android.launcher3.allapps.AllAppsStore
|
||||
import com.android.launcher3.allapps.AlphabeticalAppsList
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem
|
||||
import com.android.launcher3.allapps.SearchUiManager
|
||||
import com.android.launcher3.allapps.search.AllAppsSearchBarController
|
||||
@@ -64,7 +64,7 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
|
||||
Selection.setSelection(this, 0)
|
||||
}
|
||||
|
||||
private lateinit var apps: AlphabeticalAppsList<*>
|
||||
private lateinit var apps: LawnchairAlphabeticalAppsList<*>
|
||||
private lateinit var appsView: ActivityAllAppsContainerView<*>
|
||||
|
||||
private var focusedResultTitle = ""
|
||||
@@ -192,7 +192,7 @@ class AllAppsSearchInput(context: Context, attrs: AttributeSet?) :
|
||||
}
|
||||
|
||||
override fun initializeSearch(appsView: ActivityAllAppsContainerView<*>) {
|
||||
apps = appsView.searchResultList
|
||||
apps = appsView.searchResultList as LawnchairAlphabeticalAppsList<*>
|
||||
this.appsView = appsView
|
||||
searchBarController.initialize(
|
||||
LawnchairSearchAlgorithm.create(context),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package app.lawnchair.allapps
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import app.lawnchair.launcher
|
||||
import app.lawnchair.preferences2.PreferenceManager2
|
||||
@@ -21,12 +22,16 @@ class LawnchairAlphabeticalAppsList<T>(
|
||||
where T : Context, T : ActivityContext {
|
||||
|
||||
private var hiddenApps: Set<String> = setOf()
|
||||
private val prefs = PreferenceManager2.getInstance(context)
|
||||
|
||||
init {
|
||||
val prefs = PreferenceManager2.getInstance(context)
|
||||
prefs.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
|
||||
hiddenApps = it
|
||||
onAppsUpdated()
|
||||
try {
|
||||
prefs.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
|
||||
hiddenApps = it
|
||||
onAppsUpdated()
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
Log.w(TAG, "Failed initialize ignore: ", t)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package app.lawnchair.overview
|
||||
|
||||
import android.app.ActivityOptions
|
||||
import android.graphics.Color
|
||||
import android.graphics.Rect
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.RemoteException
|
||||
import android.util.Log
|
||||
import android.view.Display
|
||||
import android.view.View
|
||||
import android.view.WindowManagerGlobal
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat
|
||||
import app.lawnchair.compatlib.eleven.WindowManagerCompatVR
|
||||
import com.android.launcher3.BaseDraggingActivity
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.logging.StatsLogManager.LauncherEvent
|
||||
import com.android.launcher3.popup.SystemShortcut
|
||||
import com.android.quickstep.TaskShortcutFactory
|
||||
import com.android.quickstep.views.RecentsView
|
||||
import com.android.quickstep.views.TaskThumbnailView
|
||||
import com.android.quickstep.views.TaskView
|
||||
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
|
||||
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
|
||||
|
||||
object TaskShortcutFactory {
|
||||
|
||||
class LegacySplitSystemShortcut(
|
||||
iconRes: Int,
|
||||
textRes: Int,
|
||||
activity: BaseDraggingActivity,
|
||||
taskContainer: TaskIdAttributeContainer,
|
||||
private val mLauncherEvent: LauncherEvent,
|
||||
) : SystemShortcut<BaseDraggingActivity?>(
|
||||
iconRes,
|
||||
textRes,
|
||||
activity,
|
||||
taskContainer.itemInfo,
|
||||
taskContainer.taskView,
|
||||
) {
|
||||
private val mHandler: Handler = Handler(Looper.getMainLooper())
|
||||
private val mRecentsView: RecentsView<*, *> = activity.getOverviewPanel()
|
||||
private val mThumbnailView: TaskThumbnailView = taskContainer.thumbnailView
|
||||
private val mTaskView: TaskView = taskContainer.taskView
|
||||
|
||||
private fun makeLaunchOptions(activity: BaseDraggingActivity): ActivityOptions? {
|
||||
val navBarPosition: Int = WindowManagerCompatVR.getNavBarPosition(activity.displayId)
|
||||
if (navBarPosition == WindowManagerCompatVR.NAV_BAR_POS_INVALID) {
|
||||
return null
|
||||
}
|
||||
val options = ActivityOptions.makeBasic()
|
||||
options.launchWindowingMode = WindowManagerCompatVR.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|
||||
return options
|
||||
}
|
||||
|
||||
override fun onClick(view: View) {
|
||||
val taskKey = mTaskView.task!!.key
|
||||
val taskId = taskKey.id
|
||||
dismissTaskMenuView(mTarget)
|
||||
val options = makeLaunchOptions(mTarget!!)
|
||||
if (options != null && ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId, options)) {
|
||||
val animStartedListener =
|
||||
Runnable { mRecentsView.dismissTask(mTaskView, false, false) }
|
||||
val position = IntArray(2)
|
||||
mThumbnailView.getLocationOnScreen(position)
|
||||
val width = (mThumbnailView.width * mTaskView.scaleX).toInt()
|
||||
val height = (mThumbnailView.height * mTaskView.scaleY).toInt()
|
||||
val taskBounds = Rect(
|
||||
position[0],
|
||||
position[1],
|
||||
position[0] + width,
|
||||
position[1] + height,
|
||||
)
|
||||
|
||||
// Take the thumbnail of the task without a scrim and apply it back after
|
||||
val alpha = mThumbnailView.dimAlpha
|
||||
mThumbnailView.dimAlpha = 0f
|
||||
val thumbnail = RecentsTransition.drawViewIntoHardwareBitmap(
|
||||
taskBounds.width(),
|
||||
taskBounds.height(),
|
||||
mThumbnailView,
|
||||
1f,
|
||||
Color.BLACK,
|
||||
)
|
||||
mThumbnailView.dimAlpha = alpha
|
||||
val future: AppTransitionAnimationSpecsFuture = object : AppTransitionAnimationSpecsFuture(mHandler) {
|
||||
override fun composeSpecs(): List<AppTransitionAnimationSpecCompat> {
|
||||
return listOf(
|
||||
AppTransitionAnimationSpecCompat(
|
||||
taskId,
|
||||
thumbnail,
|
||||
taskBounds,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
try {
|
||||
WindowManagerGlobal.getWindowManagerService()
|
||||
.overridePendingAppTransitionMultiThumbFuture(
|
||||
future.future,
|
||||
RecentsTransition.wrapStartedListener(
|
||||
mHandler,
|
||||
animStartedListener,
|
||||
),
|
||||
true,
|
||||
taskKey.displayId,
|
||||
)
|
||||
} catch (e: RemoteException) {
|
||||
Log.w("TAG", "Failed to override pending app transition (multi-thumbnail future): ", e)
|
||||
}
|
||||
mTarget.statsLogManager.logger().withItemInfo(mTaskView.itemInfo).log(mLauncherEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
var legacySplit: TaskShortcutFactory = object : TaskShortcutFactory {
|
||||
|
||||
override fun getShortcuts(
|
||||
activity: BaseDraggingActivity,
|
||||
taskContainer: TaskIdAttributeContainer,
|
||||
): List<SystemShortcut<*>>? {
|
||||
val task = taskContainer.task
|
||||
if (!task.isDockable) {
|
||||
return null
|
||||
}
|
||||
return if (isAvailable(activity, task.key.displayId)) {
|
||||
listOf(
|
||||
LegacySplitSystemShortcut(
|
||||
R.drawable.ic_split_vertical,
|
||||
R.string.recent_task_option_split_screen,
|
||||
activity,
|
||||
taskContainer,
|
||||
LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
private fun isAvailable(activity: BaseDraggingActivity, displayId: Int): Boolean {
|
||||
return if (LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
false
|
||||
} else {
|
||||
(
|
||||
!activity.deviceProfile.isMultiWindowMode &&
|
||||
(displayId == -1 || displayId == Display.DEFAULT_DISPLAY)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import androidx.core.os.bundleOf
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat
|
||||
import app.lawnchair.preferences.PreferenceChangeListener
|
||||
import app.lawnchair.preferences.PreferenceManager
|
||||
import app.lawnchair.util.requireSystemService
|
||||
@@ -66,6 +67,7 @@ class LawnchairDeviceSearchAlgorithm(context: Context) :
|
||||
}
|
||||
|
||||
private fun createSearchSession() {
|
||||
if (LawnchairQuickstepCompat.ATLEAST_U) return
|
||||
Executors.UI_HELPER_EXECUTOR.execute {
|
||||
searchSession?.destroy()
|
||||
val idp = LauncherAppState.getIDP(context)
|
||||
@@ -122,6 +124,7 @@ class LawnchairDeviceSearchAlgorithm(context: Context) :
|
||||
|
||||
companion object {
|
||||
fun checkSearchCompatibility(context: Context) {
|
||||
if (LawnchairQuickstepCompat.ATLEAST_U) return
|
||||
Executors.UI_HELPER_EXECUTOR.execute {
|
||||
val searchContext = SearchContext(1 or 2, 200, Bundle())
|
||||
val searchManager = context.requireSystemService<SearchUiManager>()
|
||||
|
||||
@@ -8,12 +8,13 @@ import android.view.WindowManager
|
||||
import androidx.annotation.Keep
|
||||
import app.lawnchair.LawnchairApp
|
||||
import com.android.internal.policy.SystemBarUtils
|
||||
import com.android.launcher3.Utilities
|
||||
import com.android.launcher3.util.WindowBounds
|
||||
import com.android.launcher3.util.window.CachedDisplayInfo
|
||||
import com.android.launcher3.util.window.WindowManagerProxy
|
||||
|
||||
@Keep
|
||||
class LawnchairWindowManagerProxy(context: Context) : WindowManagerProxy(true) {
|
||||
class LawnchairWindowManagerProxy(context: Context) : WindowManagerProxy(Utilities.ATLEAST_T) {
|
||||
|
||||
override fun getRotation(displayInfoContext: Context): Int {
|
||||
if (LawnchairApp.isAtleastT) {
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.wm.shell.util;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Simple container for recent tasks. May contain either a single or pair of tasks.
|
||||
*/
|
||||
public class GroupedRecentTaskInfo implements Parcelable {
|
||||
|
||||
public static final int TYPE_SINGLE = 1;
|
||||
public static final int TYPE_SPLIT = 2;
|
||||
public static final int TYPE_FREEFORM = 3;
|
||||
|
||||
@IntDef(prefix = {"TYPE_"}, value = {
|
||||
TYPE_SINGLE ,
|
||||
TYPE_SPLIT ,
|
||||
TYPE_FREEFORM
|
||||
})
|
||||
public @interface GroupType {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private final ActivityManager.RecentTaskInfo[] mTasks;
|
||||
@Nullable
|
||||
private final SplitBounds mSplitBounds;
|
||||
@GroupType
|
||||
private final int mType;
|
||||
|
||||
/**
|
||||
* Create new for a single task
|
||||
*/
|
||||
|
||||
public static GroupedRecentTaskInfo forSingleTask(
|
||||
@NonNull ActivityManager.RecentTaskInfo task) {
|
||||
return new GroupedRecentTaskInfo (new ActivityManager.RecentTaskInfo[]{task} , null ,
|
||||
TYPE_SINGLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new for a pair of tasks in split screen
|
||||
*/
|
||||
public static GroupedRecentTaskInfo forSplitTasks(@NonNull ActivityManager.RecentTaskInfo task1 ,
|
||||
@NonNull ActivityManager.RecentTaskInfo task2 , @Nullable SplitBounds splitBounds) {
|
||||
return new GroupedRecentTaskInfo (new ActivityManager.RecentTaskInfo[]{task1 , task2} ,
|
||||
splitBounds , TYPE_SPLIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new for a group of freeform tasks
|
||||
*/
|
||||
public static GroupedRecentTaskInfo forFreeformTasks(
|
||||
@NonNull ActivityManager.RecentTaskInfo... tasks) {
|
||||
return new GroupedRecentTaskInfo (tasks , null , TYPE_FREEFORM);
|
||||
}
|
||||
|
||||
private GroupedRecentTaskInfo(@NonNull ActivityManager.RecentTaskInfo[] tasks ,
|
||||
@Nullable SplitBounds splitBounds , @GroupType int type) {
|
||||
mTasks = tasks;
|
||||
mSplitBounds = splitBounds;
|
||||
mType = type;
|
||||
}
|
||||
|
||||
GroupedRecentTaskInfo(Parcel parcel) {
|
||||
mTasks = parcel.createTypedArray(ActivityManager.RecentTaskInfo.CREATOR);
|
||||
mSplitBounds = parcel.readTypedObject(SplitBounds.CREATOR);
|
||||
mType = parcel.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get primary {@link ActivityManager.RecentTaskInfo}
|
||||
*/
|
||||
@NonNull
|
||||
public ActivityManager.RecentTaskInfo getTaskInfo1() {
|
||||
return mTasks[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get secondary {@link ActivityManager.RecentTaskInfo}.
|
||||
* <p>
|
||||
* Used in split screen.
|
||||
*/
|
||||
@Nullable
|
||||
public ActivityManager.RecentTaskInfo getTaskInfo2() {
|
||||
if (mTasks.length > 1) {
|
||||
return mTasks[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all {@link ActivityManager.RecentTaskInfo}s grouped together.
|
||||
*/
|
||||
@NonNull
|
||||
public List<ActivityManager.RecentTaskInfo> getTaskInfoList() {
|
||||
return Arrays.asList (mTasks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return {@link SplitBounds} if this is a split screen entry or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
public SplitBounds getSplitBounds() {
|
||||
return mSplitBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get type of this recents entry. One of {@link GroupType}
|
||||
*/
|
||||
@GroupType
|
||||
public int getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder taskString = new StringBuilder ( );
|
||||
for (int i = 0; i < mTasks.length; i++) {
|
||||
if (i == 0) {
|
||||
taskString.append ("Task");
|
||||
} else {
|
||||
taskString.append (", Task");
|
||||
}
|
||||
taskString.append (i + 1).append (": ").append (getTaskInfo (mTasks[i]));
|
||||
}
|
||||
if (mSplitBounds != null) {
|
||||
taskString.append (", SplitBounds: ").append (mSplitBounds);
|
||||
}
|
||||
taskString.append (", Type=");
|
||||
switch (mType) {
|
||||
case TYPE_SINGLE:
|
||||
taskString.append ("TYPE_SINGLE");
|
||||
break;
|
||||
case TYPE_SPLIT:
|
||||
taskString.append ("TYPE_SPLIT");
|
||||
break;
|
||||
case TYPE_FREEFORM:
|
||||
taskString.append ("TYPE_FREEFORM");
|
||||
break;
|
||||
}
|
||||
return taskString.toString();
|
||||
}
|
||||
|
||||
private String getTaskInfo(ActivityManager.RecentTaskInfo taskInfo) {
|
||||
if (taskInfo == null) {
|
||||
return null;
|
||||
}
|
||||
return "id=" + taskInfo.taskId
|
||||
+ " baseIntent=" + (taskInfo.baseIntent != null
|
||||
? taskInfo.baseIntent.getComponent ( )
|
||||
: "null")
|
||||
+ " winMode=" + WindowConfiguration.windowingModeToString (
|
||||
taskInfo.getWindowingMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel , int flags) {
|
||||
parcel.writeTypedArray(mTasks , flags);
|
||||
parcel.writeTypedObject(mSplitBounds , flags);
|
||||
parcel.writeInt(mType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Creator<GroupedRecentTaskInfo> CREATOR =
|
||||
new Creator<GroupedRecentTaskInfo> ( ) {
|
||||
public GroupedRecentTaskInfo createFromParcel(Parcel source) {
|
||||
return new GroupedRecentTaskInfo(source);
|
||||
}
|
||||
|
||||
public GroupedRecentTaskInfo[] newArray(int size) {
|
||||
return new GroupedRecentTaskInfo[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
Submodule platform_frameworks_libs_systemui updated: 02aee0e36d...5f57efed9a.
Binary file not shown.
Binary file not shown.
@@ -127,6 +127,10 @@ public class LauncherAnimationRunner extends RemoteAnimationRunnerCompat {
|
||||
});
|
||||
}
|
||||
|
||||
public void onAnimationCancelled(boolean isKeyguardOccluded) {
|
||||
onAnimationCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by RemoteAnimationFactory implementations to run the actual animation and its lifecycle
|
||||
* callbacks.
|
||||
@@ -196,13 +200,19 @@ public class LauncherAnimationRunner extends RemoteAnimationRunnerCompat {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.TIRAMISU) {
|
||||
mAnimator.start();
|
||||
}
|
||||
|
||||
if (skipFirstFrame) {
|
||||
// Because t=0 has the app icon in its original spot, we can skip the
|
||||
// first frame and have the same movement one frame earlier.
|
||||
mAnimator.setCurrentPlayTime(
|
||||
Math.min(getSingleFrameMs(context), mAnimator.getTotalDuration()));
|
||||
}
|
||||
mAnimator.start();
|
||||
if (Utilities.ATLEAST_U) {
|
||||
mAnimator.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +244,11 @@ public class LauncherAnimationRunner extends RemoteAnimationRunnerCompat {
|
||||
RemoteAnimationTarget[] nonAppTargets,
|
||||
LauncherAnimationRunner.AnimationResult result);
|
||||
|
||||
@UiThread
|
||||
default void onAnimationCancelled(boolean isKeyguardOccluded) {
|
||||
onAnimationCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the animation is cancelled. This can happen with or without
|
||||
* the create being called.
|
||||
|
||||
@@ -164,6 +164,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import app.lawnchair.LawnchairApp;
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
import app.lawnchair.icons.shape.IconShapeManager;
|
||||
import app.lawnchair.theme.color.ColorTokens;
|
||||
|
||||
@@ -282,9 +283,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
};
|
||||
|
||||
mStartingWindowListener.setTransitionManager(this);
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
|
||||
mStartingWindowListener);
|
||||
if (Utilities.ATLEAST_T) {
|
||||
mStartingWindowListener.setTransitionManager(this);
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(
|
||||
mStartingWindowListener);
|
||||
}
|
||||
}
|
||||
|
||||
mOpeningXInterpolator = AnimationUtils.loadInterpolator(context, R.interpolator.app_open_x);
|
||||
@@ -333,10 +336,12 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
long statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION
|
||||
- STATUS_BAR_TRANSITION_PRE_DELAY;
|
||||
ActivityOptions options = ActivityOptions.makeRemoteAnimation(
|
||||
ActivityOptions options = LawnchairQuickstepCompat.getActivityOptionsCompat().makeRemoteAnimation(
|
||||
new RemoteAnimationAdapter(runner, duration, statusBarTransitionDelay),
|
||||
new RemoteTransition(runner.toRemoteTransition(),
|
||||
mLauncher.getIApplicationThread(), "QuickstepLaunch"));
|
||||
LawnchairQuickstepCompat.getRemoteTransitionCompat().getRemoteTransition(runner.toRemoteTransition(),
|
||||
mLauncher.getIApplicationThread(), "QuickstepLaunch"),
|
||||
"Lawnchair");
|
||||
|
||||
return new ActivityOptionsWrapper(options, onEndCallback);
|
||||
}
|
||||
|
||||
@@ -457,7 +462,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
if (target == null)
|
||||
return new Rect(0, 0, mDeviceProfile.widthPx, mDeviceProfile.heightPx);
|
||||
final Rect bounds = new Rect(target.screenSpaceBounds);
|
||||
if (target.localBounds != null) {
|
||||
if (Utilities.ATLEAST_R && target.localBounds != null) {
|
||||
bounds.set(target.localBounds);
|
||||
} else {
|
||||
bounds.offsetTo(target.position.x, target.position.y);
|
||||
@@ -864,7 +869,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
} else {
|
||||
tmpPos.set(target.position.x, target.position.y);
|
||||
}
|
||||
final Rect crop = new Rect(target.screenSpaceBounds);
|
||||
final Rect crop = new Rect(Utilities.ATLEAST_R ? target.screenSpaceBounds : target.sourceContainerBounds);
|
||||
crop.offsetTo(0, 0);
|
||||
|
||||
if ((rotationChange % 2) == 1) {
|
||||
@@ -1107,9 +1112,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
* Registers remote animations used when closing apps to home screen.
|
||||
*/
|
||||
public void registerRemoteAnimations() {
|
||||
if (SEPARATE_RECENTS_ACTIVITY.get()) {
|
||||
return;
|
||||
}
|
||||
if (SEPARATE_RECENTS_ACTIVITY.get() || !Utilities.ATLEAST_S) return;
|
||||
if (hasControlRemoteAppTransitionPermission()) {
|
||||
RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
|
||||
addRemoteAnimations(definition);
|
||||
@@ -1147,17 +1150,16 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
* Registers remote animations used when closing apps to home screen.
|
||||
*/
|
||||
public void registerRemoteTransitions() {
|
||||
if (ENABLE_SHELL_TRANSITIONS && Utilities.ATLEAST_U) {
|
||||
if (ENABLE_SHELL_TRANSITIONS && LawnchairQuickstepCompat.ATLEAST_U) {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).shareTransactionQueue();
|
||||
}
|
||||
if (SEPARATE_RECENTS_ACTIVITY.get()) {
|
||||
return;
|
||||
}
|
||||
if (!Utilities.ATLEAST_S)
|
||||
return;
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_T) return;
|
||||
if (hasControlRemoteAppTransitionPermission()) {
|
||||
mWallpaperOpenTransitionRunner = createWallpaperOpenRunner(false /* fromUnlock */);
|
||||
mLauncherOpenTransition = new RemoteTransition(
|
||||
mLauncherOpenTransition = LawnchairQuickstepCompat.getRemoteTransitionCompat().getRemoteTransition(
|
||||
new LauncherAnimationRunner(mHandler, mWallpaperOpenTransitionRunner,
|
||||
false /* startAtFrontOfQueue */).toRemoteTransition(),
|
||||
mLauncher.getIApplicationThread(), "QuickstepLaunchHome");
|
||||
@@ -1184,8 +1186,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
public void onActivityDestroyed() {
|
||||
unregisterRemoteAnimations();
|
||||
unregisterRemoteTransitions();
|
||||
mStartingWindowListener.setTransitionManager(null);
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
|
||||
if (Utilities.ATLEAST_T) {
|
||||
mStartingWindowListener.setTransitionManager(null);
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterRemoteAnimations() {
|
||||
@@ -1193,8 +1197,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
return;
|
||||
}
|
||||
if (hasControlRemoteAppTransitionPermission()) {
|
||||
mLauncher.unregisterRemoteAnimations();
|
||||
|
||||
if (Utilities.ATLEAST_R) {
|
||||
mLauncher.unregisterRemoteAnimations();
|
||||
}
|
||||
// Also clear strong references to the runners registered with the remote
|
||||
// animation
|
||||
// definition so we don't have to wait for the system gc
|
||||
@@ -1212,8 +1217,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
return;
|
||||
}
|
||||
if (hasControlRemoteAppTransitionPermission()) {
|
||||
if (mLauncherOpenTransition == null)
|
||||
return;
|
||||
if (mLauncherOpenTransition == null) return;
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).unregisterRemoteTransition(
|
||||
mLauncherOpenTransition);
|
||||
mLauncherOpenTransition = null;
|
||||
@@ -1227,6 +1231,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
|
||||
private boolean launcherIsATargetWithMode(RemoteAnimationTarget[] targets, int mode) {
|
||||
for (RemoteAnimationTarget target : targets) {
|
||||
if (!Utilities.ATLEAST_S) {
|
||||
return target.mode == mode && target.taskId == mLauncher.getTaskId();
|
||||
}
|
||||
if (target.mode == mode && target.taskInfo != null
|
||||
// Compare component name instead of task-id because transitions will promote
|
||||
// the target up to the root task while getTaskId returns the leaf.
|
||||
@@ -1277,7 +1284,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
RemoteAnimationTarget target = appTargets[i];
|
||||
transaction.forSurface(target.leash)
|
||||
.setAlpha(1f)
|
||||
.setWindowCrop(target.screenSpaceBounds)
|
||||
.setWindowCrop(Utilities.ATLEAST_R ? target.screenSpaceBounds : target.sourceContainerBounds)
|
||||
.setCornerRadius(cornerRadius);
|
||||
}
|
||||
surfaceApplier.scheduleApply(transaction);
|
||||
@@ -1304,6 +1311,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
* app targets
|
||||
*/
|
||||
private @Nullable View findLauncherView(RemoteAnimationTarget[] appTargets) {
|
||||
if (!Utilities.ATLEAST_S) return null;
|
||||
for (RemoteAnimationTarget appTarget : appTargets) {
|
||||
if (appTarget.mode == MODE_CLOSING) {
|
||||
View launcherView = findLauncherView(appTarget);
|
||||
@@ -2018,7 +2026,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
RemoteAnimationTarget target = mAppTargets[i];
|
||||
SurfaceProperties builder = transaction.forSurface(target.leash);
|
||||
|
||||
if (target.localBounds != null) {
|
||||
if (Utilities.ATLEAST_R && target.localBounds != null) {
|
||||
mTmpPos.set(target.localBounds.left, target.localBounds.top);
|
||||
} else {
|
||||
mTmpPos.set(target.position.x, target.position.y);
|
||||
|
||||
@@ -86,6 +86,7 @@ import java.util.Objects;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import app.lawnchair.LawnchairApp;
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Model delegate which loads prediction items
|
||||
@@ -259,8 +260,9 @@ public class QuickstepModelDelegate extends ModelDelegate {
|
||||
* atom.
|
||||
*/
|
||||
protected void registerSnapshotLoggingCallback() {
|
||||
if (mStatsManager == null) {
|
||||
if (mStatsManager == null || !LawnchairQuickstepCompat.ATLEAST_R) {
|
||||
Log.d(TAG, "Failed to get StatsManager");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -330,7 +332,7 @@ public class QuickstepModelDelegate extends ModelDelegate {
|
||||
super.destroy();
|
||||
mActive = false;
|
||||
StatsLogCompatManager.LOGS_CONSUMER.remove(mAppEventProducer);
|
||||
if (mIsPrimaryInstance) {
|
||||
if (mIsPrimaryInstance && LawnchairQuickstepCompat.ATLEAST_R) {
|
||||
mStatsManager.clearPullAtomCallback(SysUiStatsLog.LAUNCHER_LAYOUT_SNAPSHOT);
|
||||
}
|
||||
destroyPredictors();
|
||||
|
||||
@@ -41,6 +41,8 @@ import com.android.quickstep.util.BaseDepthController;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Controls blur and wallpaper zoom, for the Launcher surface only.
|
||||
*/
|
||||
@@ -77,7 +79,7 @@ public class DepthController extends BaseDepthController implements StateHandler
|
||||
mOnAttachListener = new View.OnAttachStateChangeListener() {
|
||||
@Override
|
||||
public void onViewAttachedToWindow(View view) {
|
||||
if (app.lawnchair.LawnchairApp.isAtleastT()) {
|
||||
if (LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
CrossWindowBlurListeners.getInstance().addListener(mLauncher.getMainExecutor(),
|
||||
mCrossWindowBlurListener);
|
||||
}
|
||||
@@ -114,7 +116,7 @@ public class DepthController extends BaseDepthController implements StateHandler
|
||||
}
|
||||
|
||||
private void removeSecondaryListeners() {
|
||||
if (mCrossWindowBlurListener != null) {
|
||||
if (mCrossWindowBlurListener != null && LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
CrossWindowBlurListeners.getInstance().removeListener(mCrossWindowBlurListener);
|
||||
}
|
||||
if (mOpaquenessListener != null) {
|
||||
|
||||
@@ -239,9 +239,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
WindowManagerGlobal.getWindowManagerService().clearTaskTransitionSpec();
|
||||
} else {
|
||||
// Adjust task transition spec to account for taskbar being visible
|
||||
WindowManagerGlobal.getWindowManagerService().setTaskTransitionSpec(
|
||||
new TaskTransitionSpec(
|
||||
mLauncher.getColor(R.color.taskbar_background)));
|
||||
if (Utilities.ATLEAST_U) {
|
||||
WindowManagerGlobal.getWindowManagerService().setTaskTransitionSpec(
|
||||
new TaskTransitionSpec(
|
||||
mLauncher.getColor(R.color.taskbar_background)));
|
||||
}
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
// This shouldn't happen but if it does task animations won't look good until the
|
||||
|
||||
@@ -645,7 +645,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
this, 0, 0, Color.TRANSPARENT,
|
||||
Executors.MAIN_EXECUTOR.getHandler(), null,
|
||||
elapsedRealTime -> callbacks.executeAllAndDestroy());
|
||||
options.setSplashScreenStyle(splashScreenStyle);
|
||||
if (Utilities.ATLEAST_T) {
|
||||
options.setSplashScreenStyle(splashScreenStyle);
|
||||
}
|
||||
Utilities.allowBGLaunch(options);
|
||||
return new ActivityOptionsWrapper(options, callbacks);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.app.viewcapture.SettingsAwareViewCapture;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
import com.android.launcher3.util.MultiPropertyFactory;
|
||||
@@ -131,14 +132,18 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
|
||||
mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
|
||||
.startCapture(getRootView(), ".Taskbar");
|
||||
if (Utilities.ATLEAST_U) {
|
||||
mViewCaptureCloseable = SettingsAwareViewCapture.getInstance(getContext())
|
||||
.startCapture(getRootView(), ".Taskbar");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
mViewCaptureCloseable.close();
|
||||
if (Utilities.ATLEAST_U) {
|
||||
mViewCaptureCloseable.close();
|
||||
}
|
||||
onDestroy(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,11 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
|
||||
onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
|
||||
|
||||
context.addOnDeviceProfileChangeListener(deviceProfileChangeListener)
|
||||
gestureNavSettingsObserver.registerForCallingUser()
|
||||
try {
|
||||
gestureNavSettingsObserver.registerForCallingUser()
|
||||
} catch (t: Throwable) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
@@ -161,19 +165,23 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
|
||||
private fun getProvidedInsets(insetsRoundedCornerFlag: Int): Array<InsetsFrameProvider> {
|
||||
val navBarsFlag =
|
||||
(if (context.isGestureNav) FLAG_SUPPRESS_SCRIM else 0) or insetsRoundedCornerFlag
|
||||
return arrayOf(
|
||||
try {
|
||||
return arrayOf(
|
||||
InsetsFrameProvider(insetsOwner, 0, navigationBars())
|
||||
.setFlags(
|
||||
navBarsFlag,
|
||||
FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER
|
||||
),
|
||||
.setFlags(
|
||||
navBarsFlag,
|
||||
FLAG_SUPPRESS_SCRIM or FLAG_INSETS_ROUNDED_CORNER
|
||||
),
|
||||
InsetsFrameProvider(insetsOwner, 0, tappableElement()),
|
||||
InsetsFrameProvider(insetsOwner, 0, mandatorySystemGestures()),
|
||||
InsetsFrameProvider(insetsOwner, INDEX_LEFT, systemGestures())
|
||||
.setSource(SOURCE_DISPLAY),
|
||||
.setSource(SOURCE_DISPLAY),
|
||||
InsetsFrameProvider(insetsOwner, INDEX_RIGHT, systemGestures())
|
||||
.setSource(SOURCE_DISPLAY)
|
||||
)
|
||||
.setSource(SOURCE_DISPLAY)
|
||||
)
|
||||
}catch (t: Throwable) {
|
||||
return emptyArray()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setProviderInsets(provider: InsetsFrameProvider, gravity: Int) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.taskbar;
|
||||
import static android.content.Context.RECEIVER_NOT_EXPORTED;
|
||||
import static android.content.pm.PackageManager.FEATURE_PC;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
|
||||
|
||||
import static com.android.launcher3.LauncherPrefs.TASKBAR_PINNING;
|
||||
@@ -54,6 +55,7 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.taskbar.unfold.NonDestroyableScopedUnfoldTransitionProgressProvider;
|
||||
@@ -72,6 +74,8 @@ import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Class to manage taskbar lifecycle
|
||||
*/
|
||||
@@ -207,8 +211,16 @@ public class TaskbarManager {
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
public TaskbarManager(TouchInteractionService service) {
|
||||
Display display = service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
|
||||
mContext = service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null);
|
||||
Display display =
|
||||
service.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY);
|
||||
mContext = (LawnchairQuickstepCompat.ATLEAST_T) ?
|
||||
service.createWindowContext(display, TYPE_NAVIGATION_BAR_PANEL, null) :
|
||||
(LawnchairQuickstepCompat.ATLEAST_S) ?
|
||||
service.createWindowContext(display, TYPE_APPLICATION_OVERLAY, null) :
|
||||
(LawnchairQuickstepCompat.ATLEAST_R) ?
|
||||
service.createWindowContext(TYPE_APPLICATION_OVERLAY, null) :
|
||||
service;
|
||||
|
||||
mNavButtonController = new TaskbarNavButtonController(service,
|
||||
SystemUiProxy.INSTANCE.get(mContext), new Handler(),
|
||||
AssistUtils.newInstance(mContext));
|
||||
@@ -217,8 +229,10 @@ public class TaskbarManager {
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
Trace.instantForTrack(Trace.TRACE_TAG_APP, "TaskbarManager",
|
||||
"onConfigurationChanged: " + newConfig);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
Trace.instantForTrack(Trace.TRACE_TAG_APP, "TaskbarManager",
|
||||
"onConfigurationChanged: " + newConfig);
|
||||
}
|
||||
debugWhyTaskbarNotDestroyed(
|
||||
"TaskbarManager#mComponentCallbacks.onConfigurationChanged: " + newConfig);
|
||||
DeviceProfile dp = mUserUnlocked
|
||||
|
||||
@@ -96,7 +96,9 @@ public class QuickstepInteractionHandler implements RemoteViews.InteractionHandl
|
||||
// Do nothing.
|
||||
}
|
||||
activityOptions.options.setPendingIntentLaunchFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
|
||||
if (Utilities.ATLEAST_T) {
|
||||
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
|
||||
}
|
||||
Utilities.allowBGLaunch(activityOptions.options);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.android.launcher3.uioverrides;
|
||||
|
||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
||||
import static android.os.Trace.TRACE_TAG_APP;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
|
||||
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
|
||||
|
||||
@@ -67,11 +66,9 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.media.permission.SafeCloseable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.Trace;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
@@ -86,7 +83,7 @@ import android.window.SplashScreen;
|
||||
import androidx.annotation.BinderThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.android.app.viewcapture.SettingsAwareViewCapture;
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
@@ -186,6 +183,8 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
public class QuickstepLauncher extends Launcher {
|
||||
private static final boolean TRACE_LAYOUTS = SystemProperties.getBoolean("persist.debug.trace_layouts", false);
|
||||
private static final String TRACE_RELAYOUT_CLASS = SystemProperties.get("persist.debug.trace_request_layout_class",
|
||||
@@ -1020,24 +1019,24 @@ public class QuickstepLauncher extends Launcher {
|
||||
ActivityOptionsWrapper activityOptions = mAppTransitionManager.hasControlRemoteAppTransitionPermission()
|
||||
? mAppTransitionManager.getActivityLaunchOptions(v)
|
||||
: super.getActivityLaunchOptions(v, item);
|
||||
if (mLastTouchUpTime > 0 && app.lawnchair.LawnchairApp.isAtleastT()) {
|
||||
if (mLastTouchUpTime > 0 && LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
activityOptions.options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER,
|
||||
mLastTouchUpTime);
|
||||
}
|
||||
if (item != null && (item.animationType == DEFAULT_NO_ICON
|
||||
|| item.animationType == VIEW_BACKGROUND) && app.lawnchair.LawnchairApp.isAtleastT()) {
|
||||
|| item.animationType == VIEW_BACKGROUND) && LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
activityOptions.options.setSplashScreenStyle(
|
||||
SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
|
||||
} else {
|
||||
if (app.lawnchair.LawnchairApp.isAtleastT()) {
|
||||
if (LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
|
||||
}
|
||||
}
|
||||
activityOptions.options.setLaunchDisplayId(
|
||||
(v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
|
||||
: Display.DEFAULT_DISPLAY);
|
||||
if (app.lawnchair.LawnchairApp.isAtleastT()) {
|
||||
Utilities.allowBGLaunch(activityOptions.options);
|
||||
Utilities.allowBGLaunch(activityOptions.options);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
addLaunchCookie(item, activityOptions.options);
|
||||
}
|
||||
return activityOptions;
|
||||
@@ -1046,11 +1045,13 @@ public class QuickstepLauncher extends Launcher {
|
||||
@Override
|
||||
public ActivityOptionsWrapper makeDefaultActivityOptions(int splashScreenStyle) {
|
||||
RunnableList callbacks = new RunnableList();
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(
|
||||
ActivityOptions options = LawnchairQuickstepCompat.ATLEAST_R ? ActivityOptions.makeCustomAnimation(
|
||||
this, 0, 0, Color.TRANSPARENT,
|
||||
Executors.MAIN_EXECUTOR.getHandler(), null,
|
||||
elapsedRealTime -> callbacks.executeAllAndDestroy());
|
||||
options.setSplashScreenStyle(splashScreenStyle);
|
||||
elapsedRealTime -> callbacks.executeAllAndDestroy()) : ActivityOptions.makeBasic();
|
||||
if (LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
options.setSplashScreenStyle(splashScreenStyle);
|
||||
}
|
||||
Utilities.allowBGLaunch(options);
|
||||
return new ActivityOptionsWrapper(options, callbacks);
|
||||
}
|
||||
|
||||
@@ -101,15 +101,12 @@ import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
|
||||
import com.android.launcher3.statehandlers.DesktopVisibilityController;
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.taskbar.TaskbarThresholdUtils;
|
||||
import com.android.launcher3.taskbar.TaskbarUIController;
|
||||
import com.android.launcher3.tracing.InputConsumerProto;
|
||||
import com.android.launcher3.tracing.SwipeHandlerProto;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.util.ActivityLifecycleCallbacksAdapter;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
@@ -157,6 +154,7 @@ import java.util.Optional;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
import app.lawnchair.util.CompatibilityKt;
|
||||
|
||||
/**
|
||||
@@ -672,15 +670,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
runningTasks = cachedTaskInfo.getPlaceholderTasks();
|
||||
}
|
||||
|
||||
// Safeguard against any null tasks being sent to recents view, happens when
|
||||
// quickswitching
|
||||
// very quickly w/ split tasks because TopTaskTracker provides stale information
|
||||
// compared to
|
||||
// actual running tasks in the recents animation.
|
||||
// TODO(b/236226779), Proper fix (ag/22237143)
|
||||
if (Arrays.stream(runningTasks).anyMatch(Objects::isNull)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Safeguard against any null tasks being sent to recents view, happens when
|
||||
// quickswitching
|
||||
@@ -702,8 +691,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
buildAnimationController();
|
||||
|
||||
try (SafeCloseable c = TraceHelper.INSTANCE.allowIpcs("logToggleRecents")) {
|
||||
LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
|
||||
(int) (mLauncherFrameDrawnTime - mTouchTimeMs));
|
||||
if (Utilities.ATLEAST_S) {
|
||||
LatencyTracker.getInstance(mContext).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
|
||||
(int) (mLauncherFrameDrawnTime - mTouchTimeMs));
|
||||
}
|
||||
}
|
||||
|
||||
// This method is only called when STATE_GESTURE_STARTED is set, so we can
|
||||
@@ -713,8 +704,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
RecentsModel.INSTANCE.get(mContext).getThumbnailCache()
|
||||
.getHighResLoadingState().setVisible(true);
|
||||
|
||||
DepthController depthController = mActivityInterface.getDepthController();
|
||||
|
||||
}
|
||||
|
||||
public MotionPauseDetector.OnMotionPauseListener getMotionPauseListener() {
|
||||
@@ -1561,7 +1550,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
? mRecentsAnimationTargets
|
||||
.findTask(mGestureState.getTopRunningTaskId())
|
||||
: null;
|
||||
final ArrayList<IBinder> cookies = runningTaskTarget != null
|
||||
final ArrayList<IBinder> cookies = Utilities.ATLEAST_S && runningTaskTarget != null
|
||||
&& runningTaskTarget.taskInfo != null
|
||||
? runningTaskTarget.taskInfo.launchCookies
|
||||
: new ArrayList<>();
|
||||
@@ -1571,6 +1560,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
&& runningTaskTarget.leash.isValid();
|
||||
boolean appCanEnterPip = !mDeviceState.isPipActive()
|
||||
&& hasValidLeash
|
||||
&& Utilities.ATLEAST_T
|
||||
&& runningTaskTarget.allowEnterPip
|
||||
&& runningTaskTarget.taskInfo.pictureInPictureParams != null
|
||||
&& runningTaskTarget.taskInfo.pictureInPictureParams.isAutoEnterEnabled();
|
||||
@@ -2221,14 +2211,22 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
} else if (mIsSwipeForSplit) {
|
||||
// Transaction to hide the task to avoid flicker for entering PiP from
|
||||
// split-screen.
|
||||
PictureInPictureSurfaceTransaction tx = new PictureInPictureSurfaceTransaction.Builder()
|
||||
.setAlpha(0f)
|
||||
.build();
|
||||
tx.setShouldDisableCanAffectSystemUiFlags(false);
|
||||
int[] taskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
|
||||
for (int taskId : taskIds) {
|
||||
mRecentsAnimationController.setFinishTaskTransaction(taskId,
|
||||
tx, null /* overlay */);
|
||||
try {
|
||||
PictureInPictureSurfaceTransaction tx = new PictureInPictureSurfaceTransaction.Builder()
|
||||
.setAlpha(0f)
|
||||
.build();
|
||||
try {
|
||||
tx.setShouldDisableCanAffectSystemUiFlags(false);
|
||||
} catch (NoSuchMethodError error) {
|
||||
Log.w(TAG, "not android 13 qpr1 : ", error);
|
||||
}
|
||||
int[] taskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds();
|
||||
for (int taskId : taskIds) {
|
||||
mRecentsAnimationController.setFinishTaskTransaction(taskId,
|
||||
tx, null /* overlay */);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
Log.w(TAG, "Failed PictureInPictureSurfaceTransaction: ", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2437,7 +2435,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, Q extends
|
||||
transaction.forSurface(target.leash).setAlpha(1).setLayer(-1).setShow();
|
||||
}
|
||||
surfaceApplier.scheduleApply(transaction);
|
||||
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_S) return;
|
||||
SplashScreenExitAnimationUtils.startAnimations(splashView, taskTarget.leash,
|
||||
mSplashMainWindowShiftLength, new TransactionPool(), new Rect(),
|
||||
SPLASH_ANIMATION_DURATION, SPLASH_FADE_OUT_DURATION,
|
||||
|
||||
@@ -30,6 +30,7 @@ import static com.android.quickstep.OverviewComponentObserver.startHomeIntentSaf
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
@@ -71,6 +72,7 @@ import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.quickstep.util.TransformParams.BuilderProxy;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -78,6 +80,8 @@ import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Handles the navigation gestures when a 3rd party launcher is the default home activity.
|
||||
*/
|
||||
@@ -160,8 +164,9 @@ public class FallbackSwipeHandler extends
|
||||
@Nullable RemoteAnimationTarget runningTaskTarget) {
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
Intent intent = new Intent(mGestureState.getHomeIntent());
|
||||
if (gestureContractAnimationFactory != null && runningTaskTarget != null) {
|
||||
gestureContractAnimationFactory.addGestureContract(intent, runningTaskTarget.taskInfo);
|
||||
var runningTask = TopTaskTracker.INSTANCE.get(mContext).getCachedTopTask(true);
|
||||
if (gestureContractAnimationFactory != null && runningTaskTarget != null && runningTask.getTaskId() == runningTaskTarget.taskId) {
|
||||
gestureContractAnimationFactory.addGestureContract(intent, runningTask.mAllCachedTasks.get(0));
|
||||
}
|
||||
startHomeIntentSafely(mContext, intent, options.toBundle());
|
||||
}
|
||||
|
||||
@@ -214,7 +214,10 @@ public class LauncherBackAnimationController {
|
||||
mAnimationFinishedCallback = finishedCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onAnimationCancelled(boolean isKeyguardOccluded) {
|
||||
onAnimationCancelled();
|
||||
}
|
||||
|
||||
public void onAnimationCancelled() {
|
||||
}
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@ import android.graphics.RectF;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
public class OrientationRectF extends RectF {
|
||||
|
||||
private static final String TAG = "OrientationRectF";
|
||||
@@ -76,7 +78,11 @@ public class OrientationRectF extends RectF {
|
||||
+ "mRotation: " + mRotation
|
||||
+ " this: " + this);
|
||||
}
|
||||
event.applyTransform(mTmpMatrix);
|
||||
if (Utilities.ATLEAST_S) {
|
||||
event.applyTransform(mTmpMatrix);
|
||||
} else {
|
||||
event.transform(mTmpMatrix);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
mTmpPoint[0] = event.getX();
|
||||
@@ -92,7 +98,11 @@ public class OrientationRectF extends RectF {
|
||||
}
|
||||
|
||||
if (contains(mTmpPoint[0], mTmpPoint[1])) {
|
||||
event.applyTransform(mTmpMatrix);
|
||||
if (Utilities.ATLEAST_S) {
|
||||
event.applyTransform(mTmpMatrix);
|
||||
} else {
|
||||
event.transform(mTmpMatrix);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -34,11 +34,14 @@ import android.util.SparseBooleanArray;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
import com.android.quickstep.util.DesktopTask;
|
||||
import com.android.quickstep.util.GroupTask;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||
import com.android.wm.shell.recents.IRecentTasksListener;
|
||||
import com.android.wm.shell.util.GroupedRecentTaskInfo;
|
||||
import com.android.wm.shell.util.SplitBounds;
|
||||
@@ -51,6 +54,7 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import app.lawnchair.LawnchairApp;
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Manages the recent task list from the system, caching it as necessary.
|
||||
@@ -83,26 +87,60 @@ public class RecentTasksList {
|
||||
mKeyguardManager = keyguardManager;
|
||||
mChangeId = 1;
|
||||
mSysUiProxy = sysUiProxy;
|
||||
sysUiProxy.registerRecentTasksListener(new IRecentTasksListener.Stub() {
|
||||
@Override
|
||||
public void onRecentTasksChanged() throws RemoteException {
|
||||
mMainThreadExecutor.execute(RecentTasksList.this::onRecentTasksChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
RecentTasksList.this.onRunningTaskAppeared(taskInfo);
|
||||
if (LawnchairApp.isRecentsEnabled()) {
|
||||
if (LawnchairQuickstepCompat.ATLEAST_U) {
|
||||
sysUiProxy.registerRecentTasksListener(new IRecentTasksListener.Stub() {
|
||||
@Override
|
||||
public void onRecentTasksChanged() throws RemoteException {
|
||||
mMainThreadExecutor.execute(RecentTasksList.this::onRecentTasksChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
RecentTasksList.this.onRunningTaskAppeared(taskInfo);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
RecentTasksList.this.onRunningTaskVanished(taskInfo);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (LawnchairQuickstepCompat.ATLEAST_Q) {
|
||||
TaskStackChangeListeners.getInstance().registerTaskStackListener(new TaskStackChangeListener () {
|
||||
@Override
|
||||
public void onTaskStackChanged() {
|
||||
onRecentTasksChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentTaskListUpdated() {
|
||||
onRecentTasksChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(int taskId) {
|
||||
onRecentTasksChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
|
||||
onRecentTasksChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityUnpinned() {
|
||||
onRecentTasksChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRunningTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
mMainThreadExecutor.execute(() -> {
|
||||
RecentTasksList.this.onRunningTaskVanished(taskInfo);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// We may receive onRunningTaskAppeared events later for tasks which have already been
|
||||
// included in the list returned by mSysUiProxy.getRunningTasks(), or may receive
|
||||
// onRunningTaskVanished for tasks not included in the returned list. These cases will be
|
||||
@@ -297,7 +335,7 @@ public class RecentTasksList {
|
||||
: Task.from(task2Key, taskInfo2,
|
||||
tmpLockedUsers.get(task2Key.userId) /* isLocked */);
|
||||
task2.setLastSnapshotData(taskInfo2);
|
||||
} else {
|
||||
} else if (Utilities.ATLEAST_S) {
|
||||
// Is fullscreen task
|
||||
if (numVisibleTasks > 0) {
|
||||
boolean isExcluded = (taskInfo1.baseIntent.getFlags()
|
||||
@@ -309,8 +347,10 @@ public class RecentTasksList {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (taskInfo1.isVisible) {
|
||||
numVisibleTasks++;
|
||||
if (Utilities.ATLEAST_S) {
|
||||
if (taskInfo1.isVisible) {
|
||||
numVisibleTasks++;
|
||||
}
|
||||
}
|
||||
final SplitConfigurationOptions.SplitBounds launcherSplitBounds =
|
||||
convertSplitBounds(rawTask.getSplitBounds());
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static android.os.Trace.TRACE_TAG_APP;
|
||||
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
|
||||
import static android.view.RemoteAnimationTarget.MODE_OPENING;
|
||||
|
||||
@@ -36,7 +35,6 @@ import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Trace;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
@@ -91,6 +89,8 @@ import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.List;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* A recents activity that shows the recently launched tasks as swipable task
|
||||
* cards.
|
||||
@@ -275,15 +275,16 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
|
||||
final LauncherAnimationRunner wrapper = new LauncherAnimationRunner(
|
||||
mUiHandler, mActivityLaunchAnimationRunner, true /* startAtFrontOfQueue */);
|
||||
final ActivityOptions options = ActivityOptions.makeRemoteAnimation(
|
||||
final ActivityOptions options = LawnchairQuickstepCompat.getActivityOptionsCompat().makeRemoteAnimation(
|
||||
new RemoteAnimationAdapter(wrapper, RECENTS_LAUNCH_DURATION,
|
||||
RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION
|
||||
- STATUS_BAR_TRANSITION_PRE_DELAY),
|
||||
new RemoteTransition(wrapper.toRemoteTransition(), getIApplicationThread(),
|
||||
"LaunchFromRecents"));
|
||||
LawnchairQuickstepCompat.getRemoteTransitionCompat().getRemoteTransition(wrapper.toRemoteTransition(), getIApplicationThread(),
|
||||
"LaunchFromRecents"),
|
||||
"Lawnchair");
|
||||
final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(options,
|
||||
onEndCallback);
|
||||
if (Utilities.ATLEAST_S) {
|
||||
if (Utilities.ATLEAST_T) {
|
||||
activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
|
||||
activityOptions.options.setLaunchDisplayId(
|
||||
(v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
|
||||
@@ -422,10 +423,11 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
private void startHomeInternal() {
|
||||
LauncherAnimationRunner runner = new LauncherAnimationRunner(
|
||||
getMainThreadHandler(), mAnimationToHomeFactory, true);
|
||||
ActivityOptions options = ActivityOptions.makeRemoteAnimation(
|
||||
ActivityOptions options = LawnchairQuickstepCompat.getActivityOptionsCompat().makeRemoteAnimation(
|
||||
new RemoteAnimationAdapter(runner, HOME_APPEAR_DURATION, 0),
|
||||
new RemoteTransition(runner.toRemoteTransition(), getIApplicationThread(),
|
||||
"StartHomeFromRecents"));
|
||||
LawnchairQuickstepCompat.getRemoteTransitionCompat().getRemoteTransition(runner.toRemoteTransition(), getIApplicationThread(),
|
||||
"StartHomeFromRecents"),
|
||||
"Lawnchair");
|
||||
startHomeIntentSafely(this, options.toBundle());
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Wrapper around {@link com.android.systemui.shared.system.RecentsAnimationListener} which
|
||||
* delegates callbacks to multiple listeners on the main thread
|
||||
@@ -125,7 +127,7 @@ public class RecentsAnimationCallbacks implements
|
||||
} else {
|
||||
RemoteAnimationTarget[] nonAppTargets;
|
||||
if (!TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
|
||||
nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(appTargets);
|
||||
nonAppTargets = LawnchairQuickstepCompat.ATLEAST_T ? mSystemUiProxy.onGoingToRecentsLegacy(appTargets) : null;
|
||||
} else {
|
||||
final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
|
||||
final ArrayList<RemoteAnimationTarget> nonApps = new ArrayList<>();
|
||||
|
||||
@@ -130,6 +130,7 @@ public class RemoteAnimationTargets {
|
||||
}
|
||||
|
||||
private static void release(RemoteAnimationTarget[] targets) {
|
||||
if (targets == null) return;
|
||||
for (RemoteAnimationTarget target : targets) {
|
||||
if (target.leash != null) {
|
||||
target.leash.release();
|
||||
|
||||
@@ -29,8 +29,9 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -59,12 +60,15 @@ import androidx.annotation.WorkerThread;
|
||||
import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.util.ScreenshotRequest;
|
||||
import com.android.internal.view.AppearanceRegion;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||
import com.android.quickstep.util.AssistUtils;
|
||||
import com.android.systemui.shared.recents.ISystemUiProxy;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
|
||||
import com.android.systemui.shared.system.RecentsAnimationListener;
|
||||
import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController;
|
||||
@@ -94,6 +98,10 @@ import com.android.wm.shell.util.GroupedRecentTaskInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Holds the reference to SystemUI.
|
||||
@@ -231,7 +239,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
unlinkToDeath();
|
||||
mSystemUiProxy = proxy;
|
||||
mPip = pip;
|
||||
mBubbles = bubbles;
|
||||
mBubbles = Utilities.ATLEAST_U ? bubbles : null;
|
||||
mSplitScreen = splitScreen;
|
||||
mOneHanded = oneHanded;
|
||||
mShellTransitions = shellTransitions;
|
||||
@@ -241,7 +249,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
mBackAnimation = backAnimation;
|
||||
mDesktopMode = desktopMode;
|
||||
mUnfoldAnimation = unfoldAnimation;
|
||||
mDragAndDrop = dragAndDrop;
|
||||
mDragAndDrop = Utilities.ATLEAST_U ? dragAndDrop : null;
|
||||
linkToDeath();
|
||||
// re-attach the listeners once missing due to setProxy has not been initialized
|
||||
// yet.
|
||||
@@ -360,6 +368,11 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect getNonMinimizedSplitScreenSecondaryBounds() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startAssistant(Bundle args) {
|
||||
if (mSystemUiProxy != null) {
|
||||
@@ -382,6 +395,18 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle monitorGestureInput(String name, int displayId) {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
return mSystemUiProxy.monitorGestureInput(name, displayId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call monitorGestureInput: " + name, e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyAccessibilityButtonClicked(int displayId) {
|
||||
if (mSystemUiProxy != null) {
|
||||
@@ -426,17 +451,6 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
// public void setTaskbarEnabled(boolean enabled) {
|
||||
// if (mSystemUiProxy != null) {
|
||||
// try {
|
||||
// mSystemUiProxy.setTaskbarEnabled(enabled);
|
||||
// } catch (RemoteException e) {
|
||||
// Log.w(TAG, "Failed call setTaskbarEnabled with arg: " +
|
||||
// enabled, e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
public void notifyTaskbarStatus(boolean visible, boolean stashed) {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
@@ -477,6 +491,54 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleImageBundleAsScreenshot(Bundle screenImageBundle, Rect locationInScreen,
|
||||
Insets visibleInsets, Task.TaskKey task) {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
mSystemUiProxy.handleImageBundleAsScreenshot(screenImageBundle, locationInScreen,
|
||||
visibleInsets, task);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call handleImageBundleAsScreenshot");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleImageAsScreenshot(Bitmap bitmap, Rect rect, Insets insets, int i) {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
mSystemUiProxy.handleImageAsScreenshot(bitmap, rect, insets, i);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call handleImageAsScreenshot", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSplitScreenMinimized(boolean minimized) throws RemoteException {}
|
||||
|
||||
@Override
|
||||
public void notifySwipeToHomeFinished() {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
mSystemUiProxy.notifySwipeUpGestureStarted();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call notifySwipeUpGestureStarted", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifySwipeUpGestureStarted() {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
mSystemUiProxy.notifySwipeToHomeFinished();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call notifySwipeToHomeFinished", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStatusBarTrackpadEvent(MotionEvent event) {
|
||||
if (mSystemUiProxy != null) {
|
||||
@@ -527,7 +589,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
boolean visible = visibleInt != 0;
|
||||
boolean changed = visible != mLastShelfVisible || shelfHeight != mLastShelfHeight;
|
||||
IPip pip = mPip;
|
||||
if (pip != null && changed) {
|
||||
if (pip != null && changed && Utilities.ATLEAST_T) {
|
||||
mLastShelfVisible = visible;
|
||||
mLastShelfHeight = shelfHeight;
|
||||
try {
|
||||
@@ -544,8 +606,10 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
* the Launcher for the Hotseat.
|
||||
*/
|
||||
public void setLauncherKeepClearAreaHeight(boolean visible, int height) {
|
||||
Message.obtain(mAsyncHandler, MSG_SET_LAUNCHER_KEEP_CLEAR_AREA_HEIGHT,
|
||||
visible ? 1 : 0, height).sendToTarget();
|
||||
if (Utilities.ATLEAST_T) {
|
||||
Message.obtain(mAsyncHandler, MSG_SET_LAUNCHER_KEEP_CLEAR_AREA_HEIGHT,
|
||||
visible ? 1 : 0, height).sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@@ -570,7 +634,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
* Sets listener to get pip animation callbacks.
|
||||
*/
|
||||
public void setPipAnimationListener(IPipAnimationListener listener) {
|
||||
if (mPip != null) {
|
||||
if (mPip != null && Utilities.ATLEAST_T) {
|
||||
try {
|
||||
mPip.setPipAnimationListener(listener);
|
||||
} catch (RemoteException e) {
|
||||
@@ -592,7 +656,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
try {
|
||||
return mPip.startSwipePipToHome(componentName, activityInfo,
|
||||
pictureInPictureParams, launcherRotation, hotseatKeepClearArea);
|
||||
} catch (RemoteException e) {
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed call startSwipePipToHome", e);
|
||||
}
|
||||
}
|
||||
@@ -636,12 +700,16 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
* Sets the next pip animation type to be the alpha animation.
|
||||
*/
|
||||
public void setPipAnimationTypeToAlpha() {
|
||||
if (mPip != null) {
|
||||
try {
|
||||
mPip.setPipAnimationTypeToAlpha();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call setPipAnimationTypeToAlpha", e);
|
||||
try {
|
||||
if (mPip != null) {
|
||||
try {
|
||||
mPip.setPipAnimationTypeToAlpha();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call setPipAnimationTypeToAlpha", e);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
Log.w(TAG, "Failed call setPipAnimationTypeToAlpha not supported", t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,7 +717,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
* Sets the app icon size in pixel used by Launcher all apps.
|
||||
*/
|
||||
public void setLauncherAppIconSize(int iconSizePx) {
|
||||
if (mPip != null) {
|
||||
if (mPip != null && Utilities.ATLEAST_T) {
|
||||
try {
|
||||
mPip.setLauncherAppIconSize(iconSizePx);
|
||||
} catch (RemoteException e) {
|
||||
@@ -766,14 +834,18 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
//
|
||||
|
||||
public void registerSplitScreenListener(ISplitScreenListener listener) {
|
||||
if (mSplitScreen != null) {
|
||||
try {
|
||||
mSplitScreen.registerSplitScreenListener(listener);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call registerSplitScreenListener");
|
||||
try {
|
||||
if (mSplitScreen != null) {
|
||||
try {
|
||||
mSplitScreen.registerSplitScreenListener(listener);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call registerSplitScreenListener");
|
||||
}
|
||||
}
|
||||
mSplitScreenListener = listener;
|
||||
} catch (Throwable t) {
|
||||
Log.w (TAG , "Not supported: " , t);
|
||||
}
|
||||
mSplitScreenListener = listener;
|
||||
}
|
||||
|
||||
public void unregisterSplitScreenListener(ISplitScreenListener listener) {
|
||||
@@ -871,7 +943,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
public void startTasksWithLegacyTransition(int taskId1, Bundle options1, int taskId2,
|
||||
Bundle options2, @SplitConfigurationOptions.StagePosition int splitPosition,
|
||||
float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) {
|
||||
if (mSystemUiProxy != null) {
|
||||
if (mSystemUiProxy != null && Utilities.ATLEAST_T) {
|
||||
try {
|
||||
mSplitScreen.startTasksWithLegacyTransition(taskId1, options1, taskId2, options2,
|
||||
splitPosition, splitRatio, adapter, instanceId);
|
||||
@@ -992,7 +1064,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
if (mSplitScreen != null) {
|
||||
try {
|
||||
return mSplitScreen.onStartingSplitLegacy(apps);
|
||||
} catch (RemoteException e) {
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed call onStartingSplitLegacy");
|
||||
}
|
||||
}
|
||||
@@ -1243,27 +1315,34 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
|
||||
public ArrayList<GroupedRecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
if (mRecentTasks != null) {
|
||||
try {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_U) {
|
||||
return getRecentTasksFromWrapper(numTasks, userId);
|
||||
}
|
||||
try {
|
||||
if (mRecentTasks != null) {
|
||||
final GroupedRecentTaskInfo[] rawTasks = mRecentTasks.getRecentTasks(numTasks,
|
||||
RECENT_IGNORE_UNAVAILABLE, userId);
|
||||
if (rawTasks == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return new ArrayList<>(Arrays.asList(rawTasks));
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call getRecentTasks", e);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
Log.w(TAG, "Failed call getRecentTasks ,may be android 13- ", t);
|
||||
return getRecentTasksFromWrapper(numTasks, userId);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
private ArrayList<GroupedRecentTaskInfo> getRecentTasksFromWrapper(int numTasks, int userId) {
|
||||
List<ActivityManager.RecentTaskInfo> recentTaskInfoList = ActivityManagerWrapper.getInstance().getRecentTasks(numTasks, userId);
|
||||
return recentTaskInfoList.stream()
|
||||
.map(GroupedRecentTaskInfo::forSingleTask)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of running tasks.
|
||||
*/
|
||||
public ArrayList<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
|
||||
if (mRecentTasks != null
|
||||
&& mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_PC)) {
|
||||
if (mRecentTasks != null) {
|
||||
try {
|
||||
return new ArrayList<>(Arrays.asList(mRecentTasks.getRunningTasks(numTasks)));
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.content.Intent;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.RemoteTransition;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
@@ -53,7 +54,7 @@ import java.util.HashMap;
|
||||
|
||||
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
public static final boolean ENABLE_SHELL_TRANSITIONS = SystemProperties.getBoolean("persist.wm.debug.shell_transit",
|
||||
true);
|
||||
Utilities.ATLEAST_U);
|
||||
public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
|
||||
&& SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
|
||||
|
||||
@@ -274,10 +275,13 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
if (!homeIsOnTop) {
|
||||
options.setTransientLaunch();
|
||||
}
|
||||
if (app.lawnchair.LawnchairApp.isAtleastT()) {
|
||||
if (Utilities.ATLEAST_S) {
|
||||
options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
|
||||
SystemUiProxy.INSTANCE.getNoCreate().startRecentsActivity(intent, options, mCallbacks);
|
||||
if (Utilities.ATLEAST_U) {
|
||||
SystemUiProxy.INSTANCE.getNoCreate().startRecentsActivity(intent, options, mCallbacks);
|
||||
}
|
||||
}
|
||||
UI_HELPER_EXECUTOR.execute(() -> mCtx.startActivity(intent, options.toBundle()));
|
||||
} else {
|
||||
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
||||
.startRecentsActivity(intent, eventTime, mCallbacks, null, null));
|
||||
|
||||
@@ -140,6 +140,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
||||
*/
|
||||
private static final TaskShortcutFactory[] MENU_OPTIONS = new TaskShortcutFactory[] {
|
||||
TaskShortcutFactory.APP_INFO,
|
||||
app.lawnchair.overview.TaskShortcutFactory.legacySplit,
|
||||
TaskShortcutFactory.SPLIT_SELECT,
|
||||
TaskShortcutFactory.PIN,
|
||||
TaskShortcutFactory.INSTALL,
|
||||
|
||||
@@ -65,6 +65,8 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Represents a system shortcut that can be shown for a recent task. Appears as
|
||||
* a single entry in
|
||||
@@ -281,6 +283,7 @@ public interface TaskShortcutFactory {
|
||||
@Override
|
||||
public List<SystemShortcut> getShortcuts(BaseDraggingActivity activity,
|
||||
TaskIdAttributeContainer taskContainer) {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_T) return null;
|
||||
DeviceProfile deviceProfile = activity.getDeviceProfile();
|
||||
final Task task = taskContainer.getTask();
|
||||
final int intentFlags = task.key.baseIntent.getFlags();
|
||||
|
||||
@@ -51,6 +51,9 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* This class tracked the top-most task and some 'approximate' task history to allow faster
|
||||
@@ -81,11 +84,14 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(int taskId) {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_T) return;
|
||||
mOrderedTaskList.removeIf(rto -> rto.taskId == taskId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_T) return;
|
||||
|
||||
mOrderedTaskList.removeIf(rto -> rto.taskId == taskInfo.taskId);
|
||||
mOrderedTaskList.addFirst(taskInfo);
|
||||
|
||||
@@ -180,6 +186,14 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta
|
||||
*/
|
||||
@UiThread
|
||||
public CachedTaskInfo getCachedTopTask(boolean filterOnlyVisibleRecents) {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_U) {
|
||||
RunningTaskInfo task = TraceHelper.allowIpcs("getCachedTopTask.false", () ->
|
||||
ActivityManagerWrapper.getInstance().getRunningTask(
|
||||
false /* filterOnlyVisibleRecents */));
|
||||
ArrayList<RunningTaskInfo> taskList = new ArrayList<>();
|
||||
Collections.addAll(taskList, task);
|
||||
return new CachedTaskInfo(taskList);
|
||||
}
|
||||
if (filterOnlyVisibleRecents) {
|
||||
// Since we only know about the top most task, any filtering may not be applied on the
|
||||
// cache. The second to top task may change while the top task is still the same.
|
||||
@@ -240,7 +254,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta
|
||||
List<RunningTaskInfo> visibleNonExcludedTasks = mAllCachedTasks.stream()
|
||||
.filter(t -> t.isVisible
|
||||
&& (t.baseIntent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0)
|
||||
.toList();
|
||||
.collect(Collectors.toList());
|
||||
return visibleNonExcludedTasks.isEmpty() ? null
|
||||
: new CachedTaskInfo(visibleNonExcludedTasks);
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatedFloat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.provider.RestoreDbTask;
|
||||
@@ -148,6 +149,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import app.lawnchair.LawnchairApp;
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Service connected by system-UI for handling touch interaction.
|
||||
@@ -206,12 +208,16 @@ public class TouchInteractionService extends Service {
|
||||
IDragAndDrop dragAndDrop = IDragAndDrop.Stub.asInterface(
|
||||
bundle.getBinder(KEY_EXTRA_SHELL_DRAG_AND_DROP));
|
||||
MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
|
||||
SystemUiProxy.INSTANCE.get(tis).setProxy(proxy, pip,
|
||||
bubbles, splitscreen, onehanded, shellTransitions, startingWindow,
|
||||
recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
|
||||
unfoldTransition, dragAndDrop);
|
||||
tis.initInputMonitor("TISBinder#onInitialize()");
|
||||
tis.preloadOverview(true /* fromInit */);
|
||||
try {
|
||||
SystemUiProxy.INSTANCE.get(tis).setProxy(proxy, pip,
|
||||
bubbles, splitscreen, onehanded, shellTransitions, startingWindow,
|
||||
recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
|
||||
unfoldTransition, dragAndDrop);
|
||||
tis.initInputMonitor("TISBinder#onInitialize()");
|
||||
tis.preloadOverview(true /* fromInit */);
|
||||
} catch (Throwable t) {
|
||||
// Ignore
|
||||
}
|
||||
}));
|
||||
sIsInitialized = true;
|
||||
}
|
||||
@@ -219,7 +225,7 @@ public class TouchInteractionService extends Service {
|
||||
@BinderThread
|
||||
@Override
|
||||
public void onTaskbarToggled() {
|
||||
if (!FeatureFlags.ENABLE_KEYBOARD_TASKBAR_TOGGLE.get())
|
||||
if (!FeatureFlags.ENABLE_KEYBOARD_TASKBAR_TOGGLE.get() || !LawnchairQuickstepCompat.ATLEAST_S)
|
||||
return;
|
||||
MAIN_EXECUTOR.execute(() -> executeForTouchInteractionService(tis -> {
|
||||
TaskbarActivityContext activityContext = tis.mTaskbarManager.getCurrentActivityContext();
|
||||
@@ -394,7 +400,7 @@ public class TouchInteractionService extends Service {
|
||||
@Nullable
|
||||
public TaskbarManager getTaskbarManager() {
|
||||
TouchInteractionService tis = mTis.get();
|
||||
if (tis == null)
|
||||
if (tis == null || !LawnchairQuickstepCompat.ATLEAST_S)
|
||||
return null;
|
||||
return tis.mTaskbarManager;
|
||||
}
|
||||
@@ -489,14 +495,16 @@ public class TouchInteractionService extends Service {
|
||||
mMainChoreographer = Choreographer.getInstance();
|
||||
mAM = ActivityManagerWrapper.getInstance();
|
||||
mDeviceState = new RecentsAnimationDeviceState(this, true);
|
||||
mTaskbarManager = new TaskbarManager(this);
|
||||
mTaskbarManager = LawnchairQuickstepCompat.ATLEAST_S ? new TaskbarManager(this) : null;
|
||||
mRotationTouchHelper = mDeviceState.getRotationTouchHelper();
|
||||
BootAwarePreloader.start(this);
|
||||
|
||||
// Call runOnUserUnlocked() before any other callbacks to ensure everything is
|
||||
// initialized.
|
||||
LockedUserState.get(this).runOnUserUnlocked(this::onUserUnlocked);
|
||||
LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
LockedUserState.get(this).runOnUserUnlocked(mTaskbarManager::onUserUnlocked);
|
||||
}
|
||||
mDeviceState.addNavigationModeChangedCallback(this::onNavigationModeChanged);
|
||||
sConnected = true;
|
||||
}
|
||||
@@ -520,7 +528,16 @@ public class TouchInteractionService extends Service {
|
||||
return;
|
||||
}
|
||||
|
||||
mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());
|
||||
if (LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
mInputMonitorCompat = new InputMonitorCompat("swipe-up", mDeviceState.getDisplayId());
|
||||
} else {
|
||||
if (!SystemUiProxy.INSTANCE.get(this).isActive()) {
|
||||
return;
|
||||
}
|
||||
Bundle bundle = SystemUiProxy.INSTANCE.get(this).monitorGestureInput("swipe-up",
|
||||
mDeviceState.getDisplayId());
|
||||
mInputMonitorCompat = InputMonitorCompat.fromBundle(bundle, "extra_input_monitor");
|
||||
}
|
||||
mInputEventReceiver = mInputMonitorCompat.getInputReceiver(Looper.getMainLooper(),
|
||||
mMainChoreographer, this::onInputEvent);
|
||||
|
||||
@@ -542,8 +559,10 @@ public class TouchInteractionService extends Service {
|
||||
mOverviewComponentObserver = new OverviewComponentObserver(this, mDeviceState);
|
||||
mOverviewCommandHelper = new OverviewCommandHelper(this,
|
||||
mOverviewComponentObserver, mTaskAnimationManager);
|
||||
mResetGestureInputConsumer = new ResetGestureInputConsumer(
|
||||
mTaskAnimationManager, mTaskbarManager::getCurrentActivityContext);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_S && mTaskbarManager != null) {
|
||||
mResetGestureInputConsumer = new ResetGestureInputConsumer(
|
||||
mTaskAnimationManager, mTaskbarManager::getCurrentActivityContext);
|
||||
}
|
||||
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
|
||||
mInputConsumer.registerInputConsumer();
|
||||
onSystemUiFlagsChanged(mDeviceState.getSystemUiStateFlags());
|
||||
@@ -585,15 +604,17 @@ public class TouchInteractionService extends Service {
|
||||
private void onOverviewTargetChange(boolean isHomeAndOverviewSame) {
|
||||
AccessibilityManager am = getSystemService(AccessibilityManager.class);
|
||||
|
||||
if (isHomeAndOverviewSame) {
|
||||
am.registerSystemAction(createAllAppsAction(), GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
|
||||
} else {
|
||||
am.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_R) {
|
||||
if (isHomeAndOverviewSame) {
|
||||
am.registerSystemAction(createAllAppsAction(), GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
|
||||
} else {
|
||||
am.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
|
||||
}
|
||||
}
|
||||
|
||||
StatefulActivity newOverviewActivity = mOverviewComponentObserver.getActivityInterface()
|
||||
.getCreatedActivity();
|
||||
if (newOverviewActivity != null) {
|
||||
if (newOverviewActivity != null && mTaskbarManager != null) {
|
||||
mTaskbarManager.setActivity(newOverviewActivity);
|
||||
}
|
||||
mTISBinder.onOverviewTargetChange();
|
||||
@@ -604,7 +625,7 @@ public class TouchInteractionService extends Service {
|
||||
.setAction(INTENT_ACTION_ALL_APPS_TOGGLE);
|
||||
final PendingIntent actionPendingIntent;
|
||||
|
||||
if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get()) {
|
||||
if (FeatureFlags.ENABLE_ALL_APPS_SEARCH_IN_TASKBAR.get() && mTaskbarManager != null) {
|
||||
actionPendingIntent = new PendingIntent(new IIntentSender.Stub() {
|
||||
@Override
|
||||
public void send(int code, Intent intent, String resolvedType,
|
||||
@@ -634,7 +655,9 @@ public class TouchInteractionService extends Service {
|
||||
int systemUiStateFlags = mDeviceState.getSystemUiStateFlags();
|
||||
SystemUiProxy.INSTANCE.get(this).setLastSystemUiStateFlags(systemUiStateFlags);
|
||||
mOverviewComponentObserver.onSystemUiStateChanged();
|
||||
mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
|
||||
if (mTaskbarManager != null) {
|
||||
mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
|
||||
}
|
||||
|
||||
int isShadeExpandedFlag = SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
|
||||
boolean wasExpanded = (lastSysUIFlags & isShadeExpandedFlag) != 0;
|
||||
@@ -671,10 +694,14 @@ public class TouchInteractionService extends Service {
|
||||
mDeviceState.destroy();
|
||||
SystemUiProxy.INSTANCE.get(this).clearProxy();
|
||||
|
||||
getSystemService(AccessibilityManager.class)
|
||||
.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_R) {
|
||||
getSystemService(AccessibilityManager.class)
|
||||
.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS);
|
||||
}
|
||||
|
||||
mTaskbarManager.destroy();
|
||||
if (mTaskbarManager != null) {
|
||||
mTaskbarManager.destroy();
|
||||
}
|
||||
sConnected = false;
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -706,7 +733,7 @@ public class TouchInteractionService extends Service {
|
||||
// Note this will create a new consumer every mouse click, as after ACTION_UP
|
||||
// from the click
|
||||
// an ACTION_HOVER_ENTER will fire as well.
|
||||
boolean isHoverActionWithoutConsumer = event.isHoverEvent()
|
||||
boolean isHoverActionWithoutConsumer = isHoverEvent(action)
|
||||
&& (mUncheckedConsumer.getType() & TYPE_CURSOR_HOVER) == 0;
|
||||
if (action == ACTION_DOWN || isHoverActionWithoutConsumer) {
|
||||
mRotationTouchHelper.setOrientationTransformIfNeeded(event);
|
||||
@@ -801,9 +828,15 @@ public class TouchInteractionService extends Service {
|
||||
traceToken.close();
|
||||
}
|
||||
|
||||
private boolean isHoverEvent(int action) {
|
||||
return action == MotionEvent.ACTION_HOVER_ENTER
|
||||
|| action == MotionEvent.ACTION_HOVER_MOVE
|
||||
|| action == MotionEvent.ACTION_HOVER_EXIT;
|
||||
}
|
||||
|
||||
// Talkback generates hover events on touch, which we do not want to consume.
|
||||
private boolean isCursorHoverEvent(MotionEvent event) {
|
||||
return event.isHoverEvent() && event.getSource() == InputDevice.SOURCE_MOUSE;
|
||||
return isHoverEvent(event.getActionMasked()) && event.getSource() == InputDevice.SOURCE_MOUSE;
|
||||
}
|
||||
|
||||
private InputConsumer tryCreateAssistantInputConsumer(
|
||||
@@ -925,7 +958,7 @@ public class TouchInteractionService extends Service {
|
||||
|
||||
// If Taskbar is present, we listen for swipe or cursor hover events to unstash
|
||||
// it.
|
||||
TaskbarActivityContext tac = mTaskbarManager.getCurrentActivityContext();
|
||||
TaskbarActivityContext tac = mTaskbarManager != null ? mTaskbarManager.getCurrentActivityContext() : null;
|
||||
if (tac != null && !(base instanceof AssistantInputConsumer)) {
|
||||
// Present always on large screen or on small screen w/ flag
|
||||
DeviceProfile dp = tac.getDeviceProfile();
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.android.launcher3.Utilities;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Utility class for helpful methods related to {@link View} objects.
|
||||
*/
|
||||
@@ -43,6 +45,9 @@ public class ViewUtils {
|
||||
*/
|
||||
public static boolean postFrameDrawn(
|
||||
View view, Runnable onFinishRunnable, BooleanSupplier canceled) {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_U) {
|
||||
return new FrameHandlerVR(view, onFinishRunnable, canceled).schedule();
|
||||
}
|
||||
return new FrameHandler(view, onFinishRunnable, canceled).schedule();
|
||||
}
|
||||
|
||||
@@ -129,4 +134,51 @@ public class ViewUtils {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class FrameHandlerVR implements HardwareRenderer.FrameDrawingCallback {
|
||||
|
||||
final ViewRootImpl mViewRoot;
|
||||
final Runnable mFinishCallback;
|
||||
final BooleanSupplier mCancelled;
|
||||
final Handler mHandler;
|
||||
|
||||
int mDeferFrameCount = 1;
|
||||
|
||||
FrameHandlerVR(View view, Runnable finishCallback, BooleanSupplier cancelled) {
|
||||
mViewRoot = view.getViewRootImpl();
|
||||
mFinishCallback = finishCallback;
|
||||
mCancelled = cancelled;
|
||||
mHandler = new Handler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFrameDraw(long frame) {
|
||||
Utilities.postAsyncCallback(mHandler, this::onFrame);
|
||||
}
|
||||
|
||||
private void onFrame() {
|
||||
if (mCancelled.getAsBoolean()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mDeferFrameCount > 0) {
|
||||
mDeferFrameCount--;
|
||||
schedule();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFinishCallback != null) {
|
||||
mFinishCallback.run();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean schedule() {
|
||||
if (mViewRoot != null && mViewRoot.getView() != null) {
|
||||
mViewRoot.registerRtFrameCallback(this);
|
||||
mViewRoot.getView().invalidate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ import com.android.internal.util.ScreenshotRequest;
|
||||
import com.android.launcher3.BuildConfig;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -61,6 +62,8 @@ import java.io.IOException;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import app.lawnchair.compatlib.utils.BitmapUtil;
|
||||
|
||||
/**
|
||||
* Utility class containing methods to help manage image actions such as sharing, cropping, and
|
||||
* saving image.
|
||||
@@ -78,16 +81,25 @@ public class ImageActionUtils {
|
||||
*/
|
||||
public static void saveScreenshot(SystemUiProxy systemUiProxy, Bitmap screenshot,
|
||||
Rect screenshotBounds, Insets visibleInsets, Task.TaskKey task) {
|
||||
ScreenshotRequest request =
|
||||
new ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OVERVIEW)
|
||||
.setTopComponent(task.sourceComponent)
|
||||
.setTaskId(task.id)
|
||||
.setUserId(task.userId)
|
||||
.setBitmap(screenshot)
|
||||
.setBoundsOnScreen(screenshotBounds)
|
||||
.setInsets(visibleInsets)
|
||||
.build();
|
||||
systemUiProxy.takeScreenshot(request);
|
||||
try {
|
||||
ScreenshotRequest request =
|
||||
new ScreenshotRequest.Builder(TAKE_SCREENSHOT_PROVIDED_IMAGE, SCREENSHOT_OVERVIEW)
|
||||
.setTopComponent(task.sourceComponent)
|
||||
.setTaskId(task.id)
|
||||
.setUserId(task.userId)
|
||||
.setBitmap(screenshot)
|
||||
.setBoundsOnScreen(screenshotBounds)
|
||||
.setInsets(visibleInsets)
|
||||
.build();
|
||||
systemUiProxy.takeScreenshot(request);
|
||||
} catch (Throwable t) {
|
||||
try {
|
||||
systemUiProxy.handleImageBundleAsScreenshot(BitmapUtil.hardwareBitmapToBundle(screenshot),
|
||||
screenshotBounds, visibleInsets, task);
|
||||
} catch (Throwable ee) {
|
||||
Shell.su("input keyevent 120").exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -107,6 +107,8 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Represent data needed for the transient state when user has selected one app for split screen
|
||||
* and is in the process of either a) selecting a second app or b) exiting intention to invoke split
|
||||
@@ -468,7 +470,7 @@ public class SplitSelectStateController {
|
||||
|
||||
final RemoteSplitLaunchTransitionRunner animationRunner =
|
||||
new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
|
||||
final RemoteTransition remoteTransition = new RemoteTransition(animationRunner,
|
||||
final RemoteTransition remoteTransition = LawnchairQuickstepCompat.getRemoteTransitionCompat().getRemoteTransition(animationRunner,
|
||||
ActivityThread.currentActivityThread().getApplicationThread(),
|
||||
"LaunchAppFullscreen");
|
||||
InstanceId instanceId = LogUtils.getShellShareableInstanceId().first;
|
||||
@@ -513,7 +515,7 @@ public class SplitSelectStateController {
|
||||
@Nullable Consumer<Boolean> callback, String transitionName) {
|
||||
final RemoteSplitLaunchTransitionRunner animationRunner =
|
||||
new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
|
||||
return new RemoteTransition(animationRunner,
|
||||
return LawnchairQuickstepCompat.getRemoteTransitionCompat().getRemoteTransition(animationRunner,
|
||||
ActivityThread.currentActivityThread().getApplicationThread(), transitionName);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.graphics.Rect;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
/**
|
||||
* Helper class for building a {@link Transaction}.
|
||||
*/
|
||||
@@ -103,7 +105,9 @@ public class SurfaceTransaction {
|
||||
* @return this Builder
|
||||
*/
|
||||
public SurfaceProperties setShadowRadius(float radius) {
|
||||
mTransaction.setShadowRadius(mSurface, radius);
|
||||
if (Utilities.ATLEAST_R) {
|
||||
mTransaction.setShadowRadius(mSurface, radius);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ import android.view.ViewRootImpl;
|
||||
|
||||
import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* Helper class to apply surface transactions in sync with RenderThread similar to
|
||||
* android.view.SyncRtSurfaceTransactionApplier
|
||||
@@ -112,7 +114,11 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
|
||||
.sendToTarget();
|
||||
return;
|
||||
}
|
||||
mTargetViewRootImpl.mergeWithNextTransaction(t, frame);
|
||||
if (LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
mTargetViewRootImpl.mergeWithNextTransaction(t, frame);
|
||||
} else {
|
||||
t.apply();
|
||||
}
|
||||
Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
|
||||
.sendToTarget();
|
||||
});
|
||||
|
||||
@@ -271,7 +271,11 @@ public class SwipePipToHomeAnimator extends RectFSpringAnim {
|
||||
PipSurfaceTransactionHelper.newSurfaceControlTransaction();
|
||||
final PictureInPictureSurfaceTransaction pipTx =
|
||||
onAnimationUpdate(tx, new RectF(mDestinationBounds), END_PROGRESS);
|
||||
pipTx.setShouldDisableCanAffectSystemUiFlags(true);
|
||||
try {
|
||||
pipTx.setShouldDisableCanAffectSystemUiFlags(true);
|
||||
} catch (NoSuchMethodError error) {
|
||||
Log.w(TAG, "not android 13 qpr1 : ", error);
|
||||
}
|
||||
return pipTx;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
public void setPreview(RemoteAnimationTarget runningTarget) {
|
||||
setPreviewBounds(
|
||||
runningTarget.startBounds == null
|
||||
? runningTarget.screenSpaceBounds : runningTarget.startBounds,
|
||||
? (Utilities.ATLEAST_R ? runningTarget.screenSpaceBounds : runningTarget.sourceContainerBounds) : runningTarget.startBounds,
|
||||
runningTarget.contentInsets);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,20 @@
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
|
||||
|
||||
import android.util.FloatProperty;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import com.android.app.animation.Interpolators;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
public class TransformParams {
|
||||
|
||||
@@ -162,7 +167,7 @@ public class TransformParams {
|
||||
} else {
|
||||
// Fade out translucent overlay.
|
||||
// TODO(b/303351074): use app.isNotInRecents directly once it is fixed.
|
||||
boolean isNotInRecents = app.taskInfo != null
|
||||
boolean isNotInRecents = LawnchairQuickstepCompat.ATLEAST_S && app.taskInfo != null
|
||||
&& (app.taskInfo.baseIntent.getFlags()
|
||||
& FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
|
||||
if (app.isTranslucent && isNotInRecents) {
|
||||
|
||||
@@ -219,6 +219,7 @@ import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import app.lawnchair.LawnchairApp;
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
import app.lawnchair.theme.color.ColorTokens;
|
||||
import app.lawnchair.util.OverScrollerCompat;
|
||||
|
||||
@@ -5461,7 +5462,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean sendUserLeaveHint = toRecents && shouldPip;
|
||||
final boolean sendUserLeaveHint = toRecents && shouldPip && LawnchairQuickstepCompat.ATLEAST_S;
|
||||
if (sendUserLeaveHint) {
|
||||
// Notify the SysUI to use fade-in animation when entering PiP from live tile.
|
||||
final SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(getContext());
|
||||
@@ -5470,14 +5471,22 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// Transaction to hide the task to avoid flicker for entering PiP from
|
||||
// split-screen.
|
||||
// See also {@link AbsSwipeUpHandler#maybeFinishSwipeToHome}.
|
||||
PictureInPictureSurfaceTransaction tx = new PictureInPictureSurfaceTransaction.Builder()
|
||||
.setAlpha(0f)
|
||||
.build();
|
||||
tx.setShouldDisableCanAffectSystemUiFlags(false);
|
||||
int[] taskIds = TopTaskTracker.INSTANCE.get(getContext()).getRunningSplitTaskIds();
|
||||
for (int taskId : taskIds) {
|
||||
mRecentsAnimationController.setFinishTaskTransaction(taskId,
|
||||
tx, null /* overlay */);
|
||||
try {
|
||||
PictureInPictureSurfaceTransaction tx = new PictureInPictureSurfaceTransaction.Builder()
|
||||
.setAlpha(0f)
|
||||
.build();
|
||||
try {
|
||||
tx.setShouldDisableCanAffectSystemUiFlags(false);
|
||||
} catch (NoSuchMethodError n) {
|
||||
Log.w(TAG, "not Android 13 qpr1 : ", n);
|
||||
}
|
||||
int[] taskIds = TopTaskTracker.INSTANCE.get(getContext()).getRunningSplitTaskIds();
|
||||
for (int taskId : taskIds) {
|
||||
mRecentsAnimationController.setFinishTaskTransaction(taskId,
|
||||
tx, null /* overlay */);
|
||||
}
|
||||
} catch (Throwable error) {
|
||||
Log.w(TAG, "Failed PictureInPictureSurfaceTransaction: ", error);
|
||||
}
|
||||
}
|
||||
mRecentsAnimationController.finish(toRecents, () -> {
|
||||
|
||||
@@ -122,6 +122,8 @@ import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
/**
|
||||
* A task in the Recents view.
|
||||
*/
|
||||
@@ -830,6 +832,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
* second app. {@code false} otherwise
|
||||
*/
|
||||
protected boolean confirmSecondSplitSelectApp() {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_T) return false;
|
||||
int index = getLastSelectedChildTaskIndex();
|
||||
TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
|
||||
if (container != null) {
|
||||
@@ -936,20 +939,25 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
}
|
||||
// Indicate success once the system has indicated that the transition has
|
||||
// started
|
||||
ActivityOptions opts = ActivityOptions.makeCustomTaskAnimation(getContext(), 0, 0,
|
||||
ActivityOptions opts = LawnchairQuickstepCompat.ATLEAST_T ? ActivityOptions.makeCustomTaskAnimation(getContext(), 0, 0,
|
||||
MAIN_EXECUTOR.getHandler(),
|
||||
elapsedRealTime -> {
|
||||
callback.accept(true);
|
||||
},
|
||||
elapsedRealTime -> {
|
||||
failureListener.onTransitionFinished();
|
||||
});
|
||||
}) : makeCustomAnimation(getContext(), 0, 0,
|
||||
() -> callback.accept(true), MAIN_EXECUTOR.getHandler());;
|
||||
opts.setLaunchDisplayId(
|
||||
getDisplay() == null ? DEFAULT_DISPLAY : getDisplay().getDisplayId());
|
||||
if (isQuickswitch) {
|
||||
opts.setFreezeRecentTasksReordering();
|
||||
}
|
||||
opts.setDisableStartingWindow(mSnapshotView.shouldShowSplashView());
|
||||
try {
|
||||
opts.setDisableStartingWindow(mSnapshotView.shouldShowSplashView());
|
||||
} catch (Throwable t) {
|
||||
// ignore
|
||||
}
|
||||
Task.TaskKey key = mTask.key;
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
if (!ActivityManagerWrapper.getInstance().startActivityFromRecents(key, opts)) {
|
||||
@@ -972,6 +980,9 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
*/
|
||||
private ActivityOptions makeCustomAnimation(Context context, int enterResId,
|
||||
int exitResId, final Runnable callback, final Handler callbackHandler) {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_T) {
|
||||
return LawnchairQuickstepCompat.getActivityOptionsCompat().makeCustomAnimation(context, enterResId, exitResId, callback, callbackHandler);
|
||||
}
|
||||
return ActivityOptions.makeCustomTaskAnimation(context, enterResId, exitResId,
|
||||
callbackHandler,
|
||||
elapsedRealTime -> {
|
||||
|
||||
+7
-2
@@ -58,7 +58,12 @@ include ':systemUILog'
|
||||
include ':systemUIAnim'
|
||||
include ':systemUnFold'
|
||||
include ':systemUIViewCapture'
|
||||
|
||||
include ':compatLib'
|
||||
include ':compatLibVR'
|
||||
include ':compatLibVS'
|
||||
include ':compatLib:compatLibVQ'
|
||||
include ':compatLib:compatLibVR'
|
||||
include ':compatLib:compatLibVS'
|
||||
include ':compatLib:compatLibVT'
|
||||
include ':compatLib:compatLibVU'
|
||||
|
||||
include ':baseline-profile'
|
||||
@@ -1495,7 +1495,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
final Rect mPadding = new Rect();
|
||||
AllAppsRecyclerView mRecyclerView;
|
||||
|
||||
AdapterHolder(int type, LawnchairAlphabeticalAppsList<T> appsList) {
|
||||
AdapterHolder(int type, AlphabeticalAppsList<T> appsList) {
|
||||
mType = type;
|
||||
mAppsList = appsList;
|
||||
mAdapter = createAdapter(mAppsList);
|
||||
|
||||
@@ -99,8 +99,6 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
|
||||
var textColor = ColorTokens.ColorPrimary.resolveColor(getContext());
|
||||
mIcon.setColorFilter(textColor);
|
||||
mTextView.setTextColor(textColor);
|
||||
DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
|
||||
setInsets(grid.getInsets());
|
||||
setInsets(mActivityContext.getDeviceProfile().getInsets());
|
||||
mTextView.setText(R.string.work_apps_pause_btn_text);
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
|
||||
* Draw the top and bottom scrims
|
||||
*/
|
||||
public void draw(Canvas canvas) {
|
||||
if (canvas == null) return;
|
||||
if (!mHideSysUiScrim) {
|
||||
if (mSysUiProgress.value <= 0) {
|
||||
mAnimateScrimOnNextDraw = false;
|
||||
@@ -156,10 +157,10 @@ public class SysUiScrim implements View.OnAttachStateChangeListener {
|
||||
mAnimateScrimOnNextDraw = false;
|
||||
}
|
||||
|
||||
if (mDrawTopScrim) {
|
||||
if (mDrawTopScrim && mTopMaskBitmap != null) {
|
||||
canvas.drawBitmap(mTopMaskBitmap, null, mTopMaskRect, mTopMaskPaint);
|
||||
}
|
||||
if (mDrawBottomScrim) {
|
||||
if (mDrawBottomScrim && mBottomMaskBitmap != null) {
|
||||
canvas.drawBitmap(mBottomMaskBitmap, null, mBottomMaskRect, mBottomMaskPaint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
@@ -238,7 +239,7 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
|
||||
}
|
||||
return;
|
||||
} else if ((!mConfig.userControlled && animated && mConfig.targetState == state)
|
||||
|| mState.shouldPreserveDataStateOnReapply()) {
|
||||
|| (mState.shouldPreserveDataStateOnReapply() && Utilities.ATLEAST_U)) {
|
||||
// We are running the same animation as requested, and/or target state should not be
|
||||
// reset -- allow the current animation to complete instead of canceling it.
|
||||
if (listener != null) {
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.graphics.Matrix
|
||||
import android.graphics.Path
|
||||
import android.graphics.Rect
|
||||
import android.graphics.RectF
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.os.RemoteException
|
||||
@@ -523,6 +522,10 @@ class ActivityLaunchAnimator(
|
||||
}
|
||||
}
|
||||
|
||||
fun onAnimationCancelled(isKeyguardOccluded: Boolean) {
|
||||
onAnimationCancelled()
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
override fun onAnimationCancelled() {
|
||||
val delegate = delegate
|
||||
@@ -686,11 +689,12 @@ class ActivityLaunchAnimator(
|
||||
// instead of recomputing isExpandingFullyAbove here.
|
||||
val isExpandingFullyAbove =
|
||||
launchAnimator.isExpandingFullyAbove(controller.launchContainer, endState)
|
||||
val windowCornerRadius = getWindowCornerRadius()
|
||||
val endRadius =
|
||||
if (isExpandingFullyAbove) {
|
||||
// Most of the time, expanding fully above the root view means expanding in full
|
||||
// screen.
|
||||
ScreenDecorationsUtils.getWindowCornerRadius(context)
|
||||
windowCornerRadius
|
||||
} else {
|
||||
// This usually means we are in split screen mode, so 2 out of 4 corners will
|
||||
// have
|
||||
@@ -758,6 +762,15 @@ class ActivityLaunchAnimator(
|
||||
)
|
||||
}
|
||||
|
||||
private fun getWindowCornerRadius() : Float {
|
||||
return try {
|
||||
ScreenDecorationsUtils.getWindowCornerRadius(context)
|
||||
} catch (t: Throwable) {
|
||||
0f
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun applyStateToWindow(
|
||||
window: RemoteAnimationTarget,
|
||||
state: LaunchAnimator.State,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.android.systemui.animation
|
||||
|
||||
import android.os.Build
|
||||
import android.view.View
|
||||
import android.window.SurfaceSyncGroup
|
||||
|
||||
@@ -28,11 +29,13 @@ object ViewRootSync {
|
||||
return
|
||||
}
|
||||
|
||||
val syncGroup = SurfaceSyncGroup("SysUIAnimation")
|
||||
syncGroup.addSyncCompleteCallback(view.context.mainExecutor) { then() }
|
||||
syncGroup.add(view.rootSurfaceControl, null /* runnable */)
|
||||
syncGroup.add(otherView.rootSurfaceControl, null /* runnable */)
|
||||
syncGroup.markSyncReady()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
val syncGroup = SurfaceSyncGroup("SysUIAnimation")
|
||||
syncGroup.addSyncCompleteCallback(view.context.mainExecutor) { then() }
|
||||
syncGroup.add(view.rootSurfaceControl, null /* runnable */)
|
||||
syncGroup.add(otherView.rootSurfaceControl, null /* runnable */)
|
||||
syncGroup.markSyncReady()
|
||||
}
|
||||
}
|
||||
|
||||
/** A Java-friendly API for [synchronizeNextDraw]. */
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package app.lawnchair.compat
|
||||
|
||||
import android.os.Build
|
||||
import app.lawnchair.compatlib.ActivityManagerCompat
|
||||
import app.lawnchair.compatlib.ActivityOptionsCompat
|
||||
import app.lawnchair.compatlib.QuickstepCompatFactory
|
||||
import app.lawnchair.compatlib.RemoteTransitionCompat
|
||||
import app.lawnchair.compatlib.eleven.QuickstepCompatFactoryVR
|
||||
import app.lawnchair.compatlib.fourteen.QuickstepCompatFactoryVU
|
||||
import app.lawnchair.compatlib.ten.QuickstepCompatFactoryVQ
|
||||
import app.lawnchair.compatlib.thirteen.QuickstepCompatFactoryVT
|
||||
import app.lawnchair.compatlib.twelve.QuickstepCompatFactoryVS
|
||||
|
||||
object LawnchairQuickstepCompat {
|
||||
|
||||
@JvmField
|
||||
val ATLEAST_Q: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
|
||||
|
||||
@JvmField
|
||||
val ATLEAST_R: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||
|
||||
@JvmField
|
||||
val ATLEAST_S: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
|
||||
|
||||
@JvmField
|
||||
val ATLEAST_T: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
|
||||
|
||||
@JvmField
|
||||
val ATLEAST_U: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
|
||||
|
||||
|
||||
@JvmStatic
|
||||
val factory: QuickstepCompatFactory = if (ATLEAST_U) {
|
||||
QuickstepCompatFactoryVU()
|
||||
} else if (ATLEAST_T) {
|
||||
QuickstepCompatFactoryVT()
|
||||
} else if (ATLEAST_S) {
|
||||
QuickstepCompatFactoryVS()
|
||||
} else if (ATLEAST_R) {
|
||||
QuickstepCompatFactoryVR()
|
||||
} else {
|
||||
QuickstepCompatFactoryVQ()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val activityManagerCompat: ActivityManagerCompat = factory.activityManagerCompat
|
||||
|
||||
@JvmStatic
|
||||
val activityOptionsCompat: ActivityOptionsCompat = factory.activityOptionsCompat
|
||||
|
||||
@JvmStatic
|
||||
val remoteTransitionCompat: RemoteTransitionCompat = factory.remoteTransitionCompat
|
||||
}
|
||||
@@ -61,6 +61,16 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
oneway void onAssistantGestureCompletion(float velocity) = 18;
|
||||
|
||||
/**
|
||||
* Get the secondary split screen app's rectangle when not minimized.
|
||||
*/
|
||||
Rect getNonMinimizedSplitScreenSecondaryBounds() = 7;
|
||||
|
||||
/**
|
||||
* Creates a new gesture monitor
|
||||
*/
|
||||
Bundle monitorGestureInput(String name, int displayId) = 14;
|
||||
|
||||
/**
|
||||
* Start the assistant.
|
||||
*/
|
||||
@@ -90,6 +100,28 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
oneway void stopScreenPinning() = 17;
|
||||
|
||||
/**
|
||||
* Handle the provided image as if it was a screenshot.
|
||||
*
|
||||
* Deprecated, use handleImageBundleAsScreenshot with image bundle and UserTask
|
||||
* @deprecated
|
||||
*/
|
||||
void handleImageAsScreenshot(in Bitmap screenImage, in Rect locationInScreen,
|
||||
in Insets visibleInsets, int taskId) = 21;
|
||||
|
||||
/**
|
||||
* Sets the split-screen divider minimized state
|
||||
*/
|
||||
void setSplitScreenMinimized(boolean minimized) = 22;
|
||||
|
||||
/*
|
||||
* Notifies that the swipe-to-home (recents animation) is finished.
|
||||
*/
|
||||
void notifySwipeToHomeFinished() = 23;
|
||||
|
||||
/** Notifies that a swipe-up gesture has started */
|
||||
void notifySwipeUpGestureStarted() = 46;
|
||||
|
||||
/**
|
||||
* Notifies that quickstep will switch to a new task
|
||||
* @param rotation indicates which Surface.Rotation the gesture was started in
|
||||
@@ -134,6 +166,12 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
oneway void takeScreenshot(in ScreenshotRequest request) = 51;
|
||||
|
||||
/**
|
||||
* Handle the provided image as if it was a screenshot.
|
||||
*/
|
||||
void handleImageBundleAsScreenshot(in Bundle screenImageBundle, in Rect locationInScreen,
|
||||
in Insets visibleInsets, in Task.TaskKey task) = 26;
|
||||
|
||||
/**
|
||||
* Dispatches trackpad status bar motion event to the notification shade. Currently these events
|
||||
* are from the input monitor in {@link TouchInteractionService}. This is different from
|
||||
|
||||
Loaded 100 of 111 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user