Patch fix for Android 13 and below (#4978)

* Patch fix for Android 13 and below
tested in Android 9, 10 and 13 and works fine.

* fix crash dragging the icons from drawer to home screen

* use LawnchairWindowManagerProxy

---------

Co-authored-by: MrSluffy <werdna.jac@gmail.com>
This commit is contained in:
Rafael de Moura Dev
2024-11-16 22:05:31 -03:00
committed by GitHub
parent 71fbccb5a3
commit 795fdb2948
37 changed files with 605 additions and 198 deletions

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?><!--
Copyright (C) 2017 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.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<com.android.quickstep.views.LauncherRecentsView
android:id="@+id/overview_panel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:accessibilityPaneTitle="@string/accessibility_recent_apps"
android:clipChildren="false"
android:clipToPadding="false"
android:visibility="invisible" />
<include
android:id="@+id/overview_actions_view"
layout="@layout/overview_actions_container" />
</merge>

View File

@@ -179,10 +179,14 @@ public class AppEventProducer implements StatsLogConsumer {
sendEvent(atomInfo, ACTION_PIN, CONTAINER_HOTSEAT_PREDICTION);
}
} else if (event == LAUNCHER_ONRESUME) {
AppTarget target = new AppTarget.Builder(new AppTargetId("launcher:launcher"),
if (Utilities.ATLEAST_Q) {
AppTarget target = new AppTarget.Builder(new AppTargetId("launcher:launcher"),
mContext.getPackageName(), Process.myUserHandle())
.build();
sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
sendEvent(target, atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
} else {
sendEvent(atomInfo, ACTION_LAUNCH, CONTAINER_PREDICTION);
}
} else if (event == LAUNCHER_DISMISS_PREDICTION_UNDO) {
sendEvent(atomInfo, ACTION_UNDISMISS, CONTAINER_HOTSEAT_PREDICTION);
} else if (event == LAUNCHER_WIDGET_ADD_BUTTON_TAP) {
@@ -252,6 +256,9 @@ public class AppEventProducer implements StatsLogConsumer {
if (shortcutInfo != null) {
return new AppTarget.Builder(new AppTargetId(id), shortcutInfo).build();
}
if (!Utilities.ATLEAST_Q) {
return null;
}
return new AppTarget.Builder(new AppTargetId(id), cn.getPackageName(), userHandle)
.setClassName(cn.getClassName())
.build();

View File

@@ -38,6 +38,7 @@ import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
@@ -196,7 +197,9 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
if (enablePredictiveBackGesture()) {
mAppsView.getAppsRecyclerViewContainer().setOutlineProvider(mViewOutlineProvider);
mAppsView.getAppsRecyclerViewContainer().setClipToOutline(true);
OnBackInvokedDispatcher dispatcher = findOnBackInvokedDispatcher();
OnBackInvokedDispatcher dispatcher;
if (!Utilities.ATLEAST_U) return;
dispatcher = findOnBackInvokedDispatcher();
if (dispatcher != null) {
dispatcher.registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT, null);
@@ -211,8 +214,10 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
if (enablePredictiveBackGesture()) {
mAppsView.getAppsRecyclerViewContainer().setOutlineProvider(null);
mAppsView.getAppsRecyclerViewContainer().setClipToOutline(false);
OnBackInvokedDispatcher dispatcher = findOnBackInvokedDispatcher();
if (dispatcher != null) {
OnBackInvokedDispatcher dispatcher;
if (!Utilities.ATLEAST_U) return;
dispatcher = findOnBackInvokedDispatcher();
if (dispatcher != null && Utilities.ATLEAST_T) {
dispatcher.unregisterOnBackInvokedCallback(null);
}
}

View File

@@ -16,8 +16,6 @@
package com.android.launcher3.uioverrides;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.os.Trace.TRACE_TAG_APP;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_OPTIMIZE_MEASURE;
import static android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED;
import static com.android.app.animation.Interpolators.EMPHASIZED;
@@ -308,7 +306,9 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer
mEnableWidgetDepth = LawnchairApp.isRecentsEnabled() ? SystemProperties.getBoolean("ro.launcher.depth.widget", true) : false;
getWorkspace().addOverlayCallback(progress ->
onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX));
addBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
if (Utilities.ATLEAST_U) {
addBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
}
}
@Override
@@ -555,7 +555,9 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer
mHotseatPredictionController.destroy();
mSplitWithKeyboardShortcutController.onDestroy();
if (mViewCapture != null) mViewCapture.close();
removeBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
if (Utilities.ATLEAST_U) {
removeBackAnimationCallback(mSplitSelectStateController.getSplitBackHandler());
}
}
@Override
@@ -899,56 +901,58 @@ public class QuickstepLauncher extends Launcher implements RecentsViewContainer
super.registerBackDispatcher();
return;
}
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
new OnBackAnimationCallback() {
@Nullable
OnBackPressedHandler mActiveOnBackPressedHandler;
@Override
public void onBackStarted(@NonNull BackEvent backEvent) {
if (mActiveOnBackPressedHandler != null) {
mActiveOnBackPressedHandler.onBackCancelled();
}
mActiveOnBackPressedHandler = getOnBackPressedHandler();
mActiveOnBackPressedHandler.onBackStarted();
}
@Override
public void onBackInvoked() {
// Recreate mActiveOnBackPressedHandler if necessary to avoid NPE
// because:
// 1. b/260636433: In 3-button-navigation mode, onBackStarted() is not
// called on ACTION_DOWN before onBackInvoked() is called in ACTION_UP.
// 2. Launcher#onBackPressed() will call onBackInvoked() without calling
// onBackInvoked() beforehand.
if (mActiveOnBackPressedHandler == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
new OnBackAnimationCallback() {
@Nullable
OnBackPressedHandler mActiveOnBackPressedHandler;
@Override
public void onBackStarted(@NonNull BackEvent backEvent) {
if (mActiveOnBackPressedHandler != null) {
mActiveOnBackPressedHandler.onBackCancelled();
}
mActiveOnBackPressedHandler = getOnBackPressedHandler();
mActiveOnBackPressedHandler.onBackStarted();
}
mActiveOnBackPressedHandler.onBackInvoked();
mActiveOnBackPressedHandler = null;
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
}
@Override
public void onBackProgressed(@NonNull BackEvent backEvent) {
if (!FeatureFlags.IS_STUDIO_BUILD
&& mActiveOnBackPressedHandler == null) {
return;
@Override
public void onBackInvoked() {
// Recreate mActiveOnBackPressedHandler if necessary to avoid NPE
// because:
// 1. b/260636433: In 3-button-navigation mode, onBackStarted() is not
// called on ACTION_DOWN before onBackInvoked() is called in ACTION_UP.
// 2. Launcher#onBackPressed() will call onBackInvoked() without calling
// onBackInvoked() beforehand.
if (mActiveOnBackPressedHandler == null) {
mActiveOnBackPressedHandler = getOnBackPressedHandler();
}
mActiveOnBackPressedHandler.onBackInvoked();
mActiveOnBackPressedHandler = null;
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
}
mActiveOnBackPressedHandler.onBackProgressed(backEvent.getProgress());
}
@Override
public void onBackCancelled() {
if (!FeatureFlags.IS_STUDIO_BUILD
&& mActiveOnBackPressedHandler == null) {
return;
@Override
public void onBackProgressed(@NonNull BackEvent backEvent) {
if (!FeatureFlags.IS_STUDIO_BUILD
&& mActiveOnBackPressedHandler == null) {
return;
}
mActiveOnBackPressedHandler.onBackProgressed(backEvent.getProgress());
}
mActiveOnBackPressedHandler.onBackCancelled();
mActiveOnBackPressedHandler = null;
}
});
@Override
public void onBackCancelled() {
if (!FeatureFlags.IS_STUDIO_BUILD
&& mActiveOnBackPressedHandler == null) {
return;
}
mActiveOnBackPressedHandler.onBackCancelled();
mActiveOnBackPressedHandler = null;
}
});
}
}
private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {

View File

@@ -38,6 +38,7 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.util.VibratorWrapper;
import com.android.quickstep.SystemUiProxy;
@@ -145,6 +146,9 @@ public class StatusBarTouchController implements TouchController {
if (!mCanIntercept) {
return false;
}
if (!Utilities.ATLEAST_R) {
return false;
}
if (action == ACTION_MOVE && mDownEvents.contains(pid)) {
float dy = ev.getY(idx) - mDownEvents.get(pid).y;
float dx = ev.getX(idx) - mDownEvents.get(pid).x;

View File

@@ -38,6 +38,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.taskbar.TaskbarUIController;
@@ -344,8 +345,17 @@ public abstract class BaseContainerInterface<STATE_TYPE extends BaseState<STATE_
int sideMargin = dp.overviewGridSideMargin;
outRect.set(0, 0, dp.widthPx, dp.heightPx);
outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin,
if (Utilities.ATLEAST_S) {
outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin,
Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin));
} else {
outRect.set(
Math.max(insets.left, sideMargin),
insets.top + topMargin,
outRect.width() - Math.max(insets.right, sideMargin),
outRect.height() - Math.max(insets.bottom, bottomMargin)
);
}
}
/**

View File

@@ -147,7 +147,7 @@ public class StatsLogCompatManager extends StatsLogManager {
if (IS_VERBOSE) {
Log.d(TAG, String.format("\nwriteSnapshot(%d):\n%s", instanceId.getId(), info));
}
if (Utilities.isRunningInTestHarness()) {
if (Utilities.isRunningInTestHarness() || !Utilities.ATLEAST_R) {
return;
}
SysUiStatsLog.write(SysUiStatsLog.LAUNCHER_SNAPSHOT,
@@ -482,7 +482,7 @@ public class StatsLogCompatManager extends StatsLogManager {
}
// TODO: remove this when b/231648228 is fixed.
if (Utilities.isRunningInTestHarness()) {
if (Utilities.isRunningInTestHarness() || !Utilities.ATLEAST_R) {
return;
}
int cardinality = mCardinality.orElseGet(() -> getCardinality(atomInfo));

View File

@@ -41,6 +41,7 @@ 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;
@@ -52,6 +53,7 @@ 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;
@@ -168,24 +170,6 @@ 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,
@@ -939,8 +923,25 @@ public class SplitSelectStateController {
mLaunchingIconView = launchingIconView;
}
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
public BackPressHandler getSplitBackHandler() {
return mSplitBackHandler;
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();
}
}
};
}
public void dump(String prefix, PrintWriter writer) {

View File

@@ -27,7 +27,9 @@ import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.core.view.updateLayoutParams
import app.lawnchair.theme.color.tokens.ColorTokens
import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.util.RunnableList
import com.android.launcher3.util.SplitConfigurationOptions
import com.android.launcher3.util.TransformingTouchDelegate
@@ -73,10 +75,7 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
ShapeDrawable(RoundRectShape(FloatArray(8) { taskCornerRadius }, null, null))
.apply {
setTint(
resources.getColor(
android.R.color.system_neutral2_300,
context.theme
)
ColorTokens.Neutral2_300.resolveColor(context)
)
}
}
@@ -102,7 +101,7 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
val thumbnailTopMarginPx = container.deviceProfile.overviewTaskThumbnailTopMarginPx
containerHeight -= thumbnailTopMarginPx
BaseContainerInterface.getTaskDimension(mContext, container.deviceProfile, tempPointF)
BaseContainerInterface.getTaskDimension(context, container.deviceProfile, tempPointF)
val windowWidth = tempPointF.x.toInt()
val windowHeight = tempPointF.y.toInt()
val scaleWidth = containerWidth / windowWidth.toFloat()
@@ -212,9 +211,13 @@ class DesktopTaskView @JvmOverloads constructor(context: Context, attrs: Attribu
}
}
repeat(taskContainers.size - tasks.size) {
with(taskContainers.removeLast()) {
removeView(thumbnailViewDeprecated)
taskThumbnailViewPool.recycle(thumbnailViewDeprecated)
if (Utilities.ATLEAST_T) {
with(taskContainers.removeLast()) {
removeView(thumbnailViewDeprecated)
taskThumbnailViewPool.recycle(thumbnailViewDeprecated)
}
} else {
taskContainers.removeAt(taskContainers.lastIndex)
}
}

View File

@@ -39,6 +39,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.desktop.DesktopRecentsTransitionController;
import com.android.launcher3.logging.StatsLogManager;
@@ -292,8 +293,8 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
// TODO: b/333533253 - Remove after flag rollout
desktopVisibilityController.setRecentsGestureEnd(endTarget);
}
if (showDesktopApps) {
SystemUiProxy.INSTANCE.get(mContainer).showDesktopApps(mContainer.getDisplayId(),
if (showDesktopApps && Utilities.ATLEAST_R) {
SystemUiProxy.INSTANCE.get(mContainer).showDesktopApps(mContainer.getDisplay().getDisplayId(),
null /* transition */);
}
}

