diff --git a/CompatLib/.gitignore b/CompatLib/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/CompatLib/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/CompatLib/build.gradle b/CompatLib/build.gradle
new file mode 100644
index 0000000000..24cd490fde
--- /dev/null
+++ b/CompatLib/build.gradle
@@ -0,0 +1,36 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk 31
+
+ defaultConfig {
+ minSdk 28
+ targetSdk 31
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ addFrameworkJar('framework-12.jar')
+}
+
+dependencies {
+ implementation 'androidx.core:core-ktx:1.6.0'
+}
diff --git a/CompatLib/consumer-rules.pro b/CompatLib/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/CompatLib/proguard-rules.pro b/CompatLib/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/CompatLib/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/CompatLib/src/main/AndroidManifest.xml b/CompatLib/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..da3d364cbc
--- /dev/null
+++ b/CompatLib/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/CompatLib/src/main/java/app/lawnchair/compatlib/ActivityManagerCompat.java b/CompatLib/src/main/java/app/lawnchair/compatlib/ActivityManagerCompat.java
new file mode 100644
index 0000000000..6f7881d2b8
--- /dev/null
+++ b/CompatLib/src/main/java/app/lawnchair/compatlib/ActivityManagerCompat.java
@@ -0,0 +1,17 @@
+package app.lawnchair.compatlib;
+
+import android.app.ActivityManager;
+import android.content.Intent;
+import android.os.RemoteException;
+import android.view.IRecentsAnimationRunner;
+
+import java.util.List;
+
+public abstract class ActivityManagerCompat {
+
+ public abstract void startRecentsActivity(Intent intent, long eventTime, RecentsAnimationRunnerStub runner) throws RemoteException;
+
+ public abstract ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents);
+
+ public abstract List getRecentTasks(int numTasks, int userId);
+}
diff --git a/CompatLib/src/main/java/app/lawnchair/compatlib/QuickstepCompatFactory.java b/CompatLib/src/main/java/app/lawnchair/compatlib/QuickstepCompatFactory.java
new file mode 100644
index 0000000000..51c263a6b4
--- /dev/null
+++ b/CompatLib/src/main/java/app/lawnchair/compatlib/QuickstepCompatFactory.java
@@ -0,0 +1,18 @@
+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 {
+
+ @NonNull
+ public abstract ActivityManagerCompat getActivityManagerCompat();
+
+ public abstract IRemoteAnimationRunner.Stub wrapRemoteAnimationRunnerStub(RemoteAnimationRunnerStub compatStub);
+
+ public abstract AppTransitionAnimationSpec createAppTransitionAnimationSpec(int taskId, Bitmap buffer, Rect rect);
+}
diff --git a/CompatLib/src/main/java/app/lawnchair/compatlib/RecentsAnimationRunnerStub.java b/CompatLib/src/main/java/app/lawnchair/compatlib/RecentsAnimationRunnerStub.java
new file mode 100644
index 0000000000..ef05ee2580
--- /dev/null
+++ b/CompatLib/src/main/java/app/lawnchair/compatlib/RecentsAnimationRunnerStub.java
@@ -0,0 +1,15 @@
+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);
+}
diff --git a/CompatLib/src/main/java/app/lawnchair/compatlib/RemoteAnimationRunnerStub.java b/CompatLib/src/main/java/app/lawnchair/compatlib/RemoteAnimationRunnerStub.java
new file mode 100644
index 0000000000..fc513389cb
--- /dev/null
+++ b/CompatLib/src/main/java/app/lawnchair/compatlib/RemoteAnimationRunnerStub.java
@@ -0,0 +1,13 @@
+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();
+}
diff --git a/CompatLib/src/main/java/app/lawnchair/compatlib/RemoteTransitionStub.java b/CompatLib/src/main/java/app/lawnchair/compatlib/RemoteTransitionStub.java
new file mode 100644
index 0000000000..6f96e17e32
--- /dev/null
+++ b/CompatLib/src/main/java/app/lawnchair/compatlib/RemoteTransitionStub.java
@@ -0,0 +1,31 @@
+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);
+}
diff --git a/CompatLib/src/main/java/app/lawnchair/compatlib/TaskSnapshotCompat.java b/CompatLib/src/main/java/app/lawnchair/compatlib/TaskSnapshotCompat.java
new file mode 100644
index 0000000000..9e758fc79c
--- /dev/null
+++ b/CompatLib/src/main/java/app/lawnchair/compatlib/TaskSnapshotCompat.java
@@ -0,0 +1,4 @@
+package app.lawnchair.compatlib;
+
+public class TaskSnapshotCompat {
+}
diff --git a/CompatLibVR/.gitignore b/CompatLibVR/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/CompatLibVR/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/CompatLibVR/build.gradle b/CompatLibVR/build.gradle
new file mode 100644
index 0000000000..1d6b399f9c
--- /dev/null
+++ b/CompatLibVR/build.gradle
@@ -0,0 +1,37 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk 30
+
+ defaultConfig {
+ minSdk 28
+ targetSdk 31
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ addFrameworkJar('framework-11.jar')
+}
+
+dependencies {
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation project(':CompatLib')
+}
\ No newline at end of file
diff --git a/CompatLibVR/consumer-rules.pro b/CompatLibVR/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/CompatLibVR/proguard-rules.pro b/CompatLibVR/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/CompatLibVR/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/CompatLibVR/src/main/AndroidManifest.xml b/CompatLibVR/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e65e490ae0
--- /dev/null
+++ b/CompatLibVR/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/CompatLibVR/src/main/java/app/lawnchair/compatlib/eleven/ActivityManagerCompatVR.java b/CompatLibVR/src/main/java/app/lawnchair/compatlib/eleven/ActivityManagerCompatVR.java
new file mode 100644
index 0000000000..48ca61758c
--- /dev/null
+++ b/CompatLibVR/src/main/java/app/lawnchair/compatlib/eleven/ActivityManagerCompatVR.java
@@ -0,0 +1,158 @@
+package app.lawnchair.compatlib.eleven;
+
+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.ActivityManager;
+import android.app.ActivityTaskManager;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.GraphicBuffer;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.hardware.HardwareBuffer;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.IRecentsAnimationController;
+import android.view.IRecentsAnimationRunner;
+import android.view.RemoteAnimationTarget;
+
+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);
+ }
+
+ @Override
+ public void onAnimationCanceled(ActivityManager.TaskSnapshot taskSnapshot) {
+ runner.onAnimationCanceled(taskSnapshot);
+ }
+
+ @Override
+ public void onTaskAppeared(RemoteAnimationTarget app) {
+ runner.onTaskAppeared(app);
+ }
+ };
+ }
+ getService().startRecentsActivity(intent, null, wrappedRunner);
+ }
+
+ @Override
+ public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
+ // Note: The set of running tasks from the system is ordered by recency
+ try {
+ List tasks =
+ ActivityTaskManager.getService().getFilteredTasks(1, filterOnlyVisibleRecents);
+ if (tasks.isEmpty()) {
+ return null;
+ }
+ return tasks.get(0);
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public List getRecentTasks(int numTasks, int userId) {
+ try {
+ 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<>();
+ }
+ }
+
+ public ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
+ ActivityManager.TaskSnapshot snapshot = null;
+ try {
+ snapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to retrieve task snapshot", e);
+ }
+ if (snapshot != null) {
+ return makeThumbnailData(snapshot);
+ } else {
+ return null;
+ }
+ }
+
+ public ThumbnailData takeScreenshot(IRecentsAnimationController animationController, int taskId) {
+ try {
+ ActivityManager.TaskSnapshot snapshot = animationController.screenshotTask(taskId);
+ return snapshot != null ? makeThumbnailData(snapshot) : new ThumbnailData();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to screenshot task", e);
+ return new ThumbnailData();
+ }
+ }
+
+ public ThumbnailData makeThumbnailData(ActivityManager.TaskSnapshot snapshot) {
+ ThumbnailData data = new ThumbnailData();
+ 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);
+ Point taskSize = snapshot.getTaskSize();
+ data.thumbnail = Bitmap.createBitmap(taskSize.x, taskSize.y, ARGB_8888);
+ data.thumbnail.eraseColor(Color.BLACK);
+ } else {
+ data.thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
+ }
+ data.insets = new Rect(snapshot.getContentInsets());
+ data.orientation = snapshot.getOrientation();
+ data.rotation = snapshot.getRotation();
+ data.reducedResolution = snapshot.isLowResolution();
+ // 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 = (float) data.thumbnail.getWidth() / snapshot.getTaskSize().x;
+ data.isRealSnapshot = snapshot.isRealSnapshot();
+ data.isTranslucent = snapshot.isTranslucent();
+ data.windowingMode = snapshot.getWindowingMode();
+ data.systemUiVisibility = snapshot.getSystemUiVisibility();
+ data.snapshotId = snapshot.getId();
+ return data;
+ }
+
+ public ThumbnailData convertTaskSnapshotToThumbnailData(Object taskSnapshot) {
+ if (taskSnapshot != null) {
+ return makeThumbnailData((ActivityManager.TaskSnapshot) taskSnapshot);
+ } else {
+ return null;
+ }
+ }
+
+ public static class ThumbnailData {
+
+ public Bitmap thumbnail;
+ public int orientation;
+ public int rotation;
+ public Rect insets;
+ public boolean reducedResolution;
+ public boolean isRealSnapshot;
+ public boolean isTranslucent;
+ public int windowingMode;
+ public int systemUiVisibility;
+ public float scale;
+ public long snapshotId;
+ }
+}
diff --git a/CompatLibVR/src/main/java/app/lawnchair/compatlib/eleven/QuickstepCompatFactoryVR.java b/CompatLibVR/src/main/java/app/lawnchair/compatlib/eleven/QuickstepCompatFactoryVR.java
new file mode 100644
index 0000000000..87dc7ef5ab
--- /dev/null
+++ b/CompatLibVR/src/main/java/app/lawnchair/compatlib/eleven/QuickstepCompatFactoryVR.java
@@ -0,0 +1,47 @@
+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);
+ }
+}
diff --git a/CompatLibVS/.gitignore b/CompatLibVS/.gitignore
new file mode 100644
index 0000000000..42afabfd2a
--- /dev/null
+++ b/CompatLibVS/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/CompatLibVS/build.gradle b/CompatLibVS/build.gradle
new file mode 100644
index 0000000000..b8d66d380b
--- /dev/null
+++ b/CompatLibVS/build.gradle
@@ -0,0 +1,37 @@
+plugins {
+ id 'com.android.library'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ compileSdk 31
+
+ defaultConfig {
+ minSdk 28
+ targetSdk 31
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles "consumer-rules.pro"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ addFrameworkJar('framework-12.jar')
+}
+
+dependencies {
+ implementation 'androidx.core:core-ktx:1.6.0'
+ implementation project(':CompatLib')
+}
\ No newline at end of file
diff --git a/CompatLibVS/consumer-rules.pro b/CompatLibVS/consumer-rules.pro
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/CompatLibVS/proguard-rules.pro b/CompatLibVS/proguard-rules.pro
new file mode 100644
index 0000000000..481bb43481
--- /dev/null
+++ b/CompatLibVS/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/CompatLibVS/src/main/AndroidManifest.xml b/CompatLibVS/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..e2ed8d4db5
--- /dev/null
+++ b/CompatLibVS/src/main/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/CompatLibVS/src/main/java/app/lawnchair/compatlib/twelve/ActivityManagerCompatVS.java b/CompatLibVS/src/main/java/app/lawnchair/compatlib/twelve/ActivityManagerCompatVS.java
new file mode 100644
index 0000000000..6b8e0e0824
--- /dev/null
+++ b/CompatLibVS/src/main/java/app/lawnchair/compatlib/twelve/ActivityManagerCompatVS.java
@@ -0,0 +1,66 @@
+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 tasks =
+ mAtm.getTasks(1, filterOnlyVisibleRecents);
+ if (tasks.isEmpty()) {
+ return null;
+ }
+ return tasks.get(0);
+ }
+
+ @Override
+ public List getRecentTasks(int numTasks, int userId) {
+ return mAtm.getRecentTasks(numTasks, RECENT_IGNORE_UNAVAILABLE, userId);
+ }
+}
diff --git a/CompatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java b/CompatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java
new file mode 100644
index 0000000000..d55ef55396
--- /dev/null
+++ b/CompatLibVS/src/main/java/app/lawnchair/compatlib/twelve/QuickstepCompatFactoryVS.java
@@ -0,0 +1,55 @@
+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);
+ }
+}
diff --git a/SystemUIShared/build.gradle b/SystemUIShared/build.gradle
index 77f5ec7faa..871874663f 100644
--- a/SystemUIShared/build.gradle
+++ b/SystemUIShared/build.gradle
@@ -38,10 +38,13 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
- addFrameworkJar('framework.jar')
+ addFrameworkJar('framework-12.jar')
}
dependencies {
compileOnly fileTree(dir: new File(rootProject.projectDir, 'prebuilts/libs'), include: 'wm_shell-aidls.jar')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation project(':CompatLib')
+ implementation project(':CompatLibVR')
+ implementation project(':CompatLibVS')
}
diff --git a/SystemUIShared/src/com/android/systemui/shared/QuickstepCompat.java b/SystemUIShared/src/com/android/systemui/shared/QuickstepCompat.java
new file mode 100644
index 0000000000..2fba1f68c8
--- /dev/null
+++ b/SystemUIShared/src/com/android/systemui/shared/QuickstepCompat.java
@@ -0,0 +1,35 @@
+package com.android.systemui.shared;
+
+import android.annotation.SuppressLint;
+import android.os.Build;
+
+import app.lawnchair.compatlib.ActivityManagerCompat;
+import app.lawnchair.compatlib.QuickstepCompatFactory;
+import app.lawnchair.compatlib.eleven.QuickstepCompatFactoryVR;
+import app.lawnchair.compatlib.twelve.QuickstepCompatFactoryVS;
+
+public class QuickstepCompat {
+
+ private static final QuickstepCompatFactory sFactory;
+ private static final ActivityManagerCompat sActivityManagerCompat;
+
+ @SuppressLint("AnnotateVersionCheck")
+ public static final boolean ATLEAST_S = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
+
+ static {
+ if (ATLEAST_S) {
+ sFactory = new QuickstepCompatFactoryVS();
+ } else {
+ sFactory = new QuickstepCompatFactoryVR();
+ }
+ sActivityManagerCompat = sFactory.getActivityManagerCompat();
+ }
+
+ public static QuickstepCompatFactory getFactory() {
+ return sFactory;
+ }
+
+ public static ActivityManagerCompat getActivityManagerCompat() {
+ return sActivityManagerCompat;
+ }
+}
diff --git a/SystemUIShared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/SystemUIShared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index f72245b9b2..351941162d 100644
--- a/SystemUIShared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/SystemUIShared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -78,6 +78,11 @@ interface ISystemUiProxy {
*/
void startAssistant(in Bundle bundle) = 13;
+ /**
+ * Creates a new gesture monitor
+ */
+ Bundle monitorGestureInput(String name, int displayId) = 14;
+
/**
* Notifies that the accessibility button in the system's navigation area has been clicked
*/
diff --git a/SystemUIShared/src/com/android/systemui/shared/recents/model/Task.java b/SystemUIShared/src/com/android/systemui/shared/recents/model/Task.java
index e9e9b2421d..9bded27172 100644
--- a/SystemUIShared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/SystemUIShared/src/com/android/systemui/shared/recents/model/Task.java
@@ -30,6 +30,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.view.ViewDebug;
+import com.android.systemui.shared.QuickstepCompat;
import com.android.systemui.shared.recents.utilities.Utilities;
import java.io.PrintWriter;
@@ -228,8 +229,9 @@ public class Task {
public boolean isLocked;
// Last snapshot data, only used for recent tasks
- public ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
- new ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData();
+ public Object lastSnapshotData = QuickstepCompat.ATLEAST_S
+ ? new ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData()
+ : null;
public Task() {
// Do nothing
@@ -254,7 +256,10 @@ public class Task {
public Task(Task other) {
this(other.key, other.colorPrimary, other.colorBackground, other.isDockable,
other.isLocked, other.taskDescription, other.topActivity);
- lastSnapshotData.set(other.lastSnapshotData);
+ if (QuickstepCompat.ATLEAST_S) {
+ ((ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData) lastSnapshotData)
+ .set((ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData) other.lastSnapshotData);
+ }
}
/**
@@ -283,13 +288,18 @@ public class Task {
}
public void setLastSnapshotData(ActivityManager.RecentTaskInfo rawTask) {
- lastSnapshotData.set(rawTask.lastSnapshotData);
+ if (QuickstepCompat.ATLEAST_S) {
+ ((ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData) lastSnapshotData)
+ .set(rawTask.lastSnapshotData);
+ }
}
/**
* Returns the visible width to height ratio. Returns 0f if snapshot data is not available.
*/
public float getVisibleThumbnailRatio(boolean clipInsets) {
+ ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
+ (ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData) this.lastSnapshotData;
if (lastSnapshotData.taskSize == null || lastSnapshotData.contentInsets == null) {
return 0f;
}
diff --git a/SystemUIShared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/SystemUIShared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
index 6594d5f51a..bf9f723b59 100644
--- a/SystemUIShared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
+++ b/SystemUIShared/src/com/android/systemui/shared/recents/model/ThumbnailData.java
@@ -22,6 +22,7 @@ import static android.graphics.Bitmap.Config.ARGB_8888;
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
+import android.app.ActivityManager;
import android.window.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.Color;
@@ -31,6 +32,8 @@ import android.hardware.HardwareBuffer;
import android.util.Log;
import android.view.WindowInsetsController.Appearance;
+import app.lawnchair.compatlib.eleven.ActivityManagerCompatVR;
+
/**
* Data for a single thumbnail.
*/
@@ -95,4 +98,17 @@ public class ThumbnailData {
appearance = snapshot.getAppearance();
snapshotId = snapshot.getId();
}
+
+ public ThumbnailData(ActivityManagerCompatVR.ThumbnailData data) {
+ thumbnail = data.thumbnail;
+ insets = data.insets;
+ orientation = data.orientation;
+ rotation = data.rotation;
+ reducedResolution = data.reducedResolution;
+ scale = data.scale;
+ isRealSnapshot = data.isRealSnapshot;
+ isTranslucent = data.isTranslucent;
+ windowingMode = data.windowingMode;
+ snapshotId = data.snapshotId;
+ }
}
diff --git a/SystemUIShared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java b/SystemUIShared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java
index a6fdfc43a1..7c135b802e 100644
--- a/SystemUIShared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/recents/view/AppTransitionAnimationSpecCompat.java
@@ -19,6 +19,8 @@ import android.graphics.Bitmap;
import android.graphics.Rect;
import android.view.AppTransitionAnimationSpec;
+import com.android.systemui.shared.QuickstepCompat;
+
/**
* Wraps the internal app transition animation spec.
*/
@@ -35,7 +37,6 @@ public class AppTransitionAnimationSpecCompat {
}
public AppTransitionAnimationSpec toAppTransitionAnimationSpec() {
- return new AppTransitionAnimationSpec(mTaskId,
- mBuffer != null ? mBuffer.getHardwareBuffer() : null, mRect);
+ return QuickstepCompat.getFactory().createAppTransitionAnimationSpec(mTaskId, mBuffer, mRect);
}
}
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/SystemUIShared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index a4c8462c83..d3e43c5387 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -53,12 +53,19 @@ import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.systemui.shared.QuickstepCompat;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.recents.utilities.Utilities;
+import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
+import app.lawnchair.compatlib.ActivityManagerCompat;
+import app.lawnchair.compatlib.RecentsAnimationRunnerStub;
+import app.lawnchair.compatlib.eleven.ActivityManagerCompatVR;
+
public class ActivityManagerWrapper {
private static final String TAG = "ActivityManagerWrapper";
@@ -73,7 +80,6 @@ public class ActivityManagerWrapper {
private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
private static final boolean ATLEAST_S = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
- private final ActivityTaskManager mAtm = ATLEAST_S ? ActivityTaskManager.getInstance() : null;
private ActivityManagerWrapper() { }
public static ActivityManagerWrapper getInstance() {
@@ -105,26 +111,29 @@ public class ActivityManagerWrapper {
* list (can be {@code null}).
*/
public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
- // Note: The set of running tasks from the system is ordered by recency
- List tasks =
- mAtm.getTasks(1, filterOnlyVisibleRecents);
- if (tasks.isEmpty()) {
- return null;
- }
- return tasks.get(0);
+ return QuickstepCompat.getActivityManagerCompat().getRunningTask(filterOnlyVisibleRecents);
}
/**
* @return a list of the recents tasks.
*/
public List getRecentTasks(int numTasks, int userId) {
- return mAtm.getRecentTasks(numTasks, RECENT_IGNORE_UNAVAILABLE, userId);
+ return QuickstepCompat.getActivityManagerCompat().getRecentTasks(numTasks, userId);
}
/**
* @return the task snapshot for the given {@param taskId}.
*/
public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
+ if (!QuickstepCompat.ATLEAST_S) {
+ ActivityManagerCompatVR compat = ((ActivityManagerCompatVR) QuickstepCompat.getActivityManagerCompat());
+ ActivityManagerCompatVR.ThumbnailData data = compat.getTaskThumbnail(taskId, isLowResolution);
+ if (data != null) {
+ return new ThumbnailData(data);
+ } else {
+ return null;
+ }
+ }
TaskSnapshot snapshot = null;
try {
snapshot = getService().getTaskSnapshot(taskId, isLowResolution);
@@ -173,9 +182,9 @@ public class ActivityManagerWrapper {
public boolean startRecentsActivity(
Intent intent, long eventTime, RecentsAnimationListener animationHandler) {
try {
- IRecentsAnimationRunner runner = null;
+ RecentsAnimationRunnerStub runner = null;
if (animationHandler != null) {
- runner = new IRecentsAnimationRunner.Stub() {
+ runner = new RecentsAnimationRunnerStub() {
@Override
public void onAnimationStart(IRecentsAnimationController controller,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
@@ -191,9 +200,16 @@ public class ActivityManagerWrapper {
}
@Override
- public void onAnimationCanceled(TaskSnapshot taskSnapshot) {
- animationHandler.onAnimationCanceled(
- taskSnapshot != null ? new ThumbnailData(taskSnapshot) : null);
+ public void onAnimationCanceled(Object taskSnapshot) {
+ if (QuickstepCompat.ATLEAST_S) {
+ animationHandler.onAnimationCanceled(
+ taskSnapshot != null ? new ThumbnailData((TaskSnapshot) taskSnapshot) : null);
+ } else {
+ ActivityManagerCompatVR compat = (ActivityManagerCompatVR) QuickstepCompat.getActivityManagerCompat();
+ ActivityManagerCompatVR.ThumbnailData data = compat.convertTaskSnapshotToThumbnailData(taskSnapshot);
+ animationHandler.onAnimationCanceled(
+ data != null ? new ThumbnailData(data) : null);
+ }
}
@Override
@@ -202,7 +218,7 @@ public class ActivityManagerWrapper {
}
};
}
- getService().startRecentsActivity(intent, eventTime, runner);
+ QuickstepCompat.getActivityManagerCompat().startRecentsActivity(intent, eventTime, runner);
return true;
} catch (Exception e) {
return false;
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
index e8c7437869..f72bec11ff 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java
@@ -25,6 +25,7 @@ import android.content.Context;
import android.os.Build;
import android.os.Handler;
+import com.android.systemui.shared.QuickstepCompat;
import com.android.systemui.shared.recents.model.Task;
/**
@@ -61,8 +62,12 @@ public abstract class ActivityOptionsCompat {
public static ActivityOptions makeRemoteAnimation(
RemoteAnimationAdapterCompat remoteAnimationAdapter) {
- return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped(),
- remoteAnimationAdapter.getRemoteTransition().getTransition());
+ if (QuickstepCompat.ATLEAST_S) {
+ return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped(),
+ remoteAnimationAdapter.getRemoteTransition().getTransition());
+ } else {
+ return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped());
+ }
}
/**
@@ -78,6 +83,18 @@ public abstract class ActivityOptionsCompat {
*/
public static ActivityOptions makeCustomAnimation(Context context, int enterResId,
int exitResId, final Runnable callback, final Handler callbackHandler) {
+ if (!QuickstepCompat.ATLEAST_S) {
+ return ActivityOptions.makeCustomAnimation(context, enterResId, exitResId,
+ callbackHandler,
+ new ActivityOptions.OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ if (callback != null) {
+ callbackHandler.post(callback);
+ }
+ }
+ }, null /* finishedListener */);
+ }
return ActivityOptions.makeCustomTaskAnimation(context, enterResId, exitResId,
callbackHandler,
new ActivityOptions.OnAnimationStartedListener() {
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/InputChannelCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/InputChannelCompat.java
index 259cca8c01..b3d9e131ea 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/InputChannelCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/InputChannelCompat.java
@@ -24,6 +24,8 @@ import android.view.InputChannel;
import android.view.InputEvent;
import android.view.MotionEvent;
+import com.android.systemui.shared.QuickstepCompat;
+
/**
* @see android.view.InputChannel
*/
@@ -81,7 +83,9 @@ public class InputChannelCompat {
* @see BatchedInputEventReceiver#setBatchingEnabled()
*/
public void setBatchingEnabled(boolean batchingEnabled) {
- mReceiver.setBatchingEnabled(batchingEnabled);
+ if (QuickstepCompat.ATLEAST_S) {
+ mReceiver.setBatchingEnabled(batchingEnabled);
+ }
}
/**
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/InputMonitorCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/InputMonitorCompat.java
index bf8e6a5663..11e5bb79c1 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/InputMonitorCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/InputMonitorCompat.java
@@ -16,6 +16,7 @@
package com.android.systemui.shared.system;
import android.hardware.input.InputManager;
+import android.os.Bundle;
import android.os.Looper;
import android.view.Choreographer;
import android.view.InputMonitor;
@@ -33,7 +34,11 @@ public class InputMonitorCompat {
* Monitor input on the specified display for gestures.
*/
public InputMonitorCompat(String name, int displayId) {
- mInputMonitor = InputManager.getInstance().monitorGestureInput(name, displayId);
+ this(InputManager.getInstance().monitorGestureInput(name, displayId));
+ }
+
+ private InputMonitorCompat(InputMonitor monitor) {
+ mInputMonitor = monitor;
}
/**
@@ -58,4 +63,11 @@ public class InputMonitorCompat {
return new InputEventReceiver(mInputMonitor.getInputChannel(), looper, choreographer,
listener);
}
+
+ /**
+ * Gets the input monitor stored in a bundle
+ */
+ public static InputMonitorCompat fromBundle(Bundle bundle, String key) {
+ return new InputMonitorCompat((InputMonitor) bundle.getParcelable(key));
+ }
}
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java
index a8c19ec241..206cd41837 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java
@@ -19,6 +19,7 @@ package com.android.systemui.shared.system;
import android.content.Context;
import com.android.internal.util.LatencyTracker;
+import com.android.systemui.shared.QuickstepCompat;
/**
* @see LatencyTracker
@@ -30,11 +31,17 @@ public class LatencyTrackerCompat {
*/
@Deprecated
public static void logToggleRecents(int duration) {
+ if (!QuickstepCompat.ATLEAST_S) {
+ return;
+ }
LatencyTracker.logActionDeprecated(LatencyTracker.ACTION_TOGGLE_RECENTS, duration, false);
}
/** @see LatencyTracker */
public static void logToggleRecents(Context context, int duration) {
+ if (!QuickstepCompat.ATLEAST_S) {
+ return;
+ }
LatencyTracker.getInstance(context).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
duration);
}
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/QuickStepContract.java b/SystemUIShared/src/com/android/systemui/shared/system/QuickStepContract.java
index c468e416f8..2a79224134 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -41,6 +41,7 @@ public class QuickStepContract {
"com.google.android.apps.nexuslauncher.NexusLauncherActivity";
public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
+ public static final String KEY_EXTRA_INPUT_MONITOR = "extra_input_monitor";
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
// See IPip.aidl
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 8e65560f7c..994275c1a4 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -23,8 +23,11 @@ import android.view.SurfaceControl;
import android.window.PictureInPictureSurfaceTransaction;
import android.window.TaskSnapshot;
+import com.android.systemui.shared.QuickstepCompat;
import com.android.systemui.shared.recents.model.ThumbnailData;
+import app.lawnchair.compatlib.eleven.ActivityManagerCompatVR;
+
public class RecentsAnimationControllerCompat {
private static final String TAG = RecentsAnimationControllerCompat.class.getSimpleName();
@@ -38,6 +41,11 @@ public class RecentsAnimationControllerCompat {
}
public ThumbnailData screenshotTask(int taskId) {
+ if (!QuickstepCompat.ATLEAST_S) {
+ ActivityManagerCompatVR compat = (ActivityManagerCompatVR) QuickstepCompat.getActivityManagerCompat();
+ ActivityManagerCompatVR.ThumbnailData data = compat.takeScreenshot(mAnimationController, taskId);
+ return data != null ? new ThumbnailData(data) : new ThumbnailData();
+ }
try {
TaskSnapshot snapshot = mAnimationController.screenshotTask(taskId);
return snapshot != null ? new ThumbnailData(snapshot) : new ThumbnailData();
@@ -146,6 +154,7 @@ public class RecentsAnimationControllerCompat {
* @see IRecentsAnimationController#detachNavigationBarFromApp
*/
public void detachNavigationBarFromApp(boolean moveHomeToTop) {
+ if (!QuickstepCompat.ATLEAST_S) return;
try {
mAnimationController.detachNavigationBarFromApp(moveHomeToTop);
} catch (RemoteException e) {
@@ -157,6 +166,7 @@ public class RecentsAnimationControllerCompat {
* @see IRecentsAnimationController#animateNavigationBarToApp(long)
*/
public void animateNavigationBarToApp(long duration) {
+ if (!QuickstepCompat.ATLEAST_S) return;
try {
mAnimationController.animateNavigationBarToApp(duration);
} catch (RemoteException e) {
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
index ee55bf0aa8..0f27a41f96 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -39,21 +39,28 @@ import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
+import com.android.systemui.shared.QuickstepCompat;
+import com.android.systemui.shared.recents.utilities.Utilities;
+
import java.util.ArrayList;
+import app.lawnchair.compatlib.RemoteAnimationRunnerStub;
+
/**
* @see RemoteAnimationAdapter
*/
public class RemoteAnimationAdapterCompat {
private final RemoteAnimationAdapter mWrapped;
- private final RemoteTransitionCompat mRemoteTransition;
+ private RemoteTransitionCompat mRemoteTransition;
public RemoteAnimationAdapterCompat(RemoteAnimationRunnerCompat runner, long duration,
long statusBarTransitionDelay) {
mWrapped = new RemoteAnimationAdapter(wrapRemoteAnimationRunner(runner), duration,
statusBarTransitionDelay);
- mRemoteTransition = buildRemoteTransition(runner);
+ if (QuickstepCompat.ATLEAST_S) {
+ mRemoteTransition = buildRemoteTransition(runner);
+ }
}
RemoteAnimationAdapter getWrapped() {
@@ -71,7 +78,7 @@ public class RemoteAnimationAdapterCompat {
private static IRemoteAnimationRunner.Stub wrapRemoteAnimationRunner(
final RemoteAnimationRunnerCompat remoteAnimationAdapter) {
- return new IRemoteAnimationRunner.Stub() {
+ return QuickstepCompat.getFactory().wrapRemoteAnimationRunnerStub(new RemoteAnimationRunnerStub() {
@Override
public void onAnimationStart(@TransitionOldType int transit,
RemoteAnimationTarget[] apps,
@@ -103,7 +110,7 @@ public class RemoteAnimationAdapterCompat {
public void onAnimationCancelled() {
remoteAnimationAdapter.onAnimationCancelled();
}
- };
+ });
}
private static class CounterRotator {
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index 2407d216b4..8dd619d516 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -37,6 +37,8 @@ import android.view.SurfaceControl;
import android.view.WindowManager;
import android.window.TransitionInfo;
+import com.android.systemui.shared.QuickstepCompat;
+
import java.util.ArrayList;
/**
@@ -87,11 +89,11 @@ public class RemoteAnimationTargetCompat {
isNotInRecents = app.isNotInRecents;
contentInsets = app.contentInsets;
activityType = app.windowConfiguration.getActivityType();
- taskInfo = app.taskInfo;
+ taskInfo = QuickstepCompat.ATLEAST_S ? app.taskInfo : null;
rotationChange = 0;
mStartLeash = app.startLeash;
- windowType = app.windowType;
+ windowType = QuickstepCompat.ATLEAST_S ? app.windowType : INVALID_WINDOW_TYPE;
}
private static int newModeToLegacyMode(int newMode) {
diff --git a/SystemUIShared/src/com/android/systemui/shared/system/ViewRootImplCompat.java b/SystemUIShared/src/com/android/systemui/shared/system/ViewRootImplCompat.java
index 89c60f1d3f..ab0fac52a0 100644
--- a/SystemUIShared/src/com/android/systemui/shared/system/ViewRootImplCompat.java
+++ b/SystemUIShared/src/com/android/systemui/shared/system/ViewRootImplCompat.java
@@ -20,6 +20,8 @@ import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewRootImpl;
+import com.android.systemui.shared.QuickstepCompat;
+
import java.util.function.LongConsumer;
/**
@@ -58,7 +60,7 @@ public class ViewRootImplCompat {
}
public void mergeWithNextTransaction(SurfaceControl.Transaction t, long frame) {
- if (mViewRoot != null) {
+ if (QuickstepCompat.ATLEAST_S && mViewRoot != null) {
mViewRoot.mergeWithNextTransaction(t, frame);
} else {
t.apply();
diff --git a/build.gradle b/build.gradle
index 1ce7cb67bb..f935608ba3 100644
--- a/build.gradle
+++ b/build.gradle
@@ -241,7 +241,7 @@ android {
}
}
- addFrameworkJar('framework.jar')
+ addFrameworkJar('framework-12.jar')
}
allprojects {
diff --git a/lawnchair/AndroidManifest.xml b/lawnchair/AndroidManifest.xml
index ce3196fa57..7ec89afae2 100644
--- a/lawnchair/AndroidManifest.xml
+++ b/lawnchair/AndroidManifest.xml
@@ -59,7 +59,7 @@
+ android:value="30" />
,
? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId())
: null;
final ArrayList cookies = runningTaskTarget != null
+ && runningTaskTarget.taskInfo != null
? runningTaskTarget.taskInfo.launchCookies
: new ArrayList<>();
boolean isTranslucent = runningTaskTarget != null && runningTaskTarget.isTranslucent;
boolean appCanEnterPip = !mDeviceState.isPipActive()
&& runningTaskTarget != null
+ && runningTaskTarget.taskInfo != null
&& runningTaskTarget.taskInfo.pictureInPictureParams != null
&& runningTaskTarget.taskInfo.pictureInPictureParams.isAutoEnterEnabled();
HomeAnimationFactory homeAnimFactory =
@@ -1391,6 +1395,17 @@ public abstract class AbsSwipeUpHandler,
@UiThread
private void startNewTask() {
TaskView taskToLaunch = mRecentsView == null ? null : mRecentsView.getNextPageTaskView();
+ if (CompatibilityKt.isOnePlusStock()) {
+ reset();
+ if (mRecentsAnimationController != null) {
+ mRecentsAnimationController.finish(true, () -> startNewTaskInternal(taskToLaunch));
+ }
+ } else {
+ startNewTaskInternal(taskToLaunch);
+ }
+ }
+
+ private void startNewTaskInternal(TaskView taskToLaunch) {
startNewTask(success -> {
if (!success) {
reset();
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index 9dfcd12dde..589d4436d9 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -51,6 +51,7 @@ import com.android.launcher3.LauncherAnimationRunner;
import com.android.launcher3.LauncherAnimationRunner.AnimationResult;
import com.android.launcher3.LauncherAnimationRunner.RemoteAnimationFactory;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
@@ -232,7 +233,9 @@ public final class RecentsActivity extends StatefulActivity {
final ActivityOptionsWrapper activityOptions = new ActivityOptionsWrapper(
ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
onEndCallback);
- activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ if (Utilities.ATLEAST_S) {
+ activityOptions.options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+ }
return activityOptions;
}
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 2f85b853f4..6491beaaae 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -228,7 +228,7 @@ public class RecentsAnimationDeviceState implements
}
try {
- mPipIsActive = ActivityTaskManager.getService().getRootTaskInfo(
+ mPipIsActive = Utilities.ATLEAST_S && ActivityTaskManager.getService().getRootTaskInfo(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED) != null;
} catch (RemoteException e) {
// Do nothing
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index d040904f98..44c568d753 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -296,6 +296,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) {
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index a078bf331e..a0fcfe9002 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -35,6 +35,7 @@ import android.window.SplashScreen;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
import com.android.launcher3.model.WellbeingModel;
@@ -166,7 +167,7 @@ public interface TaskShortcutFactory {
dismissTaskMenuView(mTarget);
ActivityOptions options = mFactory.makeLaunchOptions(mTarget);
- if (options != null) {
+ if (options != null && Utilities.ATLEAST_S) {
options.setSplashscreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
}
if (options != null
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index db5c93c503..3e30a941c2 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -25,6 +25,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.quickstep.GestureState.DEFAULT_STATE;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
+import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_ONE_HANDED;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_PIP;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS;
@@ -359,7 +360,16 @@ public class TouchInteractionService extends Service implements PluginListener
-
+
diff --git a/res/color/overview_scrim_dark.xml b/res/color/overview_scrim_dark.xml
index 48cf5763a1..253bc1886e 100644
--- a/res/color/overview_scrim_dark.xml
+++ b/res/color/overview_scrim_dark.xml
@@ -14,5 +14,5 @@
limitations under the License.
-->
-
+
diff --git a/settings.gradle b/settings.gradle
index ee169f821c..fc30852ccc 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -4,3 +4,6 @@ project(':IconLoader').projectDir = new File(rootDir, 'platform_frameworks_libs_
include ':SharedLibWrapper'
project(':SharedLibWrapper').projectDir = new File(rootDir, 'SharedLibWrapper')
include ':SystemUIShared'
+include ':CompatLib'
+include ':CompatLibVR'
+include ':CompatLibVS'
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 618ce33cc6..704973a0f2 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -93,7 +93,7 @@ public final class FeatureFlags {
"ADAPTIVE_ICON_WINDOW_ANIM", true, "Use adaptive icons for window animations.");
public static final BooleanFlag ENABLE_QUICKSTEP_LIVE_TILE = getDebugFlag(
- "ENABLE_QUICKSTEP_LIVE_TILE", true, "Enable live tile in Quickstep overview");
+ "ENABLE_QUICKSTEP_LIVE_TILE", Utilities.ATLEAST_S, "Enable live tile in Quickstep overview");
public static final BooleanFlag ENABLE_QUICKSTEP_WIDGET_APP_START = getDebugFlag(
"ENABLE_QUICKSTEP_WIDGET_APP_START", Utilities.ATLEAST_S,