Commit 2f3850e5 authored by Amit Kumar's avatar Amit Kumar 💻
Browse files

Add lawnchair based quickstep implementation

This is important to do as Launcher3 implementation heavily depends on AOSP framework codebase.
parent 0c24a571
Pipeline #124921 failed with stage
in 2 minutes and 33 seconds
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
minSdkVersion 25
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
addFrameworkJar('framework.jar')
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
# 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
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xyz.paphonb.quickstep.compat" />
package xyz.paphonb.quickstep.compat;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.IAssistDataReceiver;
import android.app.ITaskStackListener;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteException;
import java.util.List;
public abstract class ActivityManagerCompat {
public abstract List<ActivityManager.RunningTaskInfo> getFilteredTasks(
int maxNum, int ignoreActivityType, int ignoreWindowingMode) throws RemoteException;
public abstract List<ActivityManager.RecentTaskInfo> getRecentTasks(
int maxNum, int flags, int userId) throws RemoteException;
public abstract ActivityManager.TaskSnapshot getTaskSnapshot(
int taskId, boolean reducedResolution) throws RemoteException;
public abstract void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
RecentsAnimationRunner recentsAnimationRunner) throws RemoteException;
public abstract void cancelRecentsAnimation(boolean restoreHomeStackPosition) throws RemoteException;
public abstract int startActivityFromRecents(int taskId, Bundle bOptions) throws RemoteException;
public abstract boolean setTaskWindowingModeSplitScreenPrimary(
int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds, boolean showRecents) throws RemoteException;
public abstract boolean removeTask(int taskId) throws RemoteException;
public abstract void removeAllVisibleRecentTasks() throws RemoteException;
public abstract void cancelTaskWindowTransition(int taskId) throws RemoteException;
public abstract int getLockTaskModeState() throws RemoteException;
public abstract void registerTaskStackListener(ITaskStackListener listener) throws RemoteException;
public abstract void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException;
public abstract boolean supportsMultiWindow(Context context);
public abstract int getDisplayId(Context context);
}
package xyz.paphonb.quickstep.compat;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.view.BatchedInputEventReceiver;;
import android.view.Choreographer;
import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputEvent;
public abstract class InputCompat {
public abstract BatchedInputEventReceiver createBatchedInputEventReceiver(
InputChannel inputChannel, Looper looper, Choreographer choreographer,
final InputEventListener listener);
public abstract void createInputConsumer(
IWindowManager windowManager, IBinder token, String name, int displayId,
InputChannel inputChannel) throws RemoteException;
public abstract boolean destroyInputConsumer(
IWindowManager windowManager, String name, int displayId) throws RemoteException;
public interface InputEventListener {
boolean onInputEvent(InputEvent event);
}
}
package xyz.paphonb.quickstep.compat;
import androidx.annotation.NonNull;
public abstract class QuickstepCompatFactory {
@NonNull
public abstract ActivityManagerCompat getActivityManagerCompat();
@NonNull
public abstract RecentsCompat getRecentsModelCompat();
@NonNull
public abstract InputCompat getInputCompat();
}
package xyz.paphonb.quickstep.compat;
import android.graphics.Rect;
import android.view.IRecentsAnimationController;
import android.view.RemoteAnimationTarget;
public interface RecentsAnimationRunner {
void onAnimationStart(IRecentsAnimationController controller,
RemoteAnimationTarget[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds);
void onAnimationCanceled(boolean deferredWithScreenshot);
}
package xyz.paphonb.quickstep.compat;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IRecentsAnimationController;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.view.ViewRootImpl;
import android.view.WindowCallbacks;
public abstract class RecentsCompat {
public abstract int getTaskId(ActivityManager.RecentTaskInfo info);
public abstract int getTaskId(ActivityManager.RunningTaskInfo info);
public abstract int getDisplayId(ActivityManager.RecentTaskInfo info);
public abstract Bitmap getThumbnail(TaskSnapshot snapshot);
public abstract void finishRecentsAnimation(
IRecentsAnimationController animationController, boolean toHome,
boolean sendUserLeaveHint) throws RemoteException;
public abstract void registerRtFrameCallback(ViewRootImpl viewRoot, FrameDrawingCallback callback);
public abstract void setSurfaceBufferSize(SurfaceControl.Transaction transaction, SurfaceControl surfaceControl, int w, int h);
public abstract WindowCallbacks createWindowCallbacks(WindowCallbacksWrapper callbacks);
public abstract void overridePendingAppTransitionMultiThumbFuture(
IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
boolean scaleUp, int displayId) throws RemoteException;
public abstract void overridePendingAppTransitionRemote(
RemoteAnimationAdapter remoteAnimationAdapter, int displayId) throws RemoteException;
public abstract boolean hasNavigationBar(int displayId) throws RemoteException;
public abstract int getNavBarPosition(int displayId) throws RemoteException;
public interface FrameDrawingCallback {
void onFrameDraw(long frame);
}
public interface WindowCallbacksWrapper {
void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
Rect stableInsets);
void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen,
Rect systemInsets, Rect stableInsets, int resizeMode);
void onWindowDragResizeEnd();
boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY);
void onRequestDraw(boolean reportNextDraw);
void onPostDraw(Canvas canvas);
}
}
<resources>
<string name="app_name">QuickstepCompat</string>
<integer name="config_quickstepCompatFactory">800</integer>
</resources>
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
minSdkVersion 25
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
addFrameworkJar('framework.jar')
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.1.0'
implementation project(':QuickstepCompat')
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
# 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
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="xyz.paphonb.quickstep.compat.ten" />
package xyz.paphonb.quickstep.compat.ten;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityTaskManager;
import android.app.IAssistDataReceiver;
import android.app.ITaskStackListener;
import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteException;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
import java.util.List;
import xyz.paphonb.quickstep.compat.ActivityManagerCompat;
import xyz.paphonb.quickstep.compat.RecentsAnimationRunner;
public class ActivityManagerCompatVQ extends ActivityManagerCompat {
@Override
public List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType, int ignoreWindowingMode) throws RemoteException {
return ActivityTaskManager.getService().getFilteredTasks(maxNum, ignoreActivityType, ignoreWindowingMode);
}
@Override
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags, int userId) throws RemoteException {
return ActivityTaskManager.getService().getRecentTasks(maxNum, flags, userId).getList();
}
@Override
public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution) throws RemoteException {
return ActivityTaskManager.getService().getTaskSnapshot(taskId, reducedResolution);
}
@Override
public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver, final RecentsAnimationRunner recentsAnimationRunner) throws RemoteException {
IRecentsAnimationRunner runner = null;
if (recentsAnimationRunner != null) {
runner = new IRecentsAnimationRunner.Stub() {
@Override
public void onAnimationStart(IRecentsAnimationController controller,
RemoteAnimationTarget[] apps, Rect homeContentInsets,
Rect minimizedHomeBounds) {
recentsAnimationRunner.onAnimationStart(controller, apps, homeContentInsets, minimizedHomeBounds);
}
@Override
public void onAnimationCanceled(boolean deferredWithScreenshot) {
recentsAnimationRunner.onAnimationCanceled(deferredWithScreenshot);
}
};
}
ActivityTaskManager.getService().startRecentsActivity(intent, assistDataReceiver, runner);
}
@Override
public void cancelRecentsAnimation(boolean restoreHomeStackPosition) throws RemoteException {
ActivityTaskManager.getService().cancelRecentsAnimation(restoreHomeStackPosition);
}
@Override
public int startActivityFromRecents(int taskId, Bundle bOptions) throws RemoteException {
return ActivityTaskManager.getService().startActivityFromRecents(taskId, bOptions);
}
@Override
public boolean setTaskWindowingModeSplitScreenPrimary(
int taskId, int createMode, boolean toTop, boolean animate,
Rect initialBounds, boolean showRecents) throws RemoteException {
return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(taskId,
createMode, toTop, animate, initialBounds, showRecents);
}
@Override
public boolean removeTask(int taskId) throws RemoteException {
return ActivityTaskManager.getService().removeTask(taskId);
}
@Override
public void removeAllVisibleRecentTasks() throws RemoteException {
ActivityTaskManager.getService().removeAllVisibleRecentTasks();
}
@Override
public void cancelTaskWindowTransition(int taskId) throws RemoteException {
ActivityTaskManager.getService().cancelTaskWindowTransition(taskId);
}
@Override
public int getLockTaskModeState() throws RemoteException {
return ActivityTaskManager.getService().getLockTaskModeState();
}
@Override
public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException {
ActivityTaskManager.getService().registerTaskStackListener(listener);
}
@Override
public void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException {
ActivityTaskManager.getService().unregisterTaskStackListener(listener);
}
@Override
public boolean supportsMultiWindow(Context context) {
return ActivityTaskManager.supportsMultiWindow(context);
}
@Override
public int getDisplayId(Context context) {
return context.getDisplayId();
}
}
package xyz.paphonb.quickstep.compat.ten;
import android.os.Build;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.view.BatchedInputEventReceiver;;
import android.view.Choreographer;
import android.view.IWindowManager;
import android.view.InputChannel;
import android.view.InputEvent;
import androidx.annotation.RequiresApi;
import xyz.paphonb.quickstep.compat.InputCompat;
@RequiresApi(Build.VERSION_CODES.Q)
public class InputCompatVQ extends InputCompat {
@Override
public BatchedInputEventReceiver createBatchedInputEventReceiver(
InputChannel inputChannel, Looper looper, Choreographer choreographer,
final InputCompat.InputEventListener listener) {
return new BatchedInputEventReceiver(inputChannel, looper, choreographer) {
@Override
public void onInputEvent(InputEvent event) {
boolean handled = listener.onInputEvent(event);
finishInputEvent(event, handled);
}
};
}
@Override
public void createInputConsumer(
IWindowManager windowManager, IBinder token, String name, int displayId,
InputChannel inputChannel) throws RemoteException {
windowManager.createInputConsumer(token, name, displayId, inputChannel);
}
@Override
public boolean destroyInputConsumer(
IWindowManager windowManager, String name, int displayId) throws RemoteException {
return windowManager.destroyInputConsumer(name, displayId);
}
}
package xyz.paphonb.quickstep.compat.ten;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import org.jetbrains.annotations.NotNull;
import xyz.paphonb.quickstep.compat.ActivityManagerCompat;
import xyz.paphonb.quickstep.compat.InputCompat;
import xyz.paphonb.quickstep.compat.QuickstepCompatFactory;
import xyz.paphonb.quickstep.compat.RecentsCompat;
@RequiresApi(Build.VERSION_CODES.Q)
public class QuickstepCompatFactoryVQ extends QuickstepCompatFactory {
@NotNull
@Override
public ActivityManagerCompat getActivityManagerCompat() {
return new ActivityManagerCompatVQ();
}
@NotNull
@Override
public RecentsCompat getRecentsModelCompat() {
return new RecentsCompatVQ();
}
@NonNull
@Override
public InputCompat getInputCompat() {
return new InputCompatVQ();
}
}
package xyz.paphonb.quickstep.compat.ten;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.graphics.Bitmap;
import android.graphics.HardwareRenderer;
import android.graphics.RecordingCanvas;
import android.graphics.Rect;
import android.os.Build;
import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.view.IAppTransitionAnimationSpecsFuture;
import android.view.IRecentsAnimationController;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
import android.view.ViewRootImpl;
import android.view.WindowCallbacks;
import android.view.WindowManagerGlobal;
import androidx.annotation.RequiresApi;
import xyz.paphonb.quickstep.compat.RecentsCompat;
@RequiresApi(Build.VERSION_CODES.Q)
public class RecentsCompatVQ extends RecentsCompat {
@Override
public int getTaskId(ActivityManager.RecentTaskInfo info) {
return info.taskId;
}
@Override
public int getTaskId(ActivityManager.RunningTaskInfo info) {
return info.taskId;
}
@Override
public int getDisplayId(ActivityManager.RecentTaskInfo info) {
return info.displayId;
}