View File

@@ -93,6 +93,7 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
@@ -803,7 +804,8 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
mContainer = RecentsViewContainer.containerFromContext(context);
mOrientationState = new RecentsOrientedState(
context, mSizeStrategy, this::animateRecentsRotationInPlace);
final int rotation = mContainer.getDisplay().getRotation();
final int rotation;
rotation = Utilities.ATLEAST_R ? mContainer.getDisplay().getRotation() : WindowConfiguration.ROTATION_UNDEFINED;
mOrientationState.setRecentsRotation(rotation);
mScrollHapticMinGapMillis = getResources()
@@ -6060,7 +6062,11 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
if (tintAmount == 0f) {
scrimBg.setTintList(null);
} else {
scrimBg.setTintBlendMode(BlendMode.SRC_OVER);
if (Utilities.ATLEAST_Q) {
scrimBg.setTintBlendMode(BlendMode.SRC_OVER);
} else {
scrimBg.setTintMode(PorterDuff.Mode.SRC_OVER);
}
scrimBg.setTint(
ColorUtils.setAlphaComponent(mTintingColor, (int) (255 * tintAmount)));
}
@@ -6314,6 +6320,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
locusId += "|DISABLED";
}
if (!Utilities.ATLEAST_R) return;
final LocusId id = new LocusId(locusId);
// Set locus context is a binder call, don't want it to happen during a transition
UI_HELPER_EXECUTOR.post(() -> mContainer.setLocusContext(id, Bundle.EMPTY));

