fix(QuickSwitch): Transition behaviour compat for 16.0 (#7282)
This commit is contained in:
1 parent
12c2ee2219
commit
d2d1775131
18 files changed
+294
-36
No files matched your search
@@ -11,6 +11,10 @@ val isOnePlusStock = checkOnePlusStock()
|
|||||||
|
|
||||||
val isGestureNavContractCompatible = checkGestureNavContract()
|
val isGestureNavContractCompatible = checkGestureNavContract()
|
||||||
|
|
||||||
|
val isNothingOs = checkNothingStock()
|
||||||
|
|
||||||
|
val isAndroidBaklavaInitial = checkGenericBaklavaInitial()
|
||||||
|
|
||||||
private fun checkOnePlusStock(): Boolean = when {
|
private fun checkOnePlusStock(): Boolean = when {
|
||||||
getSystemProperty("ro.rom.version", "")
|
getSystemProperty("ro.rom.version", "")
|
||||||
.contains(Regex("Oxygen OS|Hydrogen OS|O2_BETA|H2_BETA")) -> true
|
.contains(Regex("Oxygen OS|Hydrogen OS|O2_BETA|H2_BETA")) -> true
|
||||||
@@ -52,6 +56,18 @@ private fun checkMeizuStock(): Boolean = when {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkNothingStock(): Boolean = when {
|
||||||
|
getSystemProperty("ro.nothing.version.id", "").isNotEmpty() -> true
|
||||||
|
getSystemProperty("ro.build.nothing.version", "").isNotEmpty() -> true
|
||||||
|
getSystemProperty("ro.build.nothing.feature.base", "").isNotEmpty() -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkGenericBaklavaInitial(): Boolean = when {
|
||||||
|
arrayOf("BP2A.", "BD1A.").any { prefix -> Build.FINGERPRINT.contains(prefix) } -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkGestureNavContract(): Boolean = when {
|
private fun checkGestureNavContract(): Boolean = when {
|
||||||
!Utilities.ATLEAST_Q -> false
|
!Utilities.ATLEAST_Q -> false
|
||||||
checkOnePlusStock() -> false
|
checkOnePlusStock() -> false
|
||||||
|
|||||||
@@ -1258,7 +1258,9 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
|||||||
homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
|
homeCheck.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK};
|
||||||
|
|
||||||
homeCheck.mRequirements[2].mNot = true;
|
homeCheck.mRequirements[2].mNot = true;
|
||||||
homeCheck.mRequirements[2].mCustomAnimation = true;
|
if (Utilities.ATLEAST_BAKLAVA) { // LC-Note: QuickSwitch compatibility!
|
||||||
|
homeCheck.mRequirements[2].mCustomAnimation = true;
|
||||||
|
}
|
||||||
homeCheck.mRequirements[2].mMustBeTask = true;
|
homeCheck.mRequirements[2].mMustBeTask = true;
|
||||||
homeCheck.mRequirements[2].mMustBeIndependent = true;
|
homeCheck.mRequirements[2].mMustBeIndependent = true;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import android.window.RemoteTransition
|
|||||||
import android.window.TransitionFilter
|
import android.window.TransitionFilter
|
||||||
import android.window.TransitionFilter.CONTAINER_ORDER_TOP
|
import android.window.TransitionFilter.CONTAINER_ORDER_TOP
|
||||||
import com.android.internal.jank.Cuj
|
import com.android.internal.jank.Cuj
|
||||||
|
import com.android.launcher3.Utilities
|
||||||
import com.android.launcher3.desktop.DesktopAppLaunchTransition.AppLaunchType
|
import com.android.launcher3.desktop.DesktopAppLaunchTransition.AppLaunchType
|
||||||
import com.android.launcher3.util.Executors.MAIN_EXECUTOR
|
import com.android.launcher3.util.Executors.MAIN_EXECUTOR
|
||||||
import com.android.quickstep.SystemUiProxy
|
import com.android.quickstep.SystemUiProxy
|
||||||
@@ -74,7 +75,8 @@ class DesktopAppLaunchTransitionManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldRegisterTransitions(): Boolean =
|
private fun shouldRegisterTransitions(): Boolean =
|
||||||
DesktopModeStatus.canEnterDesktopMode(context) &&
|
Utilities.ATLEAST_BAKLAVA && // LC-Note: This is only available for Baklava
|
||||||
|
DesktopModeStatus.canEnterDesktopMode(context) &&
|
||||||
DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue
|
DesktopModeFlags.ENABLE_DESKTOP_APP_LAUNCH_TRANSITIONS_BUGFIX.isTrue
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.launcher3.taskbar
|
package com.android.launcher3.taskbar
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.Insets
|
import android.graphics.Insets
|
||||||
@@ -22,6 +23,7 @@ import android.graphics.Paint
|
|||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.graphics.Region
|
import android.graphics.Region
|
||||||
import android.os.Binder
|
import android.os.Binder
|
||||||
|
import android.os.Handler
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.view.DisplayInfo
|
import android.view.DisplayInfo
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
@@ -50,6 +52,7 @@ import androidx.core.graphics.toRegion
|
|||||||
import com.android.internal.policy.GestureNavigationSettingsObserver
|
import com.android.internal.policy.GestureNavigationSettingsObserver
|
||||||
import com.android.launcher3.DeviceProfile
|
import com.android.launcher3.DeviceProfile
|
||||||
import com.android.launcher3.R
|
import com.android.launcher3.R
|
||||||
|
import com.android.launcher3.Utilities
|
||||||
import com.android.launcher3.anim.AlphaUpdateListener
|
import com.android.launcher3.anim.AlphaUpdateListener
|
||||||
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
|
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION
|
||||||
import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
|
import com.android.launcher3.config.FeatureFlags.enableTaskbarNoRecreate
|
||||||
@@ -89,12 +92,29 @@ class TaskbarInsetsController(val context: TaskbarActivityContext) : LoggableTas
|
|||||||
onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
|
onTaskbarOrBubblebarWindowHeightOrInsetsChanged()
|
||||||
}
|
}
|
||||||
private val gestureNavSettingsObserver =
|
private val gestureNavSettingsObserver =
|
||||||
GestureNavigationSettingsObserver(
|
if (Utilities.ATLEAST_V) { // LC-Note: This is only available for V
|
||||||
context.mainThreadHandler,
|
GestureNavigationSettingsObserver(
|
||||||
Executors.UI_HELPER_EXECUTOR.handler,
|
context.mainThreadHandler,
|
||||||
context,
|
Executors.UI_HELPER_EXECUTOR.handler,
|
||||||
this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged,
|
context,
|
||||||
)
|
this::onTaskbarOrBubblebarWindowHeightOrInsetsChanged,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
GestureNavigationSettingsObserver::class.java
|
||||||
|
.getConstructor(Handler::class.java, Context::class.java, Runnable::class.java)
|
||||||
|
.newInstance(
|
||||||
|
context.mainThreadHandler,
|
||||||
|
context,
|
||||||
|
Runnable { onTaskbarOrBubblebarWindowHeightOrInsetsChanged() },
|
||||||
|
)
|
||||||
|
} catch (e: ReflectiveOperationException) {
|
||||||
|
throw IllegalStateException(
|
||||||
|
"LC: Unable to create legacy GestureNavigationSettingsObserver! QuickSwitch is tested for Android 14 above!",
|
||||||
|
e,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@VisibleForTesting val debugTouchableRegion = DebugTouchableRegion()
|
@VisibleForTesting val debugTouchableRegion = DebugTouchableRegion()
|
||||||
|
|
||||||
// Initialized in init.
|
// Initialized in init.
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ import android.graphics.Matrix;
|
|||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -1687,8 +1688,19 @@ public abstract class AbsSwipeUpHandler<
|
|||||||
boolean hasValidLeash = runningTaskTarget != null
|
boolean hasValidLeash = runningTaskTarget != null
|
||||||
&& runningTaskTarget.leash != null
|
&& runningTaskTarget.leash != null
|
||||||
&& runningTaskTarget.leash.isValid();
|
&& runningTaskTarget.leash.isValid();
|
||||||
|
|
||||||
|
boolean enableDesktopWindowingPipCompat = false;
|
||||||
|
// Literal int because https://github.com/LawnchairLauncher/lawnchair/issues/6817
|
||||||
|
if (Build.VERSION.SDK_INT >= 36 && Build.VERSION.SDK_INT_FULL >= 3600001) {
|
||||||
|
try {
|
||||||
|
enableDesktopWindowingPipCompat = DesktopExperienceFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d("LC-AbsSwipeUpHandler", "Failed to get ENABLE_DESKTOP_WINDOWING_PIP flag, defaulting to false", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final boolean swipeUpInDesktopWindowing =
|
final boolean swipeUpInDesktopWindowing =
|
||||||
DesktopExperienceFlags.ENABLE_DESKTOP_WINDOWING_PIP.isTrue()
|
enableDesktopWindowingPipCompat
|
||||||
&& runningTaskTarget != null
|
&& runningTaskTarget != null
|
||||||
&& runningTaskTarget.taskInfo.getWindowingMode()
|
&& runningTaskTarget.taskInfo.getWindowingMode()
|
||||||
== WINDOWING_MODE_FREEFORM;
|
== WINDOWING_MODE_FREEFORM;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ private val USER_SETUP_COMPLETE_URI = Settings.Secure.getUriFor(USER_SETUP_COMPL
|
|||||||
class AllAppsActionManager(
|
class AllAppsActionManager(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val bgExecutor: Executor,
|
private val bgExecutor: Executor,
|
||||||
private val quickstepKeyGestureEventsManager: QuickstepKeyGestureEventsManager,
|
private val quickstepKeyGestureEventsManager: QuickstepKeyGestureEventsManager?, // LC-Note: Nullable because this isn't available for U and lower
|
||||||
private val createAllAppsPendingIntent: () -> PendingIntent,
|
private val createAllAppsPendingIntent: () -> PendingIntent,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@@ -104,12 +104,12 @@ class AllAppsActionManager(
|
|||||||
),
|
),
|
||||||
GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
|
GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS,
|
||||||
)
|
)
|
||||||
quickstepKeyGestureEventsManager.registerAllAppsKeyGestureEvent(
|
quickstepKeyGestureEventsManager?.registerAllAppsKeyGestureEvent( // LC-Note: QuickSwitch compatibility!
|
||||||
allAppsPendingIntent
|
allAppsPendingIntent
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
accessibilityManager.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
|
accessibilityManager.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
|
||||||
quickstepKeyGestureEventsManager.unregisterAllAppsKeyGestureEvent()
|
quickstepKeyGestureEventsManager?.unregisterAllAppsKeyGestureEvent() // LC-Note: QuickSwitch compatibility!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ class AllAppsActionManager(
|
|||||||
context
|
context
|
||||||
.getSystemService(AccessibilityManager::class.java)
|
.getSystemService(AccessibilityManager::class.java)
|
||||||
?.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
|
?.unregisterSystemAction(GLOBAL_ACTION_ACCESSIBILITY_ALL_APPS)
|
||||||
quickstepKeyGestureEventsManager.unregisterAllAppsKeyGestureEvent()
|
quickstepKeyGestureEventsManager?.unregisterAllAppsKeyGestureEvent() // LC-Note: QuickSwitch compatibility!
|
||||||
SettingsCache.INSTANCE[context].unregister(
|
SettingsCache.INSTANCE[context].unregister(
|
||||||
USER_SETUP_COMPLETE_URI,
|
USER_SETUP_COMPLETE_URI,
|
||||||
onSettingsChangeListener,
|
onSettingsChangeListener,
|
||||||
|
|||||||
@@ -26,10 +26,12 @@ import android.content.Intent
|
|||||||
import android.content.pm.ShortcutInfo
|
import android.content.pm.ShortcutInfo
|
||||||
import android.graphics.Point
|
import android.graphics.Point
|
||||||
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
|
||||||
import android.os.Message
|
import android.os.Message
|
||||||
|
import android.os.Parcel
|
||||||
import android.os.RemoteException
|
import android.os.RemoteException
|
||||||
import android.os.Trace
|
import android.os.Trace
|
||||||
import android.os.Trace.traceBegin
|
import android.os.Trace.traceBegin
|
||||||
@@ -52,12 +54,14 @@ import android.window.WindowContainerTransaction
|
|||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
|
import app.lawnchair.util.isAndroidBaklavaInitial
|
||||||
|
import app.lawnchair.util.isNothingOs
|
||||||
//import app.lawnchair.gestures.type.GestureType
|
//import app.lawnchair.gestures.type.GestureType
|
||||||
import com.android.internal.logging.InstanceId
|
import com.android.internal.logging.InstanceId
|
||||||
import com.android.internal.util.ScreenshotRequest
|
import com.android.internal.util.ScreenshotRequest
|
||||||
import com.android.internal.view.AppearanceRegion
|
import com.android.internal.view.AppearanceRegion
|
||||||
import com.android.launcher3.Flags
|
import com.android.launcher3.Flags
|
||||||
import com.android.launcher3.Utilities.ATLEAST_BAKLAVA
|
import com.android.launcher3.Utilities
|
||||||
import com.android.launcher3.dagger.ApplicationContext
|
import com.android.launcher3.dagger.ApplicationContext
|
||||||
import com.android.launcher3.dagger.LauncherAppComponent
|
import com.android.launcher3.dagger.LauncherAppComponent
|
||||||
import com.android.launcher3.dagger.LauncherAppSingleton
|
import com.android.launcher3.dagger.LauncherAppSingleton
|
||||||
@@ -214,6 +218,36 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun startInitialAndroid16RecentsTransition(
|
||||||
|
recentTasks: IRecentTasks,
|
||||||
|
pendingIntent: PendingIntent,
|
||||||
|
intent: Intent?,
|
||||||
|
options: Bundle,
|
||||||
|
listener: IRecentsAnimationRunner,
|
||||||
|
): Boolean {
|
||||||
|
val data = Parcel.obtain(recentTasks.asBinder())
|
||||||
|
return try {
|
||||||
|
data.writeInterfaceToken(IRecentTasks.DESCRIPTOR)
|
||||||
|
data.writeTypedObject(pendingIntent, 0)
|
||||||
|
data.writeTypedObject(intent, 0)
|
||||||
|
data.writeTypedObject(options, 0)
|
||||||
|
data.writeStrongInterface(context.iApplicationThread)
|
||||||
|
data.writeStrongInterface(listener)
|
||||||
|
recentTasks.asBinder().transact(
|
||||||
|
if (usesNothingOs4BaklavaInitialRecentsTransitionAidl()) {
|
||||||
|
LC_TRANSACTION_startRecentsTransition_NothingOS_4_BaklavaInitial
|
||||||
|
} else {
|
||||||
|
LC_TRANSACTION_startRecentsTransition_AOSP_BaklavaInitial
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
null,
|
||||||
|
IBinder.FLAG_ONEWAY,
|
||||||
|
)
|
||||||
|
} finally {
|
||||||
|
data.recycle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun onBackEvent(backEvent: KeyEvent?) =
|
fun onBackEvent(backEvent: KeyEvent?) =
|
||||||
executeWithErrorLog({ "Failed call onBackPressed" }) {
|
executeWithErrorLog({ "Failed call onBackPressed" }) {
|
||||||
systemUiProxy?.onBackEvent(backEvent)
|
systemUiProxy?.onBackEvent(backEvent)
|
||||||
@@ -1108,7 +1142,7 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context:
|
|||||||
|
|
||||||
private fun shouldEnableRunningTasksForDesktopMode(): Boolean =
|
private fun shouldEnableRunningTasksForDesktopMode(): Boolean =
|
||||||
DesktopModeStatus.canEnterDesktopMode(context) &&
|
DesktopModeStatus.canEnterDesktopMode(context) &&
|
||||||
if (ATLEAST_BAKLAVA) {
|
if (Utilities.ATLEAST_BAKLAVA) {
|
||||||
ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS.isTrue
|
ENABLE_DESKTOP_WINDOWING_TASKBAR_RUNNING_APPS.isTrue
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
@@ -1271,6 +1305,24 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context:
|
|||||||
displayId: Int,
|
displayId: Int,
|
||||||
): Boolean {
|
): Boolean {
|
||||||
executeWithErrorLog({ "Error starting recents via shell" }) {
|
executeWithErrorLog({ "Error starting recents via shell" }) {
|
||||||
|
if (usesAOSPBaklavaInitialRecentsTransitionAidl()) {
|
||||||
|
if (wct != null) {
|
||||||
|
Log.w("LC-SystemUiProxy", "Android 16 initial does not support WCT-backed recents transitions")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val recentTasks = recentTasks ?: return false
|
||||||
|
return startInitialAndroid16RecentsTransition(
|
||||||
|
recentTasks,
|
||||||
|
getRecentsPendingIntent(displayId),
|
||||||
|
intent,
|
||||||
|
options.toBundle().apply {
|
||||||
|
if (useSyntheticRecentsTransition) {
|
||||||
|
putBoolean("is_synthetic_recents_transition", true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
RecentsAnimationListenerStub(listener),
|
||||||
|
)
|
||||||
|
}
|
||||||
recentTasks?.startRecentsTransition(
|
recentTasks?.startRecentsTransition(
|
||||||
getRecentsPendingIntent(displayId),
|
getRecentsPendingIntent(displayId),
|
||||||
intent,
|
intent,
|
||||||
@@ -1284,8 +1336,7 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context:
|
|||||||
RecentsAnimationListenerStub(listener),
|
RecentsAnimationListenerStub(listener),
|
||||||
)
|
)
|
||||||
?: run {
|
?: run {
|
||||||
// LC-Ignored
|
if (Utilities.ATLEAST_S) ActiveGestureProtoLogProxy.logRecentTasksMissing()
|
||||||
//ActiveGestureProtoLogProxy.logRecentTasksMissing()
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@@ -1295,6 +1346,45 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context:
|
|||||||
|
|
||||||
private class RecentsAnimationListenerStub(val listener: RecentsAnimationListener) :
|
private class RecentsAnimationListenerStub(val listener: RecentsAnimationListener) :
|
||||||
IRecentsAnimationRunner.Stub() {
|
IRecentsAnimationRunner.Stub() {
|
||||||
|
override fun onTransact(
|
||||||
|
code: Int,
|
||||||
|
data: Parcel,
|
||||||
|
reply: Parcel?,
|
||||||
|
flags: Int,
|
||||||
|
): Boolean {
|
||||||
|
if (usesNothingOs4BaklavaInitialRecentsTransitionAidl()
|
||||||
|
&& code == LC_TRANSACTION_onAnimationStartWithSurfaceTransaction) {
|
||||||
|
// LC-Note: What even the fuck this is (this handles a Nothing OS 4 binder transaction)
|
||||||
|
data.enforceInterface(IRecentsAnimationRunner.DESCRIPTOR) // This can be mistaken for IRecentsAnimationController, keep it this way
|
||||||
|
val controller = IRecentsAnimationController.Stub.asInterface(
|
||||||
|
data.readStrongBinder())
|
||||||
|
val transitionInfo = data.readTypedObject(TransitionInfo.CREATOR)
|
||||||
|
val transaction = data.readTypedObject(Transaction.CREATOR)
|
||||||
|
val apps = data.createTypedArray(RemoteAnimationTarget.CREATOR)
|
||||||
|
val wallpapers = data.createTypedArray(RemoteAnimationTarget.CREATOR)
|
||||||
|
val homeContentInsets = data.readTypedObject(Rect.CREATOR)
|
||||||
|
val minimizedHomeBounds = data.readTypedObject(Rect.CREATOR)
|
||||||
|
val extras = data.readTypedObject(Bundle.CREATOR)
|
||||||
|
data.enforceNoDataAvail()
|
||||||
|
try {
|
||||||
|
transaction?.apply()
|
||||||
|
} finally {
|
||||||
|
transaction?.close()
|
||||||
|
}
|
||||||
|
onAnimationStart(
|
||||||
|
controller,
|
||||||
|
apps,
|
||||||
|
wallpapers,
|
||||||
|
homeContentInsets,
|
||||||
|
minimizedHomeBounds,
|
||||||
|
extras,
|
||||||
|
transitionInfo,
|
||||||
|
)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onTransact(code, data, reply, flags)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onAnimationStart(
|
override fun onAnimationStart(
|
||||||
controller: IRecentsAnimationController,
|
controller: IRecentsAnimationController,
|
||||||
apps: Array<RemoteAnimationTarget>?,
|
apps: Array<RemoteAnimationTarget>?,
|
||||||
@@ -1397,6 +1487,31 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context:
|
|||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SystemUiProxy"
|
private const val TAG = "SystemUiProxy"
|
||||||
|
|
||||||
|
/** LC-Note: Android 16.0 start recents transition binder code */
|
||||||
|
private const val LC_TRANSACTION_startRecentsTransition_AOSP_BaklavaInitial =
|
||||||
|
IBinder.FIRST_CALL_TRANSACTION + 4
|
||||||
|
|
||||||
|
/** LC-Note: Android 16.0, Nothing OS 4.0 start recents transition binder code whose value
|
||||||
|
* is higher than AOSP 16.0 or [LC_TRANSACTION_startRecentsTransition_AOSP_BaklavaInitial] */
|
||||||
|
private const val LC_TRANSACTION_startRecentsTransition_NothingOS_4_BaklavaInitial =
|
||||||
|
IBinder.FIRST_CALL_TRANSACTION + 5
|
||||||
|
|
||||||
|
/** LC-Note: onAnimationStartWithSurfaceTransac binder code */
|
||||||
|
private const val LC_TRANSACTION_onAnimationStartWithSurfaceTransaction =
|
||||||
|
IBinder.FIRST_CALL_TRANSACTION + 4
|
||||||
|
|
||||||
|
/** LC-Note: Should use AOSP 16.0 recents transition AIDL? */
|
||||||
|
private fun usesAOSPBaklavaInitialRecentsTransitionAidl(): Boolean {
|
||||||
|
return Build.VERSION.SDK_INT == Build.VERSION_CODES.BAKLAVA
|
||||||
|
&& isAndroidBaklavaInitial
|
||||||
|
}
|
||||||
|
|
||||||
|
/** LC-Note: Should use Nothing OS 16.0 recents transition AIDL? */
|
||||||
|
private fun usesNothingOs4BaklavaInitialRecentsTransitionAidl(): Boolean {
|
||||||
|
return usesAOSPBaklavaInitialRecentsTransitionAidl()
|
||||||
|
&& isNothingOs
|
||||||
|
}
|
||||||
|
|
||||||
@JvmField val INSTANCE = DaggerSingletonObject(LauncherAppComponent::getSystemUiProxy)
|
@JvmField val INSTANCE = DaggerSingletonObject(LauncherAppComponent::getSystemUiProxy)
|
||||||
|
|
||||||
private const val MSG_SET_SHELF_HEIGHT = 1
|
private const val MSG_SET_SHELF_HEIGHT = 1
|
||||||
|
|||||||
@@ -337,7 +337,9 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||||||
|
|
||||||
final ActivityOptions options = ActivityOptions.makeBasic();
|
final ActivityOptions options = ActivityOptions.makeBasic();
|
||||||
options.setPendingIntentBackgroundActivityStartMode(
|
options.setPendingIntentBackgroundActivityStartMode(
|
||||||
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS);
|
Utilities.ATLEAST_BAKLAVA // LC-Note: QuickSwitch compatibility!
|
||||||
|
? ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS
|
||||||
|
: ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
|
||||||
options.setTransientLaunch();
|
options.setTransientLaunch();
|
||||||
options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
|
options.setSourceInfo(ActivityOptions.SourceInfo.TYPE_RECENTS_ANIMATION, eventTime);
|
||||||
options.setLaunchDisplayId(mDisplayId);
|
options.setLaunchDisplayId(mDisplayId);
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.UiThread;
|
import androidx.annotation.UiThread;
|
||||||
|
|
||||||
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.dagger.ApplicationContext;
|
import com.android.launcher3.dagger.ApplicationContext;
|
||||||
import com.android.launcher3.dagger.LauncherAppSingleton;
|
import com.android.launcher3.dagger.LauncherAppSingleton;
|
||||||
import com.android.launcher3.statehandlers.DesktopVisibilityController;
|
import com.android.launcher3.statehandlers.DesktopVisibilityController;
|
||||||
@@ -161,7 +162,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta
|
|||||||
// task is brought to front, then mark other tasks behind as not-visible
|
// task is brought to front, then mark other tasks behind as not-visible
|
||||||
if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
|
if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
|
||||||
|| (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
|| (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
|
||||||
&& !taskInfo.isActivityStackTransparent)) {
|
&& (!Utilities.ATLEAST_BAKLAVA || !taskInfo.isActivityStackTransparent))) { // LC-Note: QuickSwitch compatibility!
|
||||||
// We've moved the task to the front of the list above, so only iterate the tasks after
|
// We've moved the task to the front of the list above, so only iterate the tasks after
|
||||||
for (int i = 1; i < mOrderedTaskList.size(); i++) {
|
for (int i = 1; i < mOrderedTaskList.size(); i++) {
|
||||||
final TaskInfo info = mOrderedTaskList.get(i);
|
final TaskInfo info = mOrderedTaskList.get(i);
|
||||||
|
|||||||
@@ -731,6 +731,7 @@ public class TouchInteractionService extends Service {
|
|||||||
|
|
||||||
private DisplayRepository mDisplayRepository;
|
private DisplayRepository mDisplayRepository;
|
||||||
|
|
||||||
|
@Nullable // LC-Note: QuickSwitch compatibility!
|
||||||
private QuickstepKeyGestureEventsManager mQuickstepKeyGestureEventsHandler;
|
private QuickstepKeyGestureEventsManager mQuickstepKeyGestureEventsHandler;
|
||||||
private DisplaysWithDecorationsRepositoryCompat mDisplaysWithDecorationsRepositoryCompat;
|
private DisplaysWithDecorationsRepositoryCompat mDisplaysWithDecorationsRepositoryCompat;
|
||||||
private CoroutineDispatcher mCoroutineDispatcher;
|
private CoroutineDispatcher mCoroutineDispatcher;
|
||||||
@@ -749,7 +750,9 @@ public class TouchInteractionService extends Service {
|
|||||||
mRotationTouchHelperRepository = RotationTouchHelper.REPOSITORY_INSTANCE.get(this);
|
mRotationTouchHelperRepository = RotationTouchHelper.REPOSITORY_INSTANCE.get(this);
|
||||||
mRecentsWindowManagerRepository = RecentsWindowManager.REPOSITORY_INSTANCE.get(this);
|
mRecentsWindowManagerRepository = RecentsWindowManager.REPOSITORY_INSTANCE.get(this);
|
||||||
mSystemDecorationChangeObserver = SystemDecorationChangeObserver.getINSTANCE().get(this);
|
mSystemDecorationChangeObserver = SystemDecorationChangeObserver.getINSTANCE().get(this);
|
||||||
mQuickstepKeyGestureEventsHandler = new QuickstepKeyGestureEventsManager(this);
|
if (Utilities.ATLEAST_V) { // LC-Note: QuickSwitch compatibility!
|
||||||
|
mQuickstepKeyGestureEventsHandler = new QuickstepKeyGestureEventsManager(this);
|
||||||
|
}
|
||||||
mCoroutineDispatcher = ProductionDispatchers.INSTANCE.getMain();
|
mCoroutineDispatcher = ProductionDispatchers.INSTANCE.getMain();
|
||||||
mDisplaysWithDecorationsRepositoryCompat =
|
mDisplaysWithDecorationsRepositoryCompat =
|
||||||
LauncherDisplaysWithDecorationsRepositoryCompat.getINSTANCE().get(this);
|
LauncherDisplaysWithDecorationsRepositoryCompat.getINSTANCE().get(this);
|
||||||
@@ -884,8 +887,10 @@ public class TouchInteractionService extends Service {
|
|||||||
onOverviewTargetChanged(mOverviewComponentObserver.isHomeAndOverviewSame());
|
onOverviewTargetChanged(mOverviewComponentObserver.isHomeAndOverviewSame());
|
||||||
|
|
||||||
mTaskbarManager.onUserUnlocked();
|
mTaskbarManager.onUserUnlocked();
|
||||||
mQuickstepKeyGestureEventsHandler.registerOverviewKeyGestureEvent(
|
if (mQuickstepKeyGestureEventsHandler != null) { // LC-Note: QuickSwitch compatibility!
|
||||||
createOverviewGestureHandler());
|
mQuickstepKeyGestureEventsHandler.registerOverviewKeyGestureEvent(
|
||||||
|
createOverviewGestureHandler());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public OverviewCommandHelper getOverviewCommandHelper() {
|
public OverviewCommandHelper getOverviewCommandHelper() {
|
||||||
@@ -971,7 +976,9 @@ public class TouchInteractionService extends Service {
|
|||||||
+ " instance=" + System.identityHashCode(this));
|
+ " instance=" + System.identityHashCode(this));
|
||||||
if (LockedUserState.get(this).isUserUnlocked()) {
|
if (LockedUserState.get(this).isUserUnlocked()) {
|
||||||
mInputConsumer.unregisterInputConsumer();
|
mInputConsumer.unregisterInputConsumer();
|
||||||
mQuickstepKeyGestureEventsHandler.onDestroy();
|
if (mQuickstepKeyGestureEventsHandler != null) { // LC-Note: QuickSwitch compatibility!
|
||||||
|
mQuickstepKeyGestureEventsHandler.onDestroy();
|
||||||
|
}
|
||||||
mOverviewComponentObserver.setHomeDisabled(false);
|
mOverviewComponentObserver.setHomeDisabled(false);
|
||||||
mOverviewComponentObserver.removeOverviewChangeListener(mOverviewChangeListener);
|
mOverviewComponentObserver.removeOverviewChangeListener(mOverviewChangeListener);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Trace
|
import android.os.Trace
|
||||||
import android.view.Display.DEFAULT_DISPLAY
|
import android.view.Display.DEFAULT_DISPLAY
|
||||||
|
import com.android.launcher3.Utilities
|
||||||
import com.android.launcher3.provider.RestoreDbTask
|
import com.android.launcher3.provider.RestoreDbTask
|
||||||
import com.android.launcher3.util.Executors
|
import com.android.launcher3.util.Executors
|
||||||
import com.android.launcher3.util.LockedUserState
|
import com.android.launcher3.util.LockedUserState
|
||||||
@@ -41,6 +42,8 @@ object ActivityPreloadUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun preloadOverview(ctx: Context, fromInit: Boolean, forSUWAllSet: Boolean) {
|
private fun preloadOverview(ctx: Context, fromInit: Boolean, forSUWAllSet: Boolean) {
|
||||||
|
if (!Utilities.ATLEAST_BAKLAVA) return // LC-Note: QuickSwitch compatibility!
|
||||||
|
|
||||||
Trace.beginSection("preloadOverview(fromInit=$fromInit, forSUWAllSet=$forSUWAllSet)")
|
Trace.beginSection("preloadOverview(fromInit=$fromInit, forSUWAllSet=$forSUWAllSet)")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.util.Log
|
|||||||
import android.view.Display.DEFAULT_DISPLAY
|
import android.view.Display.DEFAULT_DISPLAY
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import com.android.internal.app.AssistUtils
|
import com.android.internal.app.AssistUtils
|
||||||
|
import com.android.launcher3.Utilities
|
||||||
import com.android.launcher3.dagger.ApplicationContext
|
import com.android.launcher3.dagger.ApplicationContext
|
||||||
import com.android.launcher3.logging.StatsLogManager
|
import com.android.launcher3.logging.StatsLogManager
|
||||||
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_ASSISTANT_FAILED_SERVICE_ERROR
|
import com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_LAUNCH_ASSISTANT_FAILED_SERVICE_ERROR
|
||||||
@@ -62,7 +63,11 @@ internal constructor(
|
|||||||
SystemUiProxy.INSTANCE[context],
|
SystemUiProxy.INSTANCE[context],
|
||||||
StatsLogManager.newInstance(context),
|
StatsLogManager.newInstance(context),
|
||||||
ContextualSearchHapticManager.INSTANCE[context],
|
ContextualSearchHapticManager.INSTANCE[context],
|
||||||
context.getSystemService(ContextualSearchManager::class.java),
|
if (Utilities.ATLEAST_V) {
|
||||||
|
context.getSystemService(ContextualSearchManager::class.java)
|
||||||
|
} else { // LC-Note: QuickSwitch compatibility!
|
||||||
|
null
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -80,13 +85,20 @@ internal constructor(
|
|||||||
systemUiProxy,
|
systemUiProxy,
|
||||||
logManagerFactory.create(context),
|
logManagerFactory.create(context),
|
||||||
hapticManager,
|
hapticManager,
|
||||||
context.getSystemService(ContextualSearchManager::class.java),
|
if (Utilities.ATLEAST_V) { // LC-Note: QuickSwitch compatibility!
|
||||||
|
context.getSystemService(ContextualSearchManager::class.java)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
/** @return Array of AssistUtils.INVOCATION_TYPE_* that we want to handle instead of SysUI. */
|
/** @return Array of AssistUtils.INVOCATION_TYPE_* that we want to handle instead of SysUI. */
|
||||||
fun getSysUiAssistOverrideInvocationTypes(): IntArray {
|
fun getSysUiAssistOverrideInvocationTypes(): IntArray {
|
||||||
val overrideInvocationTypes = com.android.launcher3.util.IntArray()
|
val overrideInvocationTypes = com.android.launcher3.util.IntArray()
|
||||||
if (context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
|
// LC-Note: QuickSwitch compatibility!
|
||||||
|
if (Utilities.ATLEAST_V &&
|
||||||
|
context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)
|
||||||
|
) {
|
||||||
overrideInvocationTypes.add(AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS)
|
overrideInvocationTypes.add(AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS)
|
||||||
}
|
}
|
||||||
return overrideInvocationTypes.toArray()
|
return overrideInvocationTypes.toArray()
|
||||||
@@ -98,7 +110,11 @@ internal constructor(
|
|||||||
*/
|
*/
|
||||||
fun tryStartAssistOverride(invocationType: Int): Boolean {
|
fun tryStartAssistOverride(invocationType: Int): Boolean {
|
||||||
if (invocationType == AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS) {
|
if (invocationType == AssistUtils.INVOCATION_TYPE_HOME_BUTTON_LONG_PRESS) {
|
||||||
if (!context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
|
// LC-Note: QuickSwitch compatibility!
|
||||||
|
if (
|
||||||
|
!Utilities.ATLEAST_V ||
|
||||||
|
!context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)
|
||||||
|
) {
|
||||||
// When Contextual Search is disabled, fall back to Assistant.
|
// When Contextual Search is disabled, fall back to Assistant.
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -142,7 +158,8 @@ internal constructor(
|
|||||||
*/
|
*/
|
||||||
fun runContextualSearchInvocationChecksAndLogFailures(): Boolean {
|
fun runContextualSearchInvocationChecksAndLogFailures(): Boolean {
|
||||||
if (
|
if (
|
||||||
contextualSearchManager == null ||
|
!Utilities.ATLEAST_V || // LC-Note: QuickSwitch compatibility!
|
||||||
|
contextualSearchManager == null ||
|
||||||
!context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)
|
!context.packageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)
|
||||||
) {
|
) {
|
||||||
Log.i(TAG, "Contextual Search invocation failed: no ContextualSearchManager")
|
Log.i(TAG, "Contextual Search invocation failed: no ContextualSearchManager")
|
||||||
|
|||||||
@@ -99,12 +99,23 @@ public class ContextualSearchStateManager {
|
|||||||
mContextualSearchPackageReceiver =
|
mContextualSearchPackageReceiver =
|
||||||
new SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR,
|
new SimpleBroadcastReceiver(context, UI_HELPER_EXECUTOR,
|
||||||
(unused) -> requestUpdateProperties());
|
(unused) -> requestUpdateProperties());
|
||||||
mContextualSearchPackage = mContext.getResources().getString(
|
|
||||||
com.android.internal.R.string.config_defaultContextualSearchPackageName);
|
// LC-Note: QuickSwitch compatibility!
|
||||||
|
String resolvedCSPkgName;
|
||||||
|
try {
|
||||||
|
resolvedCSPkgName = mContext.getResources().getString(
|
||||||
|
com.android.internal.R.string.config_defaultContextualSearchPackageName);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Failed to get config_defaultContextualSearchPackageName", e);
|
||||||
|
resolvedCSPkgName = "";
|
||||||
|
}
|
||||||
|
mContextualSearchPackage = resolvedCSPkgName;
|
||||||
|
|
||||||
mSystemUiProxy = systemUiProxy;
|
mSystemUiProxy = systemUiProxy;
|
||||||
mTopTaskTracker = topTaskTracker;
|
mTopTaskTracker = topTaskTracker;
|
||||||
|
|
||||||
if (areAllContextualSearchFlagsDisabled()
|
if (!Utilities.ATLEAST_V // LC-Note: QuickSwitch compatibility!
|
||||||
|
|| areAllContextualSearchFlagsDisabled()
|
||||||
|| !context.getPackageManager().hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
|
|| !context.getPackageManager().hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
|
||||||
// If we had previously registered a SystemAction which is no longer valid, we need to
|
// If we had previously registered a SystemAction which is no longer valid, we need to
|
||||||
// unregister it here.
|
// unregister it here.
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ public final class FeatureFlags {
|
|||||||
DISABLED, "Sends a notification whenever launcher encounters an uncaught exception.");
|
DISABLED, "Sends a notification whenever launcher encounters an uncaught exception.");
|
||||||
|
|
||||||
public static final boolean ENABLE_TASKBAR_NAVBAR_UNIFICATION =
|
public static final boolean ENABLE_TASKBAR_NAVBAR_UNIFICATION =
|
||||||
enableTaskbarNavbarUnification() && (!isPhone() || enableTaskbarOnPhones());
|
Utilities.ATLEAST_V && enableTaskbarNavbarUnification()
|
||||||
|
&& (!isPhone() || enableTaskbarOnPhones()); // LC-Note: QuickSwitch, Note, when this is enabled, it can crash with type 2019 on Android 14 and under
|
||||||
|
|
||||||
private static boolean isPhone() {
|
private static boolean isPhone() {
|
||||||
final boolean isPhone;
|
final boolean isPhone;
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import androidx.annotation.Nullable;
|
|||||||
|
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
|
|
||||||
|
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@@ -111,8 +113,10 @@ public class Task {
|
|||||||
this.displayId = t.displayId;
|
this.displayId = t.displayId;
|
||||||
this.baseActivity = t.baseActivity;
|
this.baseActivity = t.baseActivity;
|
||||||
this.numActivities = t.numActivities;
|
this.numActivities = t.numActivities;
|
||||||
this.isTopActivityNoDisplay = t.isTopActivityNoDisplay;
|
if (LawnchairQuickstepCompat.ATLEAST_BAKLAVA) { // LC-Note: QuickSwitch compatibility!
|
||||||
this.isActivityStackTransparent = t.isActivityStackTransparent;
|
this.isTopActivityNoDisplay = t.isTopActivityNoDisplay;
|
||||||
|
this.isActivityStackTransparent = t.isActivityStackTransparent;
|
||||||
|
}
|
||||||
updateHashCode();
|
updateHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ dependencies {
|
|||||||
compileOnly projects.msdllib
|
compileOnly projects.msdllib
|
||||||
compileOnly projects.flags
|
compileOnly projects.flags
|
||||||
compileOnly projects.utils
|
compileOnly projects.utils
|
||||||
|
compileOnly libs.chickenhook.restrictionbypass
|
||||||
}
|
}
|
||||||
|
|
||||||
ksp {
|
ksp {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ import android.annotation.SuppressLint;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.WindowConfiguration;
|
import android.app.WindowConfiguration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
import android.view.RemoteAnimationTarget;
|
import android.view.RemoteAnimationTarget;
|
||||||
@@ -51,6 +52,8 @@ import android.view.SurfaceControl;
|
|||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.window.TransitionInfo;
|
import android.window.TransitionInfo;
|
||||||
|
|
||||||
|
import org.chickenhook.restrictionbypass.RestrictionBypass;
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
/** Various utility functions for transitions. */
|
/** Various utility functions for transitions. */
|
||||||
@@ -408,7 +411,7 @@ public class TransitionUtil {
|
|||||||
null,
|
null,
|
||||||
new Rect(change.getStartAbsBounds()),
|
new Rect(change.getStartAbsBounds()),
|
||||||
taskInfo,
|
taskInfo,
|
||||||
change.isAllowEnterPip(),
|
getAllowEnterPip(change), // LC-Note: QuickSwitch compatibility!
|
||||||
INVALID_WINDOW_TYPE
|
INVALID_WINDOW_TYPE
|
||||||
);
|
);
|
||||||
target.setWillShowImeOnTarget(
|
target.setWillShowImeOnTarget(
|
||||||
@@ -418,6 +421,28 @@ public class TransitionUtil {
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Can you enter picture-in-picture mode?
|
||||||
|
* <p>
|
||||||
|
* SDK 35 or above: isAllowEnterPip()
|
||||||
|
* <p>
|
||||||
|
* SDK 34 or below: getAllowEnterPip()
|
||||||
|
* <p>
|
||||||
|
* LC-Note: QuickSwitch compatibility!
|
||||||
|
*
|
||||||
|
* @return true if the change allows entering picture-in-picture mode, false otherwise
|
||||||
|
* */
|
||||||
|
private static boolean getAllowEnterPip(TransitionInfo.Change change) {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) {
|
||||||
|
return change.isAllowEnterPip();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return (Boolean) RestrictionBypass.getMethod(
|
||||||
|
TransitionInfo.Change.class, "getAllowEnterPip").invoke(change);
|
||||||
|
} catch (ReflectiveOperationException e) {
|
||||||
|
throw new IllegalStateException("Unable to read allowEnterPip from transition change", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new RemoteAnimationTarget from the provided change and leash
|
* Creates a new RemoteAnimationTarget from the provided change and leash
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -18,11 +18,30 @@ package com.android.wm.shell.shared.pip
|
|||||||
|
|
||||||
import android.app.AppGlobals
|
import android.app.AppGlobals
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
import android.window.DesktopExperienceFlags.ENABLE_DESKTOP_WINDOWING_PIP
|
import android.window.DesktopExperienceFlags.ENABLE_DESKTOP_WINDOWING_PIP
|
||||||
import com.android.wm.shell.Flags
|
import com.android.wm.shell.Flags
|
||||||
|
|
||||||
class PipFlags {
|
class PipFlags {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
/** LC-Note: Can you enable desktop windowing picture-in-picture?
|
||||||
|
*
|
||||||
|
* SDK 36.1 or above: ENABLE_DESKTOP_WINDOWING_PIP.isTrue
|
||||||
|
*
|
||||||
|
* SDK Anything else: false
|
||||||
|
*
|
||||||
|
* Note when an exception occurred it will default to false
|
||||||
|
*/
|
||||||
|
private val enableDesktopWindowingPipCompat = Build.VERSION.SDK_INT >= 36 && Build.VERSION.SDK_INT_FULL >= 3600001 && try { // Literal int because https://github.com/LawnchairLauncher/lawnchair/issues/6817
|
||||||
|
ENABLE_DESKTOP_WINDOWING_PIP.isTrue
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.d("LC-PipFlags", "Failed to get ENABLE_DESKTOP_WINDOWING_PIP flag, defaulting to false", e)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if PiP2 implementation should be used. Special note: if PiP on Desktop
|
* Returns true if PiP2 implementation should be used. Special note: if PiP on Desktop
|
||||||
* Windowing is enabled, override the PiP2 gantry flag to be ON.
|
* Windowing is enabled, override the PiP2 gantry flag to be ON.
|
||||||
@@ -31,7 +50,7 @@ class PipFlags {
|
|||||||
val isPip2ExperimentEnabled: Boolean by lazy {
|
val isPip2ExperimentEnabled: Boolean by lazy {
|
||||||
val isTv = AppGlobals.getPackageManager().hasSystemFeature(
|
val isTv = AppGlobals.getPackageManager().hasSystemFeature(
|
||||||
PackageManager.FEATURE_LEANBACK, 0)
|
PackageManager.FEATURE_LEANBACK, 0)
|
||||||
(Flags.enablePip2() || ENABLE_DESKTOP_WINDOWING_PIP.isTrue) && !isTv
|
(Flags.enablePip2() || enableDesktopWindowingPipCompat) && !isTv
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
Reference in new issue
Block a user