fixed issue applying lawnchair as recents provider in A15

- fixed animation app to home
- action buttons in recents
This commit is contained in:
MrSluffy
2024-12-11 12:27:09 +08:00
parent ca709e52eb
commit 1a9982ad65
31 changed files with 1611 additions and 722 deletions

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import android.graphics.Region;
/**
* Listener for changes to the system gesture exclusion region
*
* {@hide}
*/
oneway interface ISystemGestureExclusionListener {
/**
* Called when the system gesture exclusion for the given display changed.
* @param displayId the display whose system gesture exclusion changed
* @param systemGestureExclusion a {@code Region} where the app would like priority over the
* system gestures, in display coordinates. Certain restrictions
* might be applied such that apps don't get all the exclusions
* they request.
* @param systemGestureExclusionUnrestricted a {@code Region} where the app would like priority
* over the system gestures, in display coordinates, without
* any restrictions applied. Null if no restrictions have been
* applied.
*/
void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion,
in Region systemGestureExclusionUnrestricted);
}

View File

@@ -0,0 +1,411 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.InsetsSource.Flags;
import android.view.WindowInsets.Type.InsetsType;
import java.util.Arrays;
import java.util.Objects;
/**
* Insets provided by a window.
*
* The insets frame will by default as the window frame size. If the providers are set, the
* calculation result based on the source size will be used as the insets frame.
*
* The InsetsFrameProvider should be self-contained. Nothing describing the window itself, such as
* contentInsets, visibleInsets, etc. won't affect the insets providing to other windows when this
* is set.
* @hide
*/
public class InsetsFrameProvider implements Parcelable {
/**
* Uses the display frame as the source.
*/
public static final int SOURCE_DISPLAY = 0;
/**
* Uses the window bounds as the source.
*/
public static final int SOURCE_CONTAINER_BOUNDS = 1;
/**
* Uses the window frame as the source.
*/
public static final int SOURCE_FRAME = 2;
/**
* Uses {@link #mArbitraryRectangle} as the source.
*/
public static final int SOURCE_ARBITRARY_RECTANGLE = 3;
private final int mId;
/**
* The selection of the starting rectangle to be converted into source frame.
*/
private int mSource = SOURCE_FRAME;
/**
* This is used as the source frame only if SOURCE_ARBITRARY_RECTANGLE is applied.
*/
private Rect mArbitraryRectangle;
/**
* Modifies the starting rectangle selected by {@link #mSource}.
*
* For example, when the given source frame is (0, 0) - (100, 200), and the insetsSize is null,
* the source frame will be directly used as the final insets frame. If the insetsSize is set to
* (0, 0, 0, 50) instead, the insets frame will be a frame starting from the bottom side of the
* source frame with height of 50, i.e., (0, 150) - (100, 200).
*/
private Insets mInsetsSize = null;
/**
* Various behavioral options/flags. Default is none.
*
* @see Flags
*/
private @Flags int mFlags;
/**
* If null, the size set in insetsSize will be applied to all window types. If it contains
* element of some types, the insets reported to the window with that types will be overridden.
*/
private InsetsSizeOverride[] mInsetsSizeOverrides = null;
/**
* This field, if set, is indicating the insets needs to be at least the given size inside the
* display cutout safe area. This will be compared to the insets size calculated based on other
* attributes, and will be applied when this is larger. This is independent of the
* PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT in LayoutParams, as this is not going to change
* the layout of the window, but only change the insets frame. This can be applied to insets
* calculated based on all three source frames.
*
* Be cautious, this will not be in effect for the window types whose insets size is overridden.
*/
private Insets mMinimalInsetsSizeInDisplayCutoutSafe = null;
/**
* Indicates the bounding rectangles within the provided insets frame, in relative coordinates
* to the source frame.
*/
private Rect[] mBoundingRects = null;
/**
* Creates an InsetsFrameProvider which describes what frame an insets source should have.
*
* @param owner the owner of this provider. We might have multiple sources with the same type on
* a display, this is used to identify them.
* @param index the index of this provider. An owner might provide multiple sources with the
* same type, this is used to identify them.
* The value must be in a range of [0, 2047].
* @param type the {@link InsetsType}.
* @see InsetsSource#createId(Object, int, int)
*/
public InsetsFrameProvider(Object owner, @IntRange(from = 0, to = 2047) int index,
@InsetsType int type) {
mId = InsetsSource.createId(owner, index, type);
}
/**
* Returns an unique integer which identifies the insets source.
*/
public int getId() {
return mId;
}
/**
* Returns the index specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
*/
public int getIndex() {
return InsetsSource.getIndex(mId);
}
/**
* Returns the {@link InsetsType} specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
*/
public int getType() {
return InsetsSource.getType(mId);
}
public InsetsFrameProvider setSource(int source) {
mSource = source;
return this;
}
public int getSource() {
return mSource;
}
public InsetsFrameProvider setFlags(@Flags int flags, @Flags int mask) {
mFlags = (mFlags & ~mask) | (flags & mask);
return this;
}
public @Flags int getFlags() {
return mFlags;
}
public boolean hasFlags(@Flags int mask) {
return (mFlags & mask) == mask;
}
public InsetsFrameProvider setInsetsSize(Insets insetsSize) {
mInsetsSize = insetsSize;
return this;
}
public Insets getInsetsSize() {
return mInsetsSize;
}
public InsetsFrameProvider setArbitraryRectangle(Rect rect) {
mArbitraryRectangle = new Rect(rect);
return this;
}
public Rect getArbitraryRectangle() {
return mArbitraryRectangle;
}
public InsetsFrameProvider setInsetsSizeOverrides(InsetsSizeOverride[] insetsSizeOverrides) {
mInsetsSizeOverrides = insetsSizeOverrides;
return this;
}
public InsetsSizeOverride[] getInsetsSizeOverrides() {
return mInsetsSizeOverrides;
}
public InsetsFrameProvider setMinimalInsetsSizeInDisplayCutoutSafe(
Insets minimalInsetsSizeInDisplayCutoutSafe) {
mMinimalInsetsSizeInDisplayCutoutSafe = minimalInsetsSizeInDisplayCutoutSafe;
return this;
}
public Insets getMinimalInsetsSizeInDisplayCutoutSafe() {
return mMinimalInsetsSizeInDisplayCutoutSafe;
}
/**
* Sets the bounding rectangles within and relative to the source frame.
*/
public InsetsFrameProvider setBoundingRects(@Nullable Rect[] boundingRects) {
mBoundingRects = boundingRects == null ? null : boundingRects.clone();
return this;
}
/**
* Returns the arbitrary bounding rects, or null if none were set.
*/
@Nullable
public Rect[] getBoundingRects() {
return mBoundingRects;
}
@Override
public int describeContents() {
return 0;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("InsetsFrameProvider: {");
sb.append("id=#").append(Integer.toHexString(mId));
sb.append(", index=").append(getIndex());
sb.append(", type=").append(WindowInsets.Type.toString(getType()));
sb.append(", source=").append(sourceToString(mSource));
sb.append(", flags=[").append(InsetsSource.flagsToString(mFlags)).append("]");
if (mInsetsSize != null) {
sb.append(", insetsSize=").append(mInsetsSize);
}
if (mInsetsSizeOverrides != null) {
sb.append(", insetsSizeOverrides=").append(Arrays.toString(mInsetsSizeOverrides));
}
if (mArbitraryRectangle != null) {
sb.append(", mArbitraryRectangle=").append(mArbitraryRectangle.toShortString());
}
if (mMinimalInsetsSizeInDisplayCutoutSafe != null) {
sb.append(", mMinimalInsetsSizeInDisplayCutoutSafe=")
.append(mMinimalInsetsSizeInDisplayCutoutSafe);
}
if (mBoundingRects != null) {
sb.append(", mBoundingRects=").append(Arrays.toString(mBoundingRects));
}
sb.append("}");
return sb.toString();
}
private static String sourceToString(int source) {
switch (source) {
case SOURCE_DISPLAY:
return "DISPLAY";
case SOURCE_CONTAINER_BOUNDS:
return "CONTAINER_BOUNDS";
case SOURCE_FRAME:
return "FRAME";
case SOURCE_ARBITRARY_RECTANGLE:
return "ARBITRARY_RECTANGLE";
}
return "UNDEFINED";
}
public InsetsFrameProvider(Parcel in) {
mId = in.readInt();
mSource = in.readInt();
mFlags = in.readInt();
mInsetsSize = in.readTypedObject(Insets.CREATOR);
mInsetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
mArbitraryRectangle = in.readTypedObject(Rect.CREATOR);
mMinimalInsetsSizeInDisplayCutoutSafe = in.readTypedObject(Insets.CREATOR);
mBoundingRects = in.createTypedArray(Rect.CREATOR);
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mId);
out.writeInt(mSource);
out.writeInt(mFlags);
out.writeTypedObject(mInsetsSize, flags);
out.writeTypedArray(mInsetsSizeOverrides, flags);
out.writeTypedObject(mArbitraryRectangle, flags);
out.writeTypedObject(mMinimalInsetsSizeInDisplayCutoutSafe, flags);
out.writeTypedArray(mBoundingRects, flags);
}
public boolean idEquals(InsetsFrameProvider o) {
return mId == o.mId;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final InsetsFrameProvider other = (InsetsFrameProvider) o;
return mId == other.mId && mSource == other.mSource && mFlags == other.mFlags
&& Objects.equals(mInsetsSize, other.mInsetsSize)
&& Arrays.equals(mInsetsSizeOverrides, other.mInsetsSizeOverrides)
&& Objects.equals(mArbitraryRectangle, other.mArbitraryRectangle)
&& Objects.equals(mMinimalInsetsSizeInDisplayCutoutSafe,
other.mMinimalInsetsSizeInDisplayCutoutSafe)
&& Arrays.equals(mBoundingRects, other.mBoundingRects);
}
@Override
public int hashCode() {
return Objects.hash(mId, mSource, mFlags, mInsetsSize,
Arrays.hashCode(mInsetsSizeOverrides), mArbitraryRectangle,
mMinimalInsetsSizeInDisplayCutoutSafe, Arrays.hashCode(mBoundingRects));
}
public static final @NonNull Parcelable.Creator<InsetsFrameProvider> CREATOR =
new Parcelable.Creator<>() {
@Override
public InsetsFrameProvider createFromParcel(Parcel in) {
return new InsetsFrameProvider(in);
}
@Override
public InsetsFrameProvider[] newArray(int size) {
return new InsetsFrameProvider[size];
}
};
/**
* Class to describe the insets size to be provided to window with specific window type. If not
* used, same insets size will be sent as instructed in the insetsSize and source.
*
* If the insetsSize of given type is set to {@code null}, the insets source frame will be used
* directly for that window type.
*/
public static class InsetsSizeOverride implements Parcelable {
private final int mWindowType;
private final Insets mInsetsSize;
protected InsetsSizeOverride(Parcel in) {
mWindowType = in.readInt();
mInsetsSize = in.readTypedObject(Insets.CREATOR);
}
public InsetsSizeOverride(int windowType, Insets insetsSize) {
mWindowType = windowType;
mInsetsSize = insetsSize;
}
public int getWindowType() {
return mWindowType;
}
public Insets getInsetsSize() {
return mInsetsSize;
}
public static final Creator<InsetsSizeOverride> CREATOR = new Creator<>() {
@Override
public InsetsSizeOverride createFromParcel(Parcel in) {
return new InsetsSizeOverride(in);
}
@Override
public InsetsSizeOverride[] newArray(int size) {
return new InsetsSizeOverride[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mWindowType);
out.writeTypedObject(mInsetsSize, flags);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(32);
sb.append("TypedInsetsSize: {");
sb.append("windowType=").append(ViewDebug.intToString(
WindowManager.LayoutParams.class, "type", mWindowType));
sb.append(", insetsSize=").append(mInsetsSize);
sb.append("}");
return sb.toString();
}
@Override
public int hashCode() {
return Objects.hash(mWindowType, mInsetsSize);
}
}
}