View File

@@ -27,6 +27,7 @@ import android.graphics.Canvas
import android.graphics.PointF
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.os.Build
import android.os.Bundle
import android.util.AttributeSet
import android.util.FloatProperty
@@ -42,6 +43,7 @@ import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction
import android.widget.FrameLayout
import android.widget.Toast
import androidx.annotation.IntDef
import androidx.annotation.RequiresApi
import androidx.annotation.VisibleForTesting
import androidx.core.view.updateLayoutParams
import com.android.app.animation.Interpolators
@@ -463,7 +465,9 @@ constructor(
(ENABLE_KEYBOARD_QUICK_SWITCH.get() || enableFocusOutline())
val cursorHoverStatesEnabled = enableCursorHoverStates()
setWillNotDraw(!keyboardFocusHighlightEnabled && !cursorHoverStatesEnabled)
context.obtainStyledAttributes(attrs, R.styleable.TaskView, defStyleAttr, defStyleRes).use {
val attrs =
context.obtainStyledAttributes(attrs, R.styleable.TaskView, defStyleAttr, defStyleRes)
try {
this.focusBorderAnimator =
focusBorderAnimator
?: if (keyboardFocusHighlightEnabled)
@@ -474,7 +478,7 @@ constructor(
),
{ bounds: Rect -> getThumbnailBounds(bounds) },
this,
it.getColor(
attrs.getColor(
R.styleable.TaskView_focusBorderColor,
BorderAnimator.DEFAULT_BORDER_COLOR
)
@@ -490,15 +494,18 @@ constructor(
),
{ bounds: Rect -> getThumbnailBounds(bounds) },
this,
it.getColor(
attrs.getColor(
R.styleable.TaskView_hoverBorderColor,
BorderAnimator.DEFAULT_BORDER_COLOR
)
)
else null
} finally {
attrs.recycle()
}
}
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public override fun onFocusChanged(
gainFocus: Boolean,
@@ -555,6 +562,7 @@ constructor(
super.draw(canvas)
}
@RequiresApi(Build.VERSION_CODES.Q)
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx
@@ -1076,7 +1084,7 @@ constructor(
Executors.UI_HELPER_EXECUTOR.execute {
if (
!ActivityManagerWrapper.getInstance()
.startActivityFromRecents(firstContainer.task.key, opts)
.startActivityFromRecents(firstContainer.task.key, if (Utilities.ATLEAST_Q) opts else null)
) {
// If the call to start activity failed, then post the result immediately,
// otherwise, wait for the animation start callback from the activity options