Fix android 14 crashes (#5620)

This commit is contained in:
Berke Emin Kabagöz
2025-09-28 04:21:02 +03:00
committed by GitHub
parent 40575a66a9
commit cb8b206a50
8 changed files with 97 additions and 9 deletions

View File

@@ -144,7 +144,8 @@ public class RemoteTargetGluer {
// a) mSplitBounds was already set (from the clicked GroupedTaskView) // a) mSplitBounds was already set (from the clicked GroupedTaskView)
// b) A SplitBounds was passed up from shell (via AbsSwipeUpHandler) // b) A SplitBounds was passed up from shell (via AbsSwipeUpHandler)
// If both of these are null, we are in a 1-app or 1-app-plus-assistant case. // If both of these are null, we are in a 1-app or 1-app-plus-assistant case.
if (mSplitBounds == null) { if (mSplitBounds == null && targets.extras != null
&& targets.extras.containsKey(KEY_EXTRA_SPLIT_BOUNDS)) {
SplitBounds shellSplitBounds = targets.extras.getParcelable(KEY_EXTRA_SPLIT_BOUNDS, SplitBounds shellSplitBounds = targets.extras.getParcelable(KEY_EXTRA_SPLIT_BOUNDS,
SplitBounds.class); SplitBounds.class);
mSplitBounds = convertShellSplitBoundsToLauncher(shellSplitBounds); mSplitBounds = convertShellSplitBoundsToLauncher(shellSplitBounds);

View File

@@ -1570,6 +1570,16 @@ public class SystemUiProxy implements ISystemUiProxy, NavHandle, SafeCloseable {
wallpapers, homeContentInsets, minimizedHomeBounds, extras); wallpapers, homeContentInsets, minimizedHomeBounds, extras);
} }
// Support for Android 13 and below
public void onAnimationStart(IRecentsAnimationController controller,
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] nonAppTargets,
Rect homeContentInsets, Rect minimizedHomeBounds) {
// Chain the call to the newer 6-argument version, passing null for the 'extras' bundle.
onAnimationStart(controller, apps, nonAppTargets, homeContentInsets,
minimizedHomeBounds, null);
}
@Override @Override
public void onAnimationCanceled(int[] taskIds, TaskSnapshot[] taskSnapshots) { public void onAnimationCanceled(int[] taskIds, TaskSnapshot[] taskSnapshots) {
listener.onAnimationCanceled( listener.onAnimationCanceled(

View File

@@ -2883,7 +2883,12 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
} }
private boolean hasDesktopTask(Task[] runningTasks) { private boolean hasDesktopTask(Task[] runningTasks) {
if (!DesktopModeStatus.canEnterDesktopMode(getContext())) { try {
if (!DesktopModeStatus.canEnterDesktopMode(getContext())) {
return false;
}
} catch (NoClassDefFoundError e) {
// Desktop mode is not supported on this device
return false; return false;
} }
for (Task task : runningTasks) { for (Task task : runningTasks) {

View File

@@ -342,7 +342,7 @@ class WorkspaceItemProcessor(
} }
try { try {
if ( if (
Utilities.ATLEAST_U && (c.restoreFlag != 0 || Utilities.ATLEAST_V && (c.restoreFlag != 0 ||
Flags.enableSupportForArchiving() && Flags.enableSupportForArchiving() &&
activityInfo != null && activityInfo != null &&
activityInfo.applicationInfo.isArchived) && !TextUtils.isEmpty(targetPkg) activityInfo.applicationInfo.isArchived) && !TextUtils.isEmpty(targetPkg)

View File

@@ -36,6 +36,7 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.IBinder; import android.os.IBinder;
@@ -53,6 +54,7 @@ import com.android.internal.app.IVoiceInteractionManagerService;
import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.recents.model.ThumbnailData;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@@ -155,9 +157,24 @@ public class ActivityManagerWrapper {
public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) { public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
TaskSnapshot snapshot = null; TaskSnapshot snapshot = null;
try { try {
snapshot = getService().getTaskSnapshot(taskId, isLowResolution); if (Build.VERSION.SDK_INT == Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
Method getTaskSnapshotMethod = getService().getClass().getMethod(
"getTaskSnapshot",
int.class, // taskId
boolean.class, // isLowResolution
boolean.class // isTranslucent (added in Android 14)
);
snapshot = (TaskSnapshot) getTaskSnapshotMethod.invoke(
getService(), taskId, isLowResolution, false);
} else {
snapshot = getService().getTaskSnapshot(taskId, isLowResolution);
}
} catch (RemoteException e) { } catch (RemoteException e) {
Log.w(TAG, "Failed to retrieve task snapshot", e); Log.w(TAG, "Failed to retrieve task snapshot", e);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
Log.e(TAG, "Failed to invoke getTaskSnapshot", e);
} }
if (snapshot != null) { if (snapshot != null) {
return ThumbnailData.fromSnapshot(snapshot); return ThumbnailData.fromSnapshot(snapshot);

View File

@@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION; import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
import android.os.Binder; import android.os.Binder;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.os.RemoteException; import android.os.RemoteException;
@@ -32,6 +33,8 @@ import android.view.InputEvent;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/** /**
* Manages the input consumer that allows the SystemUI to directly receive input. * Manages the input consumer that allows the SystemUI to directly receive input.
@@ -139,7 +142,14 @@ public class InputConsumerController {
if (mInputEventReceiver == null) { if (mInputEventReceiver == null) {
final InputChannel inputChannel = new InputChannel(); final InputChannel inputChannel = new InputChannel();
try { try {
mWindowManager.destroyInputConsumer(mToken, DEFAULT_DISPLAY); // Hook for Android P (9) to VANILLA_ICE_CREAM (15), where the method signature changed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
hookDestroyInputConsumer(mWindowManager);
} else {
mWindowManager.destroyInputConsumer(mToken, DEFAULT_DISPLAY);
}
mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel); mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "Failed to create input consumer", e); Log.e(TAG, "Failed to create input consumer", e);
@@ -152,13 +162,36 @@ public class InputConsumerController {
} }
} }
/**
* IWindowManager @destroyInputConsumer reflection
*/
private void hookDestroyInputConsumer(IWindowManager mWindowManager) throws RemoteException {
try {
Class<?> iWindowManagerClass = Class.forName("android.view.IWindowManager");
Method destroyInputConsumerMethod = iWindowManagerClass.getMethod("destroyInputConsumer", String.class, int.class);
destroyInputConsumerMethod.invoke(mWindowManager, mName, DEFAULT_DISPLAY);
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException |
InvocationTargetException e) {
Log.e(TAG, "Failed to invoke destroyInputConsumer", e);
mWindowManager.destroyInputConsumer(mToken, DEFAULT_DISPLAY);
}
}
/** /**
* Unregisters the input consumer. * Unregisters the input consumer.
*/ */
public void unregisterInputConsumer() { public void unregisterInputConsumer() {
if (mInputEventReceiver != null) { if (mInputEventReceiver != null) {
try { try {
mWindowManager.destroyInputConsumer(mToken, DEFAULT_DISPLAY); // Hook for Android P (9) to VANILLA_ICE_CREAM (15), where the method signature changed
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) {
hookDestroyInputConsumer(mWindowManager);
} else {
mWindowManager.destroyInputConsumer(mToken, DEFAULT_DISPLAY);
}
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "Failed to destroy input consumer", e); Log.e(TAG, "Failed to destroy input consumer", e);
} }

View File

@@ -16,6 +16,7 @@
package com.android.systemui.shared.system; package com.android.systemui.shared.system;
import android.os.Build;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import android.view.IRecentsAnimationController; import android.view.IRecentsAnimationController;
@@ -26,6 +27,8 @@ import android.window.TaskSnapshot;
import com.android.internal.os.IResultReceiver; import com.android.internal.os.IResultReceiver;
import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.recents.model.ThumbnailData;
import java.lang.reflect.Method;
public class RecentsAnimationControllerCompat { public class RecentsAnimationControllerCompat {
private static final String TAG = RecentsAnimationControllerCompat.class.getSimpleName(); private static final String TAG = RecentsAnimationControllerCompat.class.getSimpleName();
@@ -92,7 +95,24 @@ public class RecentsAnimationControllerCompat {
*/ */
public void finish(boolean toHome, boolean sendUserLeaveHint, IResultReceiver finishCb) { public void finish(boolean toHome, boolean sendUserLeaveHint, IResultReceiver finishCb) {
try { try {
mAnimationController.finish(toHome, sendUserLeaveHint, finishCb); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
mAnimationController.finish(toHome, sendUserLeaveHint, finishCb);
} else {
try {
Method finishMethod = mAnimationController.getClass().getMethod(
"finish", boolean.class, boolean.class);
finishMethod.invoke(mAnimationController, toHome, sendUserLeaveHint);
if (finishCb != null) {
finishCb.send(0, null);
}
} catch (Exception e) {
Log.e(TAG, "Failed to finish recents animation via reflection", e);
if (finishCb != null) {
finishCb.send(0, null);
}
}
}
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, "Failed to finish recents animation", e); Log.e(TAG, "Failed to finish recents animation", e);
try { try {

View File

@@ -19,6 +19,7 @@ package com.android.wm.shell.shared;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.Build;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
@@ -150,7 +151,8 @@ public class DesktopModeStatus {
*/ */
@VisibleForTesting @VisibleForTesting
public static boolean isDesktopModeSupported(@NonNull Context context) { public static boolean isDesktopModeSupported(@NonNull Context context) {
return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported); return Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
&& context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
} }
/** /**