View File

@@ -19,6 +19,7 @@ package android.window;
import android.view.SurfaceControl;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
import android.window.WindowAnimationState;
/**
* Interface allowing remote processes to play transition animations.
@@ -36,7 +37,6 @@ import android.window.TransitionInfo;
*
* {@hide}
*/
oneway interface IRemoteTransition {
/**
* Starts a transition animation. Once complete, the implementation should call
@@ -46,6 +46,7 @@ oneway interface IRemoteTransition {
*/
void startAnimation(in IBinder token, in TransitionInfo info, in SurfaceControl.Transaction t,
in IRemoteTransitionFinishedCallback finishCallback);
/**
* Attempts to merge a transition animation into the animation that is currently
* being played by this remote. If merge is not possible/supported, this should be a no-op.
@@ -59,4 +60,25 @@ oneway interface IRemoteTransition {
void mergeAnimation(in IBinder transition, in TransitionInfo info,
in SurfaceControl.Transaction t, in IBinder mergeTarget,
in IRemoteTransitionFinishedCallback finishCallback);
/**
* Takes over the animation of the windows from an existing transition. Once complete, the
* implementation should call `finishCallback`.
*
* @param transition An identifier for the transition to be taken over.
* @param states The animation states of the windows involved in the transition. These must be
* sorted in the same way as the Changes inside `info`, and each state may be
* null.
*/
void takeOverAnimation(in IBinder transition, in TransitionInfo info,
in SurfaceControl.Transaction t, in IRemoteTransitionFinishedCallback finishCallback,
in WindowAnimationState[] states);
/**
* Called when a different handler has consumed the transition
*
* @param transition An identifier for the transition that was consumed.
* @param aborted Whether the transition is aborted or not.
*/
void onTransitionConsumed(in IBinder transition, in boolean aborted);
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.annotation.NonNull;
@@ -5,16 +21,14 @@ import android.annotation.Nullable;
import android.app.IApplicationThread;
import android.os.IBinder;
import android.os.Parcelable;
import com.android.internal.util.DataClass;
/**
* Represents a remote transition animation and information required to run it (eg. the app thread
* that needs to be boosted).
*
* @hide
*/
@DataClass(genToString = true, genSetters = true, genAidl = true)
public class RemoteTransition implements Parcelable {
public final class RemoteTransition implements Parcelable {
/** The actual remote-transition interface used to run the transition animation. */
private @NonNull IRemoteTransition mRemoteTransition;
@@ -24,14 +38,20 @@ public class RemoteTransition implements Parcelable {
/** A name for this that can be used for debugging. */
private @Nullable String mDebugName;
/** Constructs with no app thread (animation runs in shell). */
/**
* Constructs with no app thread (animation runs in shell).
* @hide
*/
public RemoteTransition(@NonNull IRemoteTransition remoteTransition) {
this(remoteTransition, null /* appThread */, null /* debugName */);
}
/** Constructs with no app thread (animation runs in shell). */
public RemoteTransition(
@NonNull IRemoteTransition remoteTransition, @Nullable String debugName) {
/**
* Constructs with no app thread (animation runs in shell).
* @hide
*/
public RemoteTransition(@NonNull IRemoteTransition remoteTransition,
@Nullable String debugName) {
this(remoteTransition, null /* appThread */, debugName);
}
@@ -40,26 +60,17 @@ public class RemoteTransition implements Parcelable {
return mRemoteTransition.asBinder();
}
// Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
//
// To regenerate run:
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/window/RemoteTransition.java
//
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
// Settings > Editor > Code Style > Formatter Control
// @formatter:off
/**
* Creates a new RemoteTransition.
*
* @param remoteTransition The actual remote-transition interface used to run the transition
* animation.
* @param appThread The application thread that will be running the remote transition.
* @param debugName A name for this that can be used for debugging.
* @param remoteTransition
* The actual remote-transition interface used to run the transition animation.
* @param appThread
* The application thread that will be running the remote transition.
* @param debugName
* A name for this that can be used for debugging.
* @hide
*/
@DataClass.Generated.Member
public RemoteTransition(
@NonNull IRemoteTransition remoteTransition,
@Nullable IApplicationThread appThread,
@@ -69,29 +80,37 @@ public class RemoteTransition implements Parcelable {
NonNull.class, null, mRemoteTransition);
this.mAppThread = appThread;
this.mDebugName = debugName;
// onConstructed(); // You can define this method to get a callback
}
/** The actual remote-transition interface used to run the transition animation. */
@DataClass.Generated.Member
/**
* The actual remote-transition interface used to run the transition animation.
* @hide
*/
public @NonNull IRemoteTransition getRemoteTransition() {
return mRemoteTransition;
}
/** The application thread that will be running the remote transition. */
@DataClass.Generated.Member
/**
* The application thread that will be running the remote transition.
* @hide
*/
public @Nullable IApplicationThread getAppThread() {
return mAppThread;
}
/** A name for this that can be used for debugging. */
@DataClass.Generated.Member
/**
* A name for this that can be used for debugging.
*/
public @Nullable String getDebugName() {
return mDebugName;
}
/** The actual remote-transition interface used to run the transition animation. */
@DataClass.Generated.Member
/**
* The actual remote-transition interface used to run the transition animation.
* @hide
*/
public @NonNull RemoteTransition setRemoteTransition(@NonNull IRemoteTransition value) {
mRemoteTransition = value;
com.android.internal.util.AnnotationValidations.validate(
@@ -99,42 +118,40 @@ public class RemoteTransition implements Parcelable {
return this;
}
/** The application thread that will be running the remote transition. */
@DataClass.Generated.Member
/**
* The application thread that will be running the remote transition.
* @hide
*/
public @NonNull RemoteTransition setAppThread(@NonNull IApplicationThread value) {
mAppThread = value;
return this;
}
/** A name for this that can be used for debugging. */
@DataClass.Generated.Member
/**
* A name for this that can be used for debugging.
*/
public @NonNull RemoteTransition setDebugName(@NonNull String value) {
mDebugName = value;
return this;
}
@Override
@DataClass.Generated.Member
public String toString() {
// You can override field toString logic by defining methods like:
// String fieldNameToString() { ... }
return "RemoteTransition { "
+ "remoteTransition = "
+ mRemoteTransition
+ ", "
+ "appThread = "
+ mAppThread
+ ", "
+ "debugName = "
+ mDebugName
+ " }";
return "RemoteTransition { " +
"remoteTransition = " + mRemoteTransition + ", " +
"appThread = " + mAppThread + ", " +
"debugName = " + mDebugName +
" }";
}
@Override
@DataClass.Generated.Member
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
// You can override field parcelling by defining methods like:
// void parcelFieldName(Parcel dest, int flags) { ... }
byte flg = 0;
if (mAppThread != null) flg |= 0x2;
if (mDebugName != null) flg |= 0x4;
@@ -145,55 +162,36 @@ public class RemoteTransition implements Parcelable {
}
@Override
@DataClass.Generated.Member
public int describeContents() {
return 0;
}
public int describeContents() { return 0; }
/** @hide */
@SuppressWarnings({"unchecked", "RedundantCast"})
@DataClass.Generated.Member
protected RemoteTransition(@NonNull android.os.Parcel in) {
// You can override field unparcelling by defining methods like:
// static FieldType unparcelFieldName(Parcel in) { ... }
byte flg = in.readByte();
IRemoteTransition remoteTransition =
IRemoteTransition.Stub.asInterface(in.readStrongBinder());
IApplicationThread appThread =
(flg & 0x2) == 0
? null
: IApplicationThread.Stub.asInterface(in.readStrongBinder());
IRemoteTransition remoteTransition = IRemoteTransition.Stub.asInterface(in.readStrongBinder());
IApplicationThread appThread = (flg & 0x2) == 0 ? null : IApplicationThread.Stub.asInterface(in.readStrongBinder());
String debugName = (flg & 0x4) == 0 ? null : in.readString();
this.mRemoteTransition = remoteTransition;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mRemoteTransition);
this.mAppThread = appThread;
this.mDebugName = debugName;
// onConstructed(); // You can define this method to get a callback
}
@DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<RemoteTransition> CREATOR =
new Parcelable.Creator<RemoteTransition>() {
@Override
public RemoteTransition[] newArray(int size) {
return new RemoteTransition[size];
}
public static final @NonNull Parcelable.Creator<RemoteTransition> CREATOR
= new Parcelable.Creator<RemoteTransition>() {
@Override
public RemoteTransition[] newArray(int size) {
return new RemoteTransition[size];
}
@Override
public RemoteTransition createFromParcel(@NonNull android.os.Parcel in) {
return new RemoteTransition(in);
}
};
@DataClass.Generated(
time = 1678926409863L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/window/RemoteTransition.java",
inputSignatures =
"private @android.annotation.NonNull android.window.IRemoteTransition mRemoteTransition\nprivate @android.annotation.Nullable android.app.IApplicationThread mAppThread\nprivate @android.annotation.Nullable java.lang.String mDebugName\npublic @android.annotation.Nullable android.os.IBinder asBinder()\nclass RemoteTransition extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genSetters=true, genAidl=true)")
@Deprecated
private void __metadata() {}
// @formatter:on
// End of generated code
}
@Override
public RemoteTransition createFromParcel(@NonNull android.os.Parcel in) {
return new RemoteTransition(in);
}
};
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import android.os.IBinder;
import android.os.RemoteException;
import android.view.SurfaceControl;
/**
* Utility base implementation of {@link IRemoteTransition} that users can extend to avoid stubbing.
*
* @hide
*/
public abstract class RemoteTransitionStub extends IRemoteTransition.Stub {
@Override
public void mergeAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t, IBinder mergeTarget,
IRemoteTransitionFinishedCallback finishCallback) throws RemoteException {}
@Override
public void takeOverAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction startTransaction,
IRemoteTransitionFinishedCallback finishCallback,
WindowAnimationState[] states) throws RemoteException {
throw new RemoteException("Takeovers are not supported by this IRemoteTransition");
}
@Override
public void onTransitionConsumed(IBinder transition, boolean aborted)
throws RemoteException {}
}

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.window;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -24,30 +25,30 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.WindowConfiguration;
import android.content.ComponentName;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.view.WindowManager;
/**
* A parcelable filter that can be used for rerouting transitions to a remote. This is a local
* representation so that the transition system doesn't need to make blocking queries over binder.
* representation so that the transition system doesn't need to make blocking queries over
* binder.
*
* @hide
*/
public final class TransitionFilter implements Parcelable {
/** The associated requirement doesn't care about the z-order. */
public static final int CONTAINER_ORDER_ANY = 0;
/** The associated requirement only matches the top-most (z-order) container. */
public static final int CONTAINER_ORDER_TOP = 1;
/** @hide */
@IntDef(
prefix = {"CONTAINER_ORDER_"},
value = {
CONTAINER_ORDER_ANY,
CONTAINER_ORDER_TOP,
})
@IntDef(prefix = { "CONTAINER_ORDER_" }, value = {
CONTAINER_ORDER_ANY,
CONTAINER_ORDER_TOP,
})
public @interface ContainerOrder {}
/**
@@ -62,10 +63,13 @@ public final class TransitionFilter implements Parcelable {
/** All flags must NOT be set on a transition. */
public @WindowManager.TransitionFlags int mNotFlags = 0;
/** A list of required changes. To pass, a transition must meet all requirements. */
/**
* A list of required changes. To pass, a transition must meet all requirements.
*/
@Nullable public Requirement[] mRequirements = null;
public TransitionFilter() {}
public TransitionFilter() {
}
private TransitionFilter(Parcel in) {
mTypeSet = in.createIntArray();
@@ -74,9 +78,7 @@ public final class TransitionFilter implements Parcelable {
mRequirements = in.createTypedArray(Requirement.CREATOR);
}
/**
* @return true if `info` meets all the requirements to pass this filter.
*/
/** @return true if `info` meets all the requirements to pass this filter. */
public boolean matches(@NonNull TransitionInfo info) {
if (mTypeSet != null) {
// non-null typeset, so make sure info is one of the types.
@@ -179,8 +181,10 @@ public final class TransitionFilter implements Parcelable {
public @ContainerOrder int mOrder = CONTAINER_ORDER_ANY;
public ComponentName mTopActivity;
public IBinder mLaunchCookie;
public Requirement() {}
public Requirement() {
}
private Requirement(Parcel in) {
mActivityType = in.readInt();
@@ -191,6 +195,7 @@ public final class TransitionFilter implements Parcelable {
mMustBeTask = in.readBoolean();
mOrder = in.readInt();
mTopActivity = in.readTypedObject(ComponentName.CREATOR);
mLaunchCookie = in.readStrongBinder();
}
/** Go through changes and find if at-least one change matches this filter */
@@ -210,7 +215,9 @@ public final class TransitionFilter implements Parcelable {
continue;
}
}
if (!matchesTopActivity(change.getTaskInfo())) continue;
if (!matchesTopActivity(change.getTaskInfo(), change.getActivityComponent())) {
continue;
}
if (mModes != null) {
boolean pass = false;
for (int m = 0; m < mModes.length; ++m) {
@@ -227,16 +234,34 @@ public final class TransitionFilter implements Parcelable {
if (mMustBeTask && change.getTaskInfo() == null) {
continue;
}
if (!matchesCookie(change.getTaskInfo())) {
continue;
}
return true;
}
return false;
}
private boolean matchesTopActivity(ActivityManager.RunningTaskInfo info) {
private boolean matchesTopActivity(ActivityManager.RunningTaskInfo taskInfo,
@Nullable ComponentName activityComponent) {
if (mTopActivity == null) return true;
if (activityComponent != null) {
return mTopActivity.equals(activityComponent);
} else if (taskInfo != null) {
return mTopActivity.equals(taskInfo.topActivity);
}
return false;
}
private boolean matchesCookie(ActivityManager.RunningTaskInfo info) {
if (mLaunchCookie == null) return true;
if (info == null) return false;
final ComponentName component = info.topActivity;
return mTopActivity.equals(component);
for (IBinder cookie : info.launchCookies) {
if (mLaunchCookie.equals(cookie)) {
return true;
}
}
return false;
}
/** Check if the request matches this filter. It may generate false positives */
@@ -245,7 +270,8 @@ public final class TransitionFilter implements Parcelable {
if (mActivityType == ACTIVITY_TYPE_UNDEFINED) return true;
return request.getTriggerTask() != null
&& request.getTriggerTask().getActivityType() == mActivityType
&& matchesTopActivity(request.getTriggerTask());
&& matchesTopActivity(request.getTriggerTask(), null /* activityCmp */)
&& matchesCookie(request.getTriggerTask());
}
@Override
@@ -259,6 +285,7 @@ public final class TransitionFilter implements Parcelable {
dest.writeBoolean(mMustBeTask);
dest.writeInt(mOrder);
dest.writeTypedObject(mTopActivity, flags);
dest.writeStrongBinder(mLaunchCookie);
}
@NonNull
@@ -299,6 +326,7 @@ public final class TransitionFilter implements Parcelable {
out.append(" mustBeTask=" + mMustBeTask);
out.append(" order=" + containerOrderToString(mOrder));
out.append(" topActivity=").append(mTopActivity);
out.append(" launchCookie=").append(mLaunchCookie);
out.append("}");
return out.toString();
}
@@ -306,11 +334,9 @@ public final class TransitionFilter implements Parcelable {
private static String containerOrderToString(int order) {
switch (order) {
case CONTAINER_ORDER_ANY:
return "ANY";
case CONTAINER_ORDER_TOP:
return "TOP";
case CONTAINER_ORDER_ANY: return "ANY";
case CONTAINER_ORDER_TOP: return "TOP";
}
return "UNKNOWN(" + order + ")";
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,6 +14,23 @@
* limitations under the License.
*/
package com.android.wm.shell.common.bubbles;
package android.window;
parcelable BubbleBarLocation;
import android.graphics.PointF;
import android.graphics.RectF;
/**
* Properties of a window animation at a given point in time.
*
* {@hide}
*/
parcelable WindowAnimationState {
long timestamp;
RectF bounds;
float scale;
float topLeftRadius;
float topRightRadius;
float bottomRightRadius;
float bottomLeftRadius;
PointF velocityPxPerMs;
}

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- NOTE! don't add dimensions for margins / gravity to root view in this file, they need to be
loaded at runtime. -->
<app.lawnchair.overview.LawnchairOverviewActionsView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom">
<LinearLayout
android:id="@+id/action_buttons"
android:layout_width="match_parent"
android:layout_height="@dimen/overview_actions_height"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal">
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<app.lawnchair.views.CustomButton
android:id="@+id/action_screenshot"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_screenshot"
android:text="@string/action_screenshot" />
<Space
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:visibility="gone" />
<app.lawnchair.views.CustomButton
android:id="@+id/action_share"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_share"
android:text="@string/action_share" />
<Space
android:id="@+id/oav_three_button_space"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1" />
<Button
android:id="@+id/action_split"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_split"
android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:visibility="gone" />
<Space
android:id="@+id/action_split_space"
android:layout_width="@dimen/overview_actions_button_spacing"
android:layout_height="1dp"
android:visibility="gone" />
<app.lawnchair.views.CustomButton
android:id="@+id/action_lens"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_lens"
android:text="@string/action_lens" />
<Space
android:id="@+id/lens_space"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:visibility="gone" />
<app.lawnchair.views.CustomButton
style="@style/OverviewActionButton"
android:id="@+id/action_clear_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/recents_clear_all"
android:drawableStart="@drawable/ic_clear_all_recents"
android:visibility="gone"
/>
<Space
android:id="@+id/clear_all_space"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:visibility="gone" />
<app.lawnchair.views.CustomButton
style="@style/OverviewActionButton"
android:id="@+id/action_locked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_lock"
android:drawableStart="@drawable/ic_locked_recents"
android:visibility="gone" />
<Space
android:id="@+id/locked_space"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_weight="1"
android:visibility="gone" />
</LinearLayout>
<app.lawnchair.views.CustomButton
android:id="@+id/action_save_app_pair"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/action_save_app_pair"
android:layout_gravity="bottom|center_horizontal"
android:visibility="gone" />
</app.lawnchair.overview.LawnchairOverviewActionsView>

View File

@@ -40,7 +40,7 @@
<string name="clock_component_name" translatable="false">com.google.android.deskclock/com.android.deskclock.DeskClock</string>
<string name="launcher_activity_logic_class" translatable="false">app.lawnchair.LauncherActivityCachingLogic</string>
<string name="main_process_initializer_class" translatable="false">app.lawnchair.LawnchairProcessInitializer</string>
<!-- <string name="task_overlay_factory_class" translatable="false">app.lawnchair.overview.TaskOverlayFactoryImpl</string>-->
<string name="task_overlay_factory_class" translatable="false">app.lawnchair.overview.TaskOverlayFactoryImpl</string>
<string name="wallpaper_picker_package" translatable="false">com.android.wallpaper</string>
<string name="wallpaper_picker_package_alt" translatable="false">com.google.android.apps.wallpaper</string>
<string name="widget_holder_factory_class" translatable="false">app.lawnchair.factory.LawnchairWidgetHolder$LawnchairHolderFactory</string>

View File

@@ -0,0 +1,98 @@
package app.lawnchair.overview
import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Space
import androidx.core.view.ViewCompat
import androidx.core.view.isVisible
import app.lawnchair.preferences.PreferenceManager
import app.lawnchair.util.isOnePlusStock
import com.android.launcher3.R
import com.android.quickstep.views.OverviewActionsView
class LawnchairOverviewActionsView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : OverviewActionsView<TaskOverlayFactoryImpl.OverlayUICallbacks>(context, attrs, defStyleAttr) {
private val prefs = PreferenceManager.getInstance(context)
private lateinit var container: LinearLayout
private lateinit var screenshotAction: Button
private lateinit var shareAction: Button
private lateinit var lensAction: Button
private lateinit var clearAllAction: Button
private lateinit var lockedAction: Button
override fun onFinishInflate() {
super.onFinishInflate()
container = ViewCompat.requireViewById(this, R.id.action_buttons)
clearAllAction = ViewCompat.requireViewById(this, R.id.action_clear_all)
shareAction = ViewCompat.requireViewById(this, R.id.action_share)
lensAction = ViewCompat.requireViewById(this, R.id.action_lens)
screenshotAction = ViewCompat.requireViewById(this, R.id.action_screenshot)
lockedAction = ViewCompat.requireViewById(this, R.id.action_locked)
shareAction.setOnClickListener { mCallbacks?.onShare() }
lensAction.setOnClickListener { mCallbacks?.onLens() }
prefs.recentsActionClearAll.subscribeChanges(this, ::updateVisibilities)
prefs.recentsActionLens.subscribeChanges(this, ::updateVisibilities)
prefs.recentsActionScreenshot.subscribeChanges(this, ::updateVisibilities)
prefs.recentsActionShare.subscribeChanges(this, ::updateVisibilities)
prefs.recentsActionLocked.subscribeChanges(this, ::updateVisibilities)
prefs.recentActionOrder.subscribeChanges(this, ::updateVisibilities)
updateVisibilities()
}
private fun updateVisibilities() {
val order = prefs.recentActionOrder.get().split(",").map { it.toInt() }
val buttonMap = mutableMapOf<Int, View>()
if (prefs.recentsActionScreenshot.get() && !isOnePlusStock) {
buttonMap[0] = screenshotAction
}
if (prefs.recentsActionShare.get()) {
buttonMap[1] = shareAction
}
if (prefs.recentsActionLens.get() && isLensAvailable()) {
buttonMap[2] = lensAction
}
if (prefs.recentsActionLocked.get()) {
buttonMap[3] = lockedAction
}
if (prefs.recentsActionClearAll.get()) {
buttonMap[4] = clearAllAction
}
val buttonsInOrder = order.mapNotNull { buttonMap[it] }
container.removeAllViews()
container.addView(createSpace())
buttonsInOrder.forEach { view ->
view.isVisible = true
container.addView(view)
container.addView(createSpace())
}
}
private fun isLensAvailable(): Boolean {
val lensIntent = context.packageManager.getLaunchIntentForPackage("com.google.ar.lens")
return lensIntent != null
}
private fun createSpace(): View {
return Space(context).apply {
layoutParams = LinearLayout.LayoutParams(0, 1).apply { weight = 1f }
}
}
override fun setClearAllClickListener(clearAllClickListener: OnClickListener?) {
clearAllAction.setOnClickListener(clearAllClickListener)
}
}

View File

@@ -0,0 +1,82 @@
package app.lawnchair.overview
import android.content.Context
import android.graphics.Matrix
import androidx.annotation.Keep
import app.lawnchair.util.RecentHelper
import app.lawnchair.util.TaskUtilLockState
import com.android.quickstep.TaskOverlayFactory
import com.android.quickstep.views.OverviewActionsView
import com.android.quickstep.views.TaskView.TaskContainer
import com.android.systemui.shared.recents.model.Task
import com.android.systemui.shared.recents.model.ThumbnailData
@Keep
class TaskOverlayFactoryImpl(@Suppress("UNUSED_PARAMETER") context: Context) : TaskOverlayFactory() {
override fun createOverlay(thumbnailView: TaskContainer) = TaskOverlay(thumbnailView)
class TaskOverlay(
taskThumbnailView: TaskContainer,
) : TaskOverlayFactory.TaskOverlay<LawnchairOverviewActionsView>(taskThumbnailView) {
override fun initOverlay(
task: Task?,
thumbnail: ThumbnailData?,
matrix: Matrix,
rotated: Boolean,
) {
actionsView.updateDisabledFlags(
OverviewActionsView.DISABLED_NO_THUMBNAIL,
thumbnail == null,
)
if (thumbnail != null) {
actionsView.updateDisabledFlags(OverviewActionsView.DISABLED_ROTATED, rotated)
val isAllowedByPolicy = mTaskContainer.thumbnailViewDeprecated.isRealSnapshot
actionsView.setCallbacks(OverlayUICallbacksImpl(isAllowedByPolicy, task))
}
}
private inner class OverlayUICallbacksImpl(
isAllowedByPolicy: Boolean,
task: Task?,
) : TaskOverlayFactory.TaskOverlay<LawnchairOverviewActionsView>.OverlayUICallbacksImpl(
isAllowedByPolicy,
task,
),
OverlayUICallbacks {
override fun onShare() {
if (mIsAllowedByPolicy) {
endLiveTileMode { mImageApi.startShareActivity(null) }
} else {
showBlockedByPolicyMessage()
}
}
override fun onLens() {
if (mIsAllowedByPolicy) {
endLiveTileMode { mImageApi.startLensActivity() }
} else {
showBlockedByPolicyMessage()
}
}
override fun onLocked(context: Context, task: Task) {
val isLocked = !RecentHelper.isAppLocked(task.key.packageName, context)
TaskUtilLockState.setTaskLockState(
context,
task.key.component,
isLocked,
task.key,
)
}
}
}
sealed interface OverlayUICallbacks : TaskOverlayFactory.OverlayUICallbacks {
fun onShare()
fun onLens()
fun onLocked(context: Context, task: Task)
}
}

View File

@@ -184,7 +184,7 @@ import app.lawnchair.compat.LawnchairQuickstepCompat;
public class QuickstepTransitionManager implements OnDeviceProfileChangeListener {
private static final boolean ENABLE_SHELL_STARTING_SURFACE =
SystemProperties.getBoolean("persist.debug.shell_starting_surface", true);
SystemProperties.getBoolean("persist.debug.shell_starting_surface", false);
/** Duration of status bar animations. */
public static final int STATUS_BAR_TRANSITION_DURATION = 120;

View File

@@ -32,19 +32,14 @@ import android.view.ViewTreeObserver;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.util.BaseDepthController;
import com.patrykmichalik.opto.core.PreferenceExtensionsKt;
import java.io.PrintWriter;
import java.util.function.Consumer;
import app.lawnchair.compat.LawnchairQuickstepCompat;
import app.lawnchair.preferences2.PreferenceManager2;
/**
* Controls blur and wallpaper zoom, for the Launcher surface only.
*/
@@ -62,25 +57,14 @@ public class DepthController extends BaseDepthController implements StateHandler
private View.OnAttachStateChangeListener mOnAttachListener;
private final boolean mEnableDepth;
public DepthController(Launcher l) {
super(l);
var pref = PreferenceManager2.getInstance(l).getWallpaperDepthEffect();
mEnableDepth = PreferenceExtensionsKt.firstBlocking(pref);
}
private void onLauncherDraw() {
View view = mLauncher.getDragLayer();
ViewRootImpl viewRootImpl = view.getViewRootImpl();
try {
if (Utilities.ATLEAST_Q) {
setSurface(viewRootImpl != null ? viewRootImpl.getSurfaceControl() : null);
}
} catch (Throwable t) {
}
setSurface(viewRootImpl != null ? viewRootImpl.getSurfaceControl() : null);
view.post(() -> view.getViewTreeObserver().removeOnDrawListener(mOnDrawListener));
}
@@ -90,13 +74,8 @@ public class DepthController extends BaseDepthController implements StateHandler
mOnAttachListener = new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
try {
CrossWindowBlurListeners.getInstance().addListener(mLauncher.getMainExecutor(),
mCrossWindowBlurListener);
} catch (Throwable t) {
// Ignore
}
CrossWindowBlurListeners.getInstance().addListener(mLauncher.getMainExecutor(),
mCrossWindowBlurListener);
mLauncher.getScrimView().addOpaquenessListener(mOpaquenessListener);
// To handle the case where window token is invalid during last setDepth call.
@@ -116,8 +95,7 @@ public class DepthController extends BaseDepthController implements StateHandler
}
/**
* Cleans up after this controller so it can be garbage collected without
* leaving traces.
* Cleans up after this controller so it can be garbage collected without leaving traces.
*/
public void dispose() {
removeSecondaryListeners();
@@ -130,11 +108,7 @@ public class DepthController extends BaseDepthController implements StateHandler
private void removeSecondaryListeners() {
if (mCrossWindowBlurListener != null) {
try {
CrossWindowBlurListeners.getInstance().removeListener(mCrossWindowBlurListener);
} catch (Throwable t) {
// Ignore
}
CrossWindowBlurListeners.getInstance().removeListener(mCrossWindowBlurListener);
}
if (mOpaquenessListener != null) {
mLauncher.getScrimView().removeOpaquenessListener(mOpaquenessListener);
@@ -167,7 +141,7 @@ public class DepthController extends BaseDepthController implements StateHandler
@Override
public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config,
PendingAnimation animation) {
PendingAnimation animation) {
if (config.hasAnimationFlag(SKIP_DEPTH_CONTROLLER)
|| mIgnoreStateChangesDuringMultiWindowAnimation) {
return;
@@ -179,15 +153,9 @@ public class DepthController extends BaseDepthController implements StateHandler
}
@Override
public void applyDepthAndBlur() {
try {
if (LawnchairQuickstepCompat.ATLEAST_R && mEnableDepth) {
ensureDependencies();
super.applyDepthAndBlur();
}
} catch (Throwable t) {
// Ignore
}
protected void applyDepthAndBlur() {
ensureDependencies();
super.applyDepthAndBlur();
}
@Override
@@ -201,7 +169,7 @@ public class DepthController extends BaseDepthController implements StateHandler
mIgnoreStateChangesDuringMultiWindowAnimation = true;
ObjectAnimator mwAnimation = ObjectAnimator.ofFloat(stateDepth, MULTI_PROPERTY_VALUE,
mLauncher.getStateManager().getState().getDepth(mLauncher, isInMultiWindowMode))
mLauncher.getStateManager().getState().getDepth(mLauncher, isInMultiWindowMode))
.setDuration(300);
mwAnimation.addListener(new AnimatorListenerAdapter() {
@Override
@@ -225,5 +193,6 @@ public class DepthController extends BaseDepthController implements StateHandler
writer.println(prefix + "\tmIgnoreStateChangesDuringMultiWindowAnimation="
+ mIgnoreStateChangesDuringMultiWindowAnimation);
writer.println(prefix + "\tmPauseBlurs=" + mPauseBlurs);
writer.println(prefix + "\tmWaitingOnSurfaceValidity=" + mWaitingOnSurfaceValidity);
}
}

View File

@@ -59,7 +59,7 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
import app.lawnchair.LawnchairApp;
import app.lawnchair.icons.LawnchairIconProvider;
import app.lawnchair.compat.LawnchairQuickstepCompat;
/**
* Singleton class to load and manage recents model.
@@ -68,10 +68,9 @@ import app.lawnchair.icons.LawnchairIconProvider;
public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
TaskStackChangeListener, TaskVisualsChangeListener, SafeCloseable {
// We do not need any synchronization for this variable as its only written on
// UI thread.
public static final MainThreadInitializedObject<RecentsModel> INSTANCE = new MainThreadInitializedObject<>(
RecentsModel::new);
// We do not need any synchronization for this variable as its only written on UI thread.
public static final MainThreadInitializedObject<RecentsModel> INSTANCE =
new MainThreadInitializedObject<>(RecentsModel::new);
private static final Executor RECENTS_MODEL_EXECUTOR = Executors.newSingleThreadExecutor(
new SimpleThreadFactory("TaskThumbnailIconCache-", THREAD_PRIORITY_BACKGROUND));
@@ -104,12 +103,11 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
@VisibleForTesting
RecentsModel(Context context, RecentTasksList taskList, TaskIconCache iconCache,
TaskThumbnailCache thumbnailCache, IconProvider iconProvider,
TaskStackChangeListeners taskStackChangeListeners) {
TaskThumbnailCache thumbnailCache, IconProvider iconProvider,
TaskStackChangeListeners taskStackChangeListeners) {
mContext = context;
mTaskList = taskList;
iconProvider = new LawnchairIconProvider(context);
mIconCache = new TaskIconCache(context, RECENTS_MODEL_EXECUTOR, iconProvider);
mIconCache = iconCache;
mIconCache.registerTaskVisualsChangeListener(this);
mThumbnailCache = thumbnailCache;
if (enableGridOnlyOverview()) {
@@ -144,13 +142,11 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
}
/**
* Fetches the list of recent tasks. Tasks are ordered by recency, with the
* latest active tasks
* Fetches the list of recent tasks. Tasks are ordered by recency, with the latest active tasks
* at the end of the list.
*
* @param callback The callback to receive the task plan once its complete or
* null. This is
* always called on the UI thread.
* @param callback The callback to receive the task plan once its complete or null. This is
* always called on the UI thread.
* @return the request id associated with this call.
*/
@Override
@@ -162,12 +158,10 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
/**
* Fetches the list of recent tasks, based on a filter
*
* @param callback The callback to receive the task plan once its complete or
* null. This is
* always called on the UI thread.
* @param filter Returns true if a GroupTask should be included into the list
* passed into
* callback.
* @param callback The callback to receive the task plan once its complete or null. This is
* always called on the UI thread.
* @param filter Returns true if a GroupTask should be included into the list passed into
* callback.
* @return the request id associated with this call.
*/
public int getTasks(@Nullable Consumer<List<GroupTask>> callback, Predicate<GroupTask> filter) {
@@ -175,8 +169,7 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
}
/**
* @return Whether the provided {@param changeId} is the latest recent tasks
* list id.
* @return Whether the provided {@param changeId} is the latest recent tasks list id.
*/
public boolean isTaskListValid(int changeId) {
return mTaskList.isTaskListValid(changeId);
@@ -194,12 +187,10 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
* Checks if a task has been removed or not.
*
* @param callback Receives true if task is removed, false otherwise
* @param filter Returns true if GroupTask should be in the list of
* considerations
* @param filter Returns true if GroupTask should be in the list of considerations
*/
public void isTaskRemoved(int taskId, Consumer<Boolean> callback, Predicate<GroupTask> filter) {
// Invalidate the existing list before checking to ensure this reflects the
// current state in
// Invalidate the existing list before checking to ensure this reflects the current state in
// the system
mTaskList.onRecentTasksChanged();
mTaskList.getTasks(true /* loadKeysOnly */, (taskGroups) -> {
@@ -227,7 +218,8 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
}
// Keep the cache up to date with the latest thumbnails
ActivityManager.RunningTaskInfo runningTask = ActivityManagerWrapper.getInstance().getRunningTask();
ActivityManager.RunningTaskInfo runningTask =
LawnchairQuickstepCompat.getActivityManagerCompat().getRunningTask(true);
int runningTaskId = runningTask != null ? runningTask.id : -1;
mTaskList.getTaskKeys(mThumbnailCache.getCacheSize(), taskGroups -> {
for (GroupTask group : taskGroups) {
@@ -392,4 +384,4 @@ public class RecentsModel implements RecentTasksDataSource, IconChangeListener,
*/
void onRunningTasksChanged();
}
}
}

View File

@@ -64,6 +64,7 @@ import androidx.annotation.WorkerThread;
import com.android.internal.logging.InstanceId;
import com.android.internal.util.ScreenshotRequest;
import com.android.internal.view.AppearanceRegion;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SafeCloseable;
@@ -109,6 +110,8 @@ import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import app.lawnchair.compat.LawnchairQuickstepCompat;
/**
* Holds the reference to SystemUI.
*/
@@ -191,9 +194,17 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
mContext = context;
mAsyncHandler = new Handler(UI_HELPER_EXECUTOR.getLooper(), this::handleMessageAsync);
final Intent baseIntent = new Intent().setPackage(mContext.getPackageName());
mRecentsPendingIntent = PendingIntent.getActivity(mContext, 0, baseIntent,
final ActivityOptions options = ActivityOptions.makeBasic();
if (Utilities.ATLEAST_U) {
options.setPendingIntentCreatorBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
}
mRecentsPendingIntent = LawnchairQuickstepCompat.ATLEAST_V ? PendingIntent.getActivity(mContext, 0, baseIntent,
PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
| Intent.FILL_IN_COMPONENT);
| Intent.FILL_IN_COMPONENT) : PendingIntent.getActivity(mContext, 0, baseIntent,
PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_ALLOW_UNSAFE_IMPLICIT_INTENT
| Intent.FILL_IN_COMPONENT, options.toBundle()) ;
mUnfoldTransitionProvider =
(enableUnfoldStateAnimation() && new ResourceUnfoldTransitionConfig().isEnabled())
@@ -1200,8 +1211,9 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
* if Launcher and SystemUI need to coordinate transactions (eg. for shell transitions).
*/
public void shareTransactionQueue() {
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
if (mOriginalTransactionToken == null) {
// mOriginalTransactionToken = SurfaceControl.Transaction.getDefaultApplyToken();
mOriginalTransactionToken = SurfaceControl.Transaction.getDefaultApplyToken();
}
setupTransactionQueue();
}
@@ -1210,19 +1222,21 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
* Switch back to using Launcher's independent transaction queue.
*/
public void unshareTransactionQueue() {
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
if (mOriginalTransactionToken == null) {
return;
}
// SurfaceControl.Transaction.setDefaultApplyToken(mOriginalTransactionToken);
SurfaceControl.Transaction.setDefaultApplyToken(mOriginalTransactionToken);
mOriginalTransactionToken = null;
}
private void setupTransactionQueue() {
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
if (mOriginalTransactionToken == null) {
return;
}
if (mShellTransitions == null) {
// SurfaceControl.Transaction.setDefaultApplyToken(mOriginalTransactionToken);
SurfaceControl.Transaction.setDefaultApplyToken(mOriginalTransactionToken);
return;
}
final IBinder shellApplyToken;
@@ -1236,7 +1250,7 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
Log.e(TAG, "Didn't receive apply token from Shell");
return;
}
// SurfaceControl.Transaction.setDefaultApplyToken(shellApplyToken);
SurfaceControl.Transaction.setDefaultApplyToken(shellApplyToken);
}
//
@@ -1624,4 +1638,4 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
pw.println("\tmUnfoldAnimationListener=" + mUnfoldAnimationListener);
pw.println("\tmDragAndDrop=" + mDragAndDrop);
}
}
}

View File

@@ -58,7 +58,7 @@ import java.io.PrintWriter;
import java.util.HashMap;
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
public static final boolean ENABLE_SHELL_TRANSITIONS = false;
public static final boolean ENABLE_SHELL_TRANSITIONS = true;
public static final boolean SHELL_TRANSITIONS_ROTATION = ENABLE_SHELL_TRANSITIONS
&& SystemProperties.getBoolean("persist.wm.debug.shell_transit_rotate", false);
@@ -100,11 +100,6 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
TaskAnimationManager(Context ctx) {
mCtx = ctx;
}
SystemUiProxy getSystemUiProxy() {
return SystemUiProxy.INSTANCE.get(mCtx);
}
/**
* Preloads the recents animation.
*/
@@ -158,7 +153,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
final BaseContainerInterface containerInterface = gestureState.getContainerInterface();
mLastGestureState = gestureState;
RecentsAnimationCallbacks newCallbacks = new RecentsAnimationCallbacks(
getSystemUiProxy(), containerInterface.allowMinimizeSplitScreen());
SystemUiProxy.INSTANCE.get(mCtx), containerInterface.allowMinimizeSplitScreen());
mCallbacks = newCallbacks;
mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() {
@Override
@@ -265,7 +260,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
}
RemoteAnimationTarget[] nonAppTargets = ENABLE_SHELL_TRANSITIONS
? null : getSystemUiProxy().onStartingSplitLegacy(
? null : SystemUiProxy.INSTANCE.get(mCtx).onStartingSplitLegacy(
appearedTaskTargets);
if (nonAppTargets == null) {
nonAppTargets = new RemoteAnimationTarget[0];
@@ -332,13 +327,12 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
if (ENABLE_SHELL_TRANSITIONS) {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setPendingIntentBackgroundActivityLaunchAllowedByPermission(true);
// Use regular (non-transient) launch for all apps page to control IME.
if (!containerInterface.allowAllAppsFromOverview()) {
options.setTransientLaunch();
}
options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
mRecentsAnimationStartPending = getSystemUiProxy()
mRecentsAnimationStartPending = SystemUiProxy.INSTANCE.get(mCtx)
.startRecentsActivity(intent, options, mCallbacks);
if (enableHandleDelayedGestureCallbacks()) {
ActiveGestureLog.INSTANCE.addLog(new ActiveGestureLog.CompoundString(
@@ -546,4 +540,4 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
mLastGestureState.dump(prefix + '\t', pw);
}
}
}
}

View File

@@ -162,7 +162,7 @@ public class TouchInteractionService extends Service {
private static final String TAG = "TouchInteractionService";
private static final ConstantItem<Boolean> HAS_ENABLED_QUICKSTEP_ONCE = backedUpItem(
"launcher.has_enabled_quickstep_once", false, EncryptionType.ENCRYPTED);
"launcher.has_enabled_quickstep_once", true, EncryptionType.ENCRYPTED);
private final TISBinder mTISBinder = new TISBinder(this);

View File

@@ -16,9 +16,11 @@
package com.android.quickstep.util
import android.annotation.BinderThread
import android.graphics.Region
import android.util.Log
import android.view.Display.DEFAULT_DISPLAY
import android.view.ISystemGestureExclusionListener
import android.view.IWindowManager
import android.view.WindowManagerGlobal
import androidx.annotation.VisibleForTesting
@@ -33,26 +35,25 @@ class GestureExclusionManager(private val windowManager: IWindowManager) {
private var lastUnrestrictedOrNull: Region? = null
@VisibleForTesting
val exclusionListener = null
// object : ISystemGestureExclusionListener.Stub() {
// @BinderThread
// override fun onSystemGestureExclusionChanged(
// displayId: Int,
// exclusionRegion: Region?,
// unrestrictedOrNull: Region?
// ) {
// if (displayId != DEFAULT_DISPLAY) {
// return
// }
// Executors.MAIN_EXECUTOR.execute {
// lastExclusionRegion = exclusionRegion
// lastUnrestrictedOrNull = unrestrictedOrNull
// listeners.forEach {
// it.onGestureExclusionChanged(exclusionRegion, unrestrictedOrNull)
// }
// }
// }
// }
val exclusionListener = object : ISystemGestureExclusionListener.Stub() {
@BinderThread
override fun onSystemGestureExclusionChanged(
displayId: Int,
exclusionRegion: Region?,
unrestrictedOrNull: Region?
) {
if (displayId != DEFAULT_DISPLAY) {
return
}
Executors.MAIN_EXECUTOR.execute {
lastExclusionRegion = exclusionRegion
lastUnrestrictedOrNull = unrestrictedOrNull
listeners.forEach {
it.onGestureExclusionChanged(exclusionRegion, unrestrictedOrNull)
}
}
}
}
/** Adds a listener for receiving gesture exclusion regions */
fun addListener(listener: ExclusionListener) {

View File

@@ -41,7 +41,6 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SNAP_TO_50_
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.NonNull;
import android.annotation.RequiresApi;
import android.annotation.UiThread;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -53,7 +52,6 @@ import android.content.pm.ShortcutInfo;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -170,10 +168,28 @@ public class SplitSelectStateController {
*/
private Pair<InstanceId, com.android.launcher3.logging.InstanceId> mSessionInstanceIds;
private final BackPressHandler mSplitBackHandler = new BackPressHandler() {
@Override
public boolean canHandleBack() {
return FeatureFlags.enableSplitContextually() && isSplitSelectActive();
}
@Override
public void onBackInvoked() {
// When exiting from split selection, leave current context to go to
// homescreen as well
getSplitAnimationController().playPlaceholderDismissAnim(mContainer,
LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
if (mActivityBackCallback != null) {
mActivityBackCallback.run();
}
}
};
public SplitSelectStateController(RecentsViewContainer container, Handler handler,
StateManager stateManager, DepthController depthController,
StatsLogManager statsLogManager, SystemUiProxy systemUiProxy, RecentsModel recentsModel,
Runnable activityBackCallback) {
StateManager stateManager, DepthController depthController,
StatsLogManager statsLogManager, SystemUiProxy systemUiProxy, RecentsModel recentsModel,
Runnable activityBackCallback) {
mContainer = container;
mHandler = handler;
mStatsLogManager = statsLogManager;
@@ -203,8 +219,8 @@ public class SplitSelectStateController {
* @param intent will be ignored if @param alreadyRunningTask is set
*/
public void setInitialTaskSelect(@Nullable Intent intent, @StagePosition int stagePosition,
@NonNull ItemInfo itemInfo, StatsLogManager.EventEnum splitEvent,
int alreadyRunningTask) {
@NonNull ItemInfo itemInfo, StatsLogManager.EventEnum splitEvent,
int alreadyRunningTask) {
mSplitSelectDataHolder.setInitialTaskSelect(intent, stagePosition, itemInfo, splitEvent,
alreadyRunningTask);
createAndLogInstanceIdsForSession();
@@ -215,8 +231,8 @@ public class SplitSelectStateController {
* running app.
*/
public void setInitialTaskSelect(ActivityManager.RunningTaskInfo info,
@StagePosition int stagePosition, @NonNull ItemInfo itemInfo,
StatsLogManager.EventEnum splitEvent) {
@StagePosition int stagePosition, @NonNull ItemInfo itemInfo,
StatsLogManager.EventEnum splitEvent) {
mSplitSelectDataHolder.setInitialTaskSelect(info, stagePosition, itemInfo, splitEvent);
createAndLogInstanceIdsForSession();
}
@@ -231,7 +247,7 @@ public class SplitSelectStateController {
* tasks (i.e. searching for a running pair of tasks.)
*/
public void findLastActiveTasksAndRunCallback(@Nullable List<ComponentKey> componentKeys,
boolean findExactPairMatch, Consumer<Task[]> callback) {
boolean findExactPairMatch, Consumer<Task[]> callback) {
mRecentTasksModel.getTasks(taskGroups -> {
if (componentKeys == null || componentKeys.isEmpty()) {
callback.accept(new Task[]{});
@@ -301,7 +317,7 @@ public class SplitSelectStateController {
* both permutations because task order is not guaranteed in GroupTasks.
*/
public boolean isInstanceOfAppPair(GroupTask groupTask, @NonNull ComponentKey componentKey1,
@NonNull ComponentKey componentKey2) {
@NonNull ComponentKey componentKey2) {
return ((isInstanceOfComponent(groupTask.task1, componentKey1)
&& isInstanceOfComponent(groupTask.task2, componentKey2))
||
@@ -335,7 +351,7 @@ public class SplitSelectStateController {
* animations are complete.
*/
public void launchSplitTasks(@PersistentSnapPosition int snapPosition,
@Nullable Consumer<Boolean> callback) {
@Nullable Consumer<Boolean> callback) {
launchTasks(callback, false /* freezeTaskList */, snapPosition, mSessionInstanceIds.first);
mStatsLogManager.logger()
@@ -420,7 +436,7 @@ public class SplitSelectStateController {
* foreground (quickswitch, launching previous pairs from overview)
*/
public void launchTasks(@Nullable Consumer<Boolean> callback, boolean freezeTaskList,
@PersistentSnapPosition int snapPosition, @Nullable InstanceId shellInstanceId) {
@PersistentSnapPosition int snapPosition, @Nullable InstanceId shellInstanceId) {
TestLogging.recordEvent(
TestProtocol.SEQUENCE_MAIN, "launchSplitTasks");
final ActivityOptions options1 = ActivityOptions.makeBasic();
@@ -524,9 +540,9 @@ public class SplitSelectStateController {
* GroupedTaskView, int, int, int, Consumer, boolean, int, RemoteTransition)}
*/
public void launchExistingSplitPair(@Nullable GroupedTaskView groupedTaskView,
int firstTaskId, int secondTaskId, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList,
@PersistentSnapPosition int snapPosition) {
int firstTaskId, int secondTaskId, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList,
@PersistentSnapPosition int snapPosition) {
launchExistingSplitPair(
groupedTaskView,
firstTaskId,
@@ -549,9 +565,9 @@ public class SplitSelectStateController {
* NOTE: This is not to be used to launch AppPairs.
*/
public void launchExistingSplitPair(@Nullable GroupedTaskView groupedTaskView,
int firstTaskId, int secondTaskId, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList,
@PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition) {
int firstTaskId, int secondTaskId, @StagePosition int stagePosition,
Consumer<Boolean> callback, boolean freezeTaskList,
@PersistentSnapPosition int snapPosition, @Nullable RemoteTransition remoteTransition) {
mLaunchingTaskView = groupedTaskView;
final ActivityOptions options1 = ActivityOptions.makeBasic();
if (freezeTaskList) {
@@ -562,7 +578,7 @@ public class SplitSelectStateController {
if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
final RemoteTransition transition = remoteTransition == null
? getShellRemoteTransition(
firstTaskId, secondTaskId, callback, "LaunchExistingPair")
firstTaskId, secondTaskId, callback, "LaunchExistingPair")
: remoteTransition;
mSystemUiProxy.startTasks(firstTaskId, optionsBundle, secondTaskId, null /* options2 */,
stagePosition, snapPosition, transition, null /*shellInstanceId*/);
@@ -633,7 +649,7 @@ public class SplitSelectStateController {
* Init {@code SplitFromDesktopController}
*/
public void initSplitFromDesktopController(QuickstepLauncher launcher,
OverviewComponentObserver overviewComponentObserver) {
OverviewComponentObserver overviewComponentObserver) {
initSplitFromDesktopController(
new SplitFromDesktopController(launcher, overviewComponentObserver));
}
@@ -644,7 +660,7 @@ public class SplitSelectStateController {
}
private RemoteTransition getShellRemoteTransition(int firstTaskId, int secondTaskId,
@Nullable Consumer<Boolean> callback, String transitionName) {
@Nullable Consumer<Boolean> callback, String transitionName) {
final RemoteSplitLaunchTransitionRunner animationRunner =
new RemoteSplitLaunchTransitionRunner(firstTaskId, secondTaskId, callback);
return new RemoteTransition(animationRunner,
@@ -652,7 +668,7 @@ public class SplitSelectStateController {
}
private RemoteAnimationAdapter getLegacyRemoteAdapter(int firstTaskId, int secondTaskId,
@Nullable Consumer<Boolean> callback) {
@Nullable Consumer<Boolean> callback) {
final RemoteSplitLaunchAnimationRunner animationRunner =
new RemoteSplitLaunchAnimationRunner(firstTaskId, secondTaskId, callback);
return new RemoteAnimationAdapter(animationRunner, 300, 150,
@@ -725,7 +741,7 @@ public class SplitSelectStateController {
private Consumer<Boolean> mFinishCallback;
RemoteSplitLaunchTransitionRunner(int initialTaskId, int secondTaskId,
@Nullable Consumer<Boolean> callback) {
@Nullable Consumer<Boolean> callback) {
mInitialTaskId = initialTaskId;
mSecondTaskId = secondTaskId;
mFinishCallback = callback;
@@ -733,8 +749,8 @@ public class SplitSelectStateController {
@Override
public void startAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishedCallback) {
SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishedCallback) {
final Runnable finishAdapter = () -> {
try {
finishedCallback.onTransitionFinished(null /* wct */, null /* sct */);
@@ -799,7 +815,7 @@ public class SplitSelectStateController {
private final Consumer<Boolean> mSuccessCallback;
RemoteSplitLaunchAnimationRunner(int initialTaskId, int secondTaskId,
@Nullable Consumer<Boolean> successCallback) {
@Nullable Consumer<Boolean> successCallback) {
mInitialTaskId = initialTaskId;
mSecondTaskId = secondTaskId;
mSuccessCallback = successCallback;
@@ -807,8 +823,8 @@ public class SplitSelectStateController {
@Override
public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
Runnable finishedCallback) {
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
Runnable finishedCallback) {
postAsyncCallback(mHandler,
() -> mSplitAnimationController.playSplitLaunchAnimation(mLaunchingTaskView,
mLaunchingIconView, mInitialTaskId, mSecondTaskId, apps, wallpapers,
@@ -923,25 +939,8 @@ public class SplitSelectStateController {
mLaunchingIconView = launchingIconView;
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public BackPressHandler getSplitBackHandler() {
return new BackPressHandler() {
@Override
public boolean canHandleBack() {
return FeatureFlags.enableSplitContextually() && isSplitSelectActive();
}
@Override
public void onBackInvoked() {
// When exiting from split selection, leave current context to go to
// homescreen as well
getSplitAnimationController().playPlaceholderDismissAnim(mContainer,
LAUNCHER_SPLIT_SELECTION_EXIT_HOME);
if (mActivityBackCallback != null) {
mActivityBackCallback.run();
}
}
};
return mSplitBackHandler;
}
public void dump(String prefix, PrintWriter writer) {
@@ -962,7 +961,7 @@ public class SplitSelectStateController {
private Drawable mAppIcon;
public SplitFromDesktopController(QuickstepLauncher launcher,
OverviewComponentObserver overviewComponentObserver) {
OverviewComponentObserver overviewComponentObserver) {
mLauncher = launcher;
mOverviewComponentObserver = overviewComponentObserver;
mSplitPlaceholderSize = mLauncher.getResources().getDimensionPixelSize(
@@ -972,7 +971,7 @@ public class SplitSelectStateController {
mSplitSelectListener = new ISplitSelectListener.Stub() {
@Override
public boolean onRequestSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
int splitPosition, Rect taskBounds) {
int splitPosition, Rect taskBounds) {
MAIN_EXECUTOR.execute(() -> enterSplitSelect(taskInfo, splitPosition,
taskBounds));
return true;
@@ -994,14 +993,14 @@ public class SplitSelectStateController {
* @param taskBounds the bounds of the task, used for {@link FloatingTaskView} animation
*/
public void enterSplitSelect(ActivityManager.RunningTaskInfo taskInfo,
int splitPosition, Rect taskBounds) {
int splitPosition, Rect taskBounds) {
mTaskInfo = taskInfo;
String packageName = mTaskInfo.realActivity.getPackageName();
PackageManager pm = mLauncher.getApplicationContext().getPackageManager();
IconProvider provider = new IconProvider(mLauncher.getApplicationContext());
try {
mAppIcon = provider.getIcon(pm.getActivityInfo(mTaskInfo.baseActivity,
PackageManager.ComponentInfoFlags.of(0)));
PackageManager.ComponentInfoFlags.of(0)));
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Package not found: " + packageName, e);
}
@@ -1036,11 +1035,11 @@ public class SplitSelectStateController {
@Override
public void onRecentsAnimationStart(RecentsAnimationController controller,
RecentsAnimationTargets targets) {
RecentsAnimationTargets targets) {
StatsLogManager.LauncherEvent launcherDesktopSplitEvent =
mSplitPosition == STAGE_POSITION_BOTTOM_OR_RIGHT ?
LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM :
LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP;
LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM :
LAUNCHER_DESKTOP_MODE_SPLIT_LEFT_TOP;
setInitialTaskSelect(mTaskInfo, mSplitPosition,
null, launcherDesktopSplitEvent);
@@ -1076,4 +1075,4 @@ public class SplitSelectStateController {
}
}
}
}
}

View File

@@ -15,6 +15,8 @@
*/
package com.android.quickstep.util;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.view.SurfaceControl;
@@ -23,8 +25,6 @@ import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.ViewRootImpl;
import androidx.annotation.NonNull;
import com.android.quickstep.RemoteAnimationTargets.ReleaseCheck;
import app.lawnchair.compat.LawnchairQuickstepCompat;
@@ -34,6 +34,7 @@ import app.lawnchair.compat.LawnchairQuickstepCompat;
* android.view.SyncRtSurfaceTransactionApplier
* with some Launcher specific utility methods
*/
@TargetApi(Build.VERSION_CODES.R)
public class SurfaceTransactionApplier extends ReleaseCheck {
private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
@@ -49,7 +50,7 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
/**
* @param targetView The view in the surface that acts as synchronization anchor.
*/
public SurfaceTransactionApplier(@NonNull View targetView) {
public SurfaceTransactionApplier(View targetView) {
if (targetView.isAttachedToWindow()) {
initialize(targetView);
} else {
@@ -75,7 +76,7 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
private void initialize(View view) {
mTargetViewRootImpl = view.getViewRootImpl();
// mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
mBarrierSurfaceControl = mTargetViewRootImpl.getSurfaceControl();
mInitialized = true;
}
@@ -108,7 +109,7 @@ public class SurfaceTransactionApplier extends ReleaseCheck {
final int toApplySeqNo = mLastSequenceNumber;
setCanRelease(false);
mTargetViewRootImpl.registerRtFrameCallback(frame -> {
if (mBarrierSurfaceControl == null && !mBarrierSurfaceControl.isValid()) {
if (mBarrierSurfaceControl == null || !mBarrierSurfaceControl.isValid()) {
Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
.sendToTarget();
return;

View File

@@ -59,8 +59,7 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.recents.utilities.PreviewPositionHelper;
/**
* A utility class which emulates the layout behavior of TaskView and
* RecentsView
* A utility class which emulates the layout behavior of TaskView and RecentsView
*/
public class TaskViewSimulator implements TransformParams.BuilderProxy {
@@ -100,7 +99,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
private final FullscreenDrawParams mCurrentFullscreenParams;
public final AnimatedFloat taskPrimaryTranslation = new AnimatedFloat();
public final AnimatedFloat taskSecondaryTranslation = new AnimatedFloat();
public final AnimatedFloat scrollScale = new AnimatedFloat();
// Carousel properties
public final AnimatedFloat carouselScale = new AnimatedFloat();
@@ -130,8 +128,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
mSizeStrategy = sizeStrategy;
mOrientationState = TraceHelper.allowIpcs("TaskViewSimulator.init",
() -> new RecentsOrientedState(context, sizeStrategy, i -> {
}));
() -> new RecentsOrientedState(context, sizeStrategy, i -> { }));
mOrientationState.setGestureActive(true);
mCurrentFullscreenParams = new FullscreenDrawParams(context);
mOrientationStateId = mOrientationState.getStateId();
@@ -170,8 +167,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
if (mSplitBounds != null) {
// The task rect changes according to the staged split task sizes, but recents
// fullscreen scale and pivot remains the same since the task fits into the
// existing
// fullscreen scale and pivot remains the same since the task fits into the existing
// sized task space bounds
mTaskRect.set(mFullTaskSize);
mOrientationState.getOrientationHandler()
@@ -179,10 +175,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
mTaskRect.offset(mTaskRectTranslationX, mTaskRectTranslationY);
} else if (mIsDesktopTask) {
// For desktop, tasks can take up only part of the screen size.
// Full task size represents the whole screen size, but scaled down to fit in
// recents.
// Task rect will represent the scaled down thumbnail position and is placed
// inside
// Full task size represents the whole screen size, but scaled down to fit in recents.
// Task rect will represent the scaled down thumbnail position and is placed inside
// full task size as it is on the home screen.
PointF fullscreenTaskDimension = new PointF();
BaseActivityInterface.getTaskDimension(mContext, mDp, fullscreenTaskDimension);
@@ -213,8 +207,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
if (mDp == null) {
return 1;
}
// Copy mFullTaskSize instead of updating it directly so it could be reused next
// time
// Copy mFullTaskSize instead of updating it directly so it could be reused next time
// without recalculating
Rect scaleRect = new Rect();
if (mScaleToCarouselTaskSize) {
@@ -242,8 +235,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Sets the targets which the simulator will control specifically for targets to
* animate when
* Sets the targets which the simulator will control specifically for targets to animate when
* in split screen
*
* @param splitInfo set to {@code null} when not in staged split mode
@@ -255,8 +247,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
mStagePosition = STAGE_POSITION_UNDEFINED;
} else {
mStagePosition = runningTarget.taskId == splitInfo.leftTopTaskId
? STAGE_POSITION_TOP_OR_LEFT
: STAGE_POSITION_BOTTOM_OR_RIGHT;
? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT;
mPositionHelper.setSplitBounds(convertLauncherSplitBoundsToShell(mSplitBounds),
mStagePosition);
}
@@ -311,17 +302,14 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Adds animation for all the components corresponding to transition from an app
* to overview.
* Adds animation for all the components corresponding to transition from an app to overview.
*/
public void addAppToOverviewAnim(PendingAnimation pa, Interpolator interpolator) {
pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 1, 0, interpolator);
float fullScreenScale;
if (enableGridOnlyOverview() && mDp.isTablet && mDp.isGestureMode) {
// Move pivot to top right edge of the screen, to avoid task scaling down in
// opposite
// direction of app window movement, otherwise the animation will wiggle left
// and right.
// Move pivot to top right edge of the screen, to avoid task scaling down in opposite
// direction of app window movement, otherwise the animation will wiggle left and right.
// Also translate the app window to top right edge of the screen to simplify
// calculations.
taskPrimaryTranslation.value = mIsRecentsRtl
@@ -330,8 +318,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
taskSecondaryTranslation.value = -mFullTaskSize.top;
mPivotOverride = new PointF(mIsRecentsRtl ? mDp.widthPx : 0, 0);
// Scale down to the carousel and use the carousel Rect to calculate
// fullScreenScale.
// Scale down to the carousel and use the carousel Rect to calculate fullScreenScale.
mScaleToCarouselTaskSize = true;
carouselScale.value = mCarouselTaskSize.width() / (float) mFullTaskSize.width();
fullScreenScale = getFullScreenScale();
@@ -344,18 +331,15 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
// Expected carousel position's center is in the middle, and invariant of
// recentsViewScale.
float exceptedCarouselCenterX = mCarouselTaskSize.centerX();
// Animating carousel translations linearly will result in a curved path,
// therefore
// we'll need to calculate the expected translation at each recentsView scale.
// Luckily
// primary and secondary follow the same translation, and primary is used here
// due to
// Animating carousel translations linearly will result in a curved path, therefore
// we'll need to calculate the expected translation at each recentsView scale. Luckily
// primary and secondary follow the same translation, and primary is used here due to
// it being simpler.
Interpolator carouselTranslationInterpolator = t -> {
// recentsViewScale is calculated rather than using recentsViewScale.value, so
// that
// recentsViewScale is calculated rather than using recentsViewScale.value, so that
// this interpolator works independently even if recentsViewScale don't animate.
float recentsViewScale = Utilities.mapToRange(t, 0, 1, fullScreenScale, 1, Interpolators.LINEAR);
float recentsViewScale =
Utilities.mapToRange(t, 0, 1, fullScreenScale, 1, Interpolators.LINEAR);
// Without the translation, the app window will animate from fullscreen into top
// right corner.
float expectedTaskCenterX = mIsRecentsRtl
@@ -363,7 +347,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
: mCarouselTaskSize.width() * recentsViewScale / 2f;
// Calculate the expected translation, then work back the animatedFraction that
// results in this value.
float carouselPrimaryTranslation = (exceptedCarouselCenterX - expectedTaskCenterX) / recentsViewScale;
float carouselPrimaryTranslation =
(exceptedCarouselCenterX - expectedTaskCenterX) / recentsViewScale;
return carouselPrimaryTranslation / carouselPrimaryTranslationTarget;
};
@@ -380,8 +365,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Adds animation for all the components corresponding to transition from
* overview to the app.
* Adds animation for all the components corresponding to transition from overview to the app.
*/
public void addOverviewToAppAnim(PendingAnimation pa, TimeInterpolator interpolator) {
pa.addFloat(fullScreenProgress, AnimatedFloat.VALUE, 0, 1, interpolator);
@@ -389,8 +373,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Returns the current clipped/visible window bounds in the window coordinate
* space
* Returns the current clipped/visible window bounds in the window coordinate space
*/
public RectF getCurrentCropRect() {
// Crop rect is the inverse of thumbnail matrix
@@ -423,15 +406,14 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Applies the rotation on the matrix to so that it maps from launcher
* coordinate space to
* Applies the rotation on the matrix to so that it maps from launcher coordinate space to
* window coordinate space.
*/
public void applyWindowToHomeRotation(Matrix matrix) {
matrix.postTranslate(mDp.windowX, mDp.windowY);
postDisplayRotation(deltaRotation(
mOrientationState.getRecentsActivityRotation(),
mOrientationState.getDisplayRotation()),
mOrientationState.getRecentsActivityRotation(),
mOrientationState.getDisplayRotation()),
mDp.widthPx, mDp.heightPx, matrix);
}
@@ -443,8 +425,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Applies the target to the previously set parameters, optionally with an
* overridden
* Applies the target to the previously set parameters, optionally with an overridden
* surface transaction
*/
public void apply(TransformParams params, @Nullable SurfaceTransaction surfaceTransaction) {
@@ -457,8 +438,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
getFullScreenScale();
if (TaskAnimationManager.SHELL_TRANSITIONS_ROTATION) {
// With shell transitions, the display is rotated early so we need to actually
// use
// With shell transitions, the display is rotated early so we need to actually use
// the rotation when the gesture starts
mThumbnailData.rotation = mOrientationState.getTouchRotation();
} else {
@@ -477,7 +457,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
float fullScreenProgress = Utilities.boundToRange(this.fullScreenProgress.value, 0, 1);
float scrollScale = this.scrollScale.value * (1f - fullScreenProgress) + fullScreenProgress;
mCurrentFullscreenParams.setProgress(fullScreenProgress, recentsViewScale.value,
carouselScale.value);
@@ -489,8 +468,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
// Apply TaskView matrix: taskRect, translate
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
mMatrix.postScale(scrollScale, scrollScale, mTaskRect.left + (mTaskRect.width() / 2),
mTaskRect.top + (mTaskRect.height() / 2));
mOrientationState.getOrientationHandler().setPrimary(mMatrix, MATRIX_POST_TRANSLATE,
taskPrimaryTranslation.value);
mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
@@ -520,8 +497,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
params.setProgress(1f - fullScreenProgress);
params.applySurfaceParams(surfaceTransaction == null
? params.createSurfaceParams(this)
: surfaceTransaction);
? params.createSurfaceParams(this) : surfaceTransaction);
if (!DEBUG) {
return;
@@ -540,9 +516,8 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
+ " recentsPrimaryT: " + recentsViewPrimaryTranslation.value
+ " recentsSecondaryT: " + recentsViewSecondaryTranslation.value
+ " recentsScroll: " + recentsViewScroll.value
+ " scrollScale: " + scrollScale
+ " this.scrollScale.value: " + this.scrollScale.value
+ " pivot: " + mPivot);
+ " pivot: " + mPivot
);
}
@Override
@@ -555,12 +530,9 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
// If mDrawsBelowRecents is unset, no reordering will be enforced.
if (mDrawsBelowRecents != null) {
// In legacy transitions, the animation leashes remain in same hierarchy in the
// TaskDisplayArea, so we don't want to bump the layer too high otherwise it
// will
// conflict with layers that WM core positions (ie. the input consumers). For
// shell
// transitions, the animation leashes are reparented to an animation container
// so we
// TaskDisplayArea, so we don't want to bump the layer too high otherwise it will
// conflict with layers that WM core positions (ie. the input consumers). For shell
// transitions, the animation leashes are reparented to an animation container so we
// can bump layers as needed.
if (ENABLE_SHELL_TRANSITIONS) {
builder.setLayer(mDrawsBelowRecents
@@ -576,8 +548,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
}
/**
* Returns the corner radius that should be applied to the target so that it
* matches the
* Returns the corner radius that should be applied to the target so that it matches the
* TaskView
*/
public float getCurrentCornerRadius() {
@@ -586,8 +557,7 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
mTempPoint[1] = 0;
mInversePositionMatrix.mapVectors(mTempPoint);
// Ideally we should use square-root. This is an optimization as one of the
// dimension is 0.
// Ideally we should use square-root. This is an optimization as one of the dimension is 0.
return Math.max(Math.abs(mTempPoint[0]), Math.abs(mTempPoint[1]));
}
}
}

View File

@@ -16,46 +16,40 @@
package com.android.quickstep.util;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import android.util.FloatProperty;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import com.android.app.animation.Interpolators;
import com.android.launcher3.Utilities;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import app.lawnchair.compat.LawnchairQuickstepCompat;
public class TransformParams {
public static FloatProperty<TransformParams> PROGRESS = new FloatProperty<TransformParams>("progress") {
@Override
public void setValue(TransformParams params, float v) {
params.setProgress(v);
}
public static FloatProperty<TransformParams> PROGRESS =
new FloatProperty<TransformParams>("progress") {
@Override
public void setValue(TransformParams params, float v) {
params.setProgress(v);
}
@Override
public Float get(TransformParams params) {
return params.getProgress();
}
};
@Override
public Float get(TransformParams params) {
return params.getProgress();
}
};
public static FloatProperty<TransformParams> TARGET_ALPHA = new FloatProperty<TransformParams>("targetAlpha") {
@Override
public void setValue(TransformParams params, float v) {
params.setTargetAlpha(v);
}
public static FloatProperty<TransformParams> TARGET_ALPHA =
new FloatProperty<TransformParams>("targetAlpha") {
@Override
public void setValue(TransformParams params, float v) {
params.setTargetAlpha(v);
}
@Override
public Float get(TransformParams params) {
return params.getTargetAlpha();
}
};
@Override
public Float get(TransformParams params) {
return params.getTargetAlpha();
}
};
/** Progress from 0 to 1 where 0 is in-app and 1 is Overview */
private float mProgress;
@@ -74,12 +68,9 @@ public class TransformParams {
}
/**
* Sets the progress of the transformation, where 0 is the source and 1 is the
* target. We
* automatically adjust properties such as currentRect and cornerRadius based on
* this
* progress, unless they are manually overridden by setting them on this
* TransformParams.
* Sets the progress of the transformation, where 0 is the source and 1 is the target. We
* automatically adjust properties such as currentRect and cornerRadius based on this
* progress, unless they are manually overridden by setting them on this TransformParams.
*/
public TransformParams setProgress(float progress) {
mProgress = progress;
@@ -87,10 +78,8 @@ public class TransformParams {
}
/**
* Sets the corner radius of the transformed window, in pixels. If unspecified
* (-1), we
* simply interpolate between the window's corner radius to the task view's
* corner radius,
* Sets the corner radius of the transformed window, in pixels. If unspecified (-1), we
* simply interpolate between the window's corner radius to the task view's corner radius,
* based on {@link #mProgress}.
*/
public TransformParams setCornerRadius(float cornerRadius) {
@@ -107,12 +96,9 @@ public class TransformParams {
}
/**
* Specifies the set of RemoteAnimationTargetCompats that are included in the
* transformation
* that these TransformParams help compute. These TransformParams generally only
* apply to
* the targetSet.apps which match the targetSet.targetMode (e.g. the
* MODE_CLOSING app when
* Specifies the set of RemoteAnimationTargetCompats that are included in the transformation
* that these TransformParams help compute. These TransformParams generally only apply to
* the targetSet.apps which match the targetSet.targetMode (e.g. the MODE_CLOSING app when
* swiping to home).
*/
public TransformParams setTargetSet(RemoteAnimationTargets targetSet) {
@@ -121,8 +107,7 @@ public class TransformParams {
}
/**
* Sets the SyncRtSurfaceTransactionApplierCompat that will apply the
* SurfaceParams that
* Sets the SyncRtSurfaceTransactionApplierCompat that will apply the SurfaceParams that
* are computed based on these TransformParams.
*/
public TransformParams setSyncTransactionApplier(SurfaceTransactionApplier applier) {
@@ -131,8 +116,7 @@ public class TransformParams {
}
/**
* Sets an alternate function to control transform for non-target apps. The
* default
* Sets an alternate function to control transform for non-target apps. The default
* implementation keeps the targets visible with alpha=1
*/
public TransformParams setBaseBuilderProxy(BuilderProxy proxy) {
@@ -165,19 +149,7 @@ public class TransformParams {
if (activityType == ACTIVITY_TYPE_HOME) {
mHomeBuilderProxy.onBuildTargetParams(builder, app, this);
} else {
// Fade out translucent overlay.
// TODO(b/303351074): use app.isNotInRecents directly once it is fixed.
boolean isNotInRecents = LawnchairQuickstepCompat.ATLEAST_S && app.taskInfo != null
&& (app.taskInfo.baseIntent.getFlags()
& FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
if (app.isTranslucent && isNotInRecents) {
float progress = Utilities.boundToRange(getProgress(), 0, 1);
builder.setAlpha(1 - Interpolators.DECELERATE_QUINT
.getInterpolation(progress));
} else {
builder.setAlpha(getTargetAlpha());
}
builder.setAlpha(getTargetAlpha());
proxy.onBuildTargetParams(builder, app, this);
}
} else {
@@ -223,11 +195,10 @@ public class TransformParams {
@FunctionalInterface
public interface BuilderProxy {
BuilderProxy NO_OP = (builder, app, params) -> {
};
BuilderProxy NO_OP = (builder, app, params) -> { };
BuilderProxy ALWAYS_VISIBLE = (builder, app, params) -> builder.setAlpha(1);
void onBuildTargetParams(SurfaceProperties builder,
RemoteAnimationTarget app, TransformParams params);
RemoteAnimationTarget app, TransformParams params);
}
}
}

View File

@@ -438,4 +438,8 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
mSaveAppPairButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
appPairIconRes, 0, 0, 0);
}
protected void setClearAllClickListener(OnClickListener listener) {
// No-op
}
}

View File

@@ -1103,6 +1103,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
mActionsView.updateFor3pLauncher(!supportsAppPairs());
mSplitSelectStateController = splitController;
mDesktopRecentsTransitionController = desktopRecentsTransitionController;
mActionsView.setClearAllClickListener(this::dismissAllTasks);
}
public SplitSelectStateController getSplitSelectController() {

View File

@@ -16,9 +16,12 @@
package com.android.launcher3.model;
import static com.android.launcher3.BuildConfigs.WIDGET_ON_FIRST_SCREEN;
import static com.android.launcher3.Flags.enableLauncherBrMetricsFixed;
import static com.android.launcher3.Flags.enableSmartspaceAsAWidget;
import static com.android.launcher3.Flags.enableSmartspaceRemovalToggle;
import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
import static com.android.launcher3.LauncherPrefs.SHOULD_SHOW_SMARTSPACE;
import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
@@ -186,8 +189,7 @@ public class LoaderTask implements Runnable {
LooperIdleLock idleLock = mLauncherBinder.newIdleLock(this);
// Just in case mFlushingWorkerThread changes but we aren't woken up,
// wait no longer than 1sec at a time
while (!mStopped && idleLock.awaitLocked(1000))
;
while (!mStopped && idleLock.awaitLocked(1000));
}
private synchronized void verifyNotStopped() throws CancellationException {
@@ -340,17 +342,17 @@ public class LoaderTask implements Runnable {
verifyNotStopped();
LauncherPrefs prefs = LauncherPrefs.get(mApp.getContext());
// if (enableSmartspaceAsAWidget() && prefs.get(SHOULD_SHOW_SMARTSPACE)) {
// mLauncherBinder.bindSmartspaceWidget();
// // Turn off pref.
// prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(false));
// logASplit("bindSmartspaceWidget");
// verifyNotStopped();
// } else if (!enableSmartspaceAsAWidget() && WIDGET_ON_FIRST_SCREEN
// && !prefs.get(LauncherPrefs.SHOULD_SHOW_SMARTSPACE)) {
// // Turn on pref.
// prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(true));
// }
if (enableSmartspaceAsAWidget() && prefs.get(SHOULD_SHOW_SMARTSPACE)) {
mLauncherBinder.bindSmartspaceWidget();
// Turn off pref.
prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(false));
logASplit("bindSmartspaceWidget");
verifyNotStopped();
} else if (!enableSmartspaceAsAWidget() && WIDGET_ON_FIRST_SCREEN
&& !prefs.get(SHOULD_SHOW_SMARTSPACE)) {
// Turn on pref.
prefs.putSync(SHOULD_SHOW_SMARTSPACE.to(true));
}
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);

View File

@@ -34,8 +34,13 @@ object LawnchairQuickstepCompat {
@JvmField
val ATLEAST_U: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.VANILLA_ICE_CREAM)
@JvmField
val ATLEAST_V: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
@JvmStatic
val factory: QuickstepCompatFactory = when {
ATLEAST_V -> QuickstepCompatFactoryVU()
ATLEAST_U -> QuickstepCompatFactoryVU()
ATLEAST_T -> QuickstepCompatFactoryVT()
ATLEAST_S -> QuickstepCompatFactoryVS()

View File

@@ -36,6 +36,8 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
import java.util.ArrayList;
import java.util.List;
import app.lawnchair.compat.LawnchairQuickstepCompat;
/**
* Tracks all the task stack listeners
*/
@@ -167,7 +169,8 @@ public class TaskStackChangeListeners {
if (!mRegistered) {
// Register mTaskStackListener to IActivityManager only once if needed.
try {
// ActivityTaskManager.getService().registerTaskStackListener(this);
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
ActivityTaskManager.getService().registerTaskStackListener(this);
mRegistered = true;
} catch (Exception e) {
Log.w(TAG, "Failed to call registerTaskStackListener", e);
@@ -184,7 +187,8 @@ public class TaskStackChangeListeners {
if (isEmpty && mRegistered) {
// Unregister mTaskStackListener once we have no more listeners
try {
// ActivityTaskManager.getService().unregisterTaskStackListener(this);
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
ActivityTaskManager.getService().unregisterTaskStackListener(this);
mRegistered = false;
} catch (Exception e) {
Log.w(TAG, "Failed to call unregisterTaskStackListener", e);

View File

@@ -12,7 +12,7 @@ android {
sourceSets {
main {
java.srcDirs = ['shared/src']
aidl.srcDirs = ['shared/src', 'wmshell/shared/aidl']
aidl.srcDirs = ['shared/src']
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = ['shared']
}

View File

@@ -1,19 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.common.desktopmode;
parcelable DesktopModeTransitionSource;

View File

@@ -1,33 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.shared;
import android.window.RemoteTransition;
import android.window.TransitionFilter;
/**
* Listener interface that Launcher attaches to SystemUI to get home activity transition callbacks
* on the default display.
*/
oneway interface IHomeTransitionListener {
/**
* Called when a transition changes the visibility of the home activity on the default display.
*/
void onHomeVisibilityChanged(in boolean isVisible);
}