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,