feat: Add option to clear home screen in settings (#6125)
Signed-off-by: abhixv <abhi.sharma1@hotmail.com>
This commit is contained in:
committed by
Pun Butrach
parent
9898749619
commit
5f3a03f4fb
@@ -9,7 +9,6 @@ import app.lawnchair.compatlib.RemoteTransitionCompat
|
||||
import app.lawnchair.compatlib.eleven.QuickstepCompatFactoryVR
|
||||
import app.lawnchair.compatlib.fifteen.QuickstepCompatFactoryVV
|
||||
import app.lawnchair.compatlib.fourteen.QuickstepCompatFactoryVU
|
||||
import app.lawnchair.compatlib.sixteen.QuickstepCompatFactoryVBaklava
|
||||
import app.lawnchair.compatlib.ten.QuickstepCompatFactoryVQ
|
||||
import app.lawnchair.compatlib.thirteen.QuickstepCompatFactoryVT
|
||||
import app.lawnchair.compatlib.twelve.QuickstepCompatFactoryVS
|
||||
@@ -40,13 +39,8 @@ object LawnchairQuickstepCompat {
|
||||
@JvmField
|
||||
val ATLEAST_V: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM
|
||||
|
||||
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.BAKLAVA)
|
||||
@JvmField
|
||||
val ATLEAST_BAKLAVA: Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA
|
||||
|
||||
@JvmStatic
|
||||
val factory: QuickstepCompatFactory = when {
|
||||
ATLEAST_BAKLAVA -> QuickstepCompatFactoryVBaklava()
|
||||
ATLEAST_V -> QuickstepCompatFactoryVV()
|
||||
ATLEAST_U -> QuickstepCompatFactoryVU()
|
||||
ATLEAST_T -> QuickstepCompatFactoryVT()
|
||||
|
||||
@@ -37,43 +37,51 @@ import kotlinx.coroutines.launch
|
||||
* @param operand The [Evaluator.ConditionOperand] to apply to the conditions.
|
||||
*/
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class CombinedCondition(
|
||||
class CombinedCondition
|
||||
constructor(
|
||||
private val scope: CoroutineScope,
|
||||
private val conditions: Collection<Condition>,
|
||||
@Evaluator.ConditionOperand private val operand: Int,
|
||||
@Evaluator.ConditionOperand private val operand: Int
|
||||
) : Condition(scope, null, false) {
|
||||
|
||||
private var job: Job? = null
|
||||
private val _startStrategy by lazy { calculateStartStrategy() }
|
||||
|
||||
override suspend fun start() {
|
||||
val groupedConditions = conditions.groupBy { it.isOverridingCondition }
|
||||
override fun start() {
|
||||
job =
|
||||
scope.launch {
|
||||
val groupedConditions = conditions.groupBy { it.isOverridingCondition }
|
||||
|
||||
lazilyEvaluate(
|
||||
conditions = groupedConditions.getOrDefault(true, emptyList()),
|
||||
filterUnknown = true,
|
||||
)
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { overriddenValue ->
|
||||
// If there are overriding conditions with values set, they take precedence.
|
||||
if (overriddenValue == null) {
|
||||
lazilyEvaluate(
|
||||
conditions = groupedConditions.getOrDefault(false, emptyList()),
|
||||
filterUnknown = false,
|
||||
lazilyEvaluate(
|
||||
conditions = groupedConditions.getOrDefault(true, emptyList()),
|
||||
filterUnknown = true
|
||||
)
|
||||
} else {
|
||||
flowOf(overriddenValue)
|
||||
}
|
||||
}
|
||||
.collect { conditionMet ->
|
||||
if (conditionMet == null) {
|
||||
clearCondition()
|
||||
} else {
|
||||
updateCondition(conditionMet)
|
||||
}
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { overriddenValue ->
|
||||
// If there are overriding conditions with values set, they take precedence.
|
||||
if (overriddenValue == null) {
|
||||
lazilyEvaluate(
|
||||
conditions = groupedConditions.getOrDefault(false, emptyList()),
|
||||
filterUnknown = false
|
||||
)
|
||||
} else {
|
||||
flowOf(overriddenValue)
|
||||
}
|
||||
}
|
||||
.collect { conditionMet ->
|
||||
if (conditionMet == null) {
|
||||
clearCondition()
|
||||
} else {
|
||||
updateCondition(conditionMet)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun stop() {}
|
||||
override fun stop() {
|
||||
job?.cancel()
|
||||
job = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a list of conditions lazily with support for short-circuiting. Conditions are
|
||||
@@ -180,6 +188,7 @@ class CombinedCondition(
|
||||
return startStrategy
|
||||
}
|
||||
|
||||
override val startStrategy: Int
|
||||
get() = _startStrategy
|
||||
override fun getStartStrategy(): Int {
|
||||
return _startStrategy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ import kotlinx.coroutines.launch
|
||||
fun Flow<Boolean>.toCondition(
|
||||
scope: CoroutineScope,
|
||||
@StartStrategy strategy: Int,
|
||||
initialValue: Boolean? = null,
|
||||
initialValue: Boolean? = null
|
||||
): Condition {
|
||||
return object : Condition(scope, initialValue, false) {
|
||||
var job: Job? = null
|
||||
|
||||
override suspend fun start() {
|
||||
override fun start() {
|
||||
job = scope.launch { collect { updateCondition(it) } }
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ fun Flow<Boolean>.toCondition(
|
||||
job = null
|
||||
}
|
||||
|
||||
override val startStrategy: Int
|
||||
get() = strategy
|
||||
override fun getStartStrategy() = strategy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,16 +36,13 @@ fun Flow<Boolean>.toCondition(
|
||||
fun Condition.toFlow(): Flow<Boolean?> {
|
||||
return callbackFlow {
|
||||
val callback =
|
||||
object : Condition.Callback {
|
||||
override fun onConditionChanged(condition: Condition) {
|
||||
if (condition.isConditionSet) {
|
||||
trySend(condition.isConditionMet)
|
||||
} else {
|
||||
trySend(null)
|
||||
}
|
||||
Condition.Callback { condition ->
|
||||
if (condition.isConditionSet) {
|
||||
trySend(condition.isConditionMet)
|
||||
} else {
|
||||
trySend(null)
|
||||
}
|
||||
}
|
||||
|
||||
addCallback(callback)
|
||||
callback.onConditionChanged(this@toFlow)
|
||||
awaitClose { removeCallback(callback) }
|
||||
|
||||
+5
-6
@@ -128,20 +128,19 @@ public class PipSurfaceTransactionHelper {
|
||||
mTmpDestinationRect.inset(insets);
|
||||
// Scale by the shortest edge and offset such that the top/left of the scaled inset
|
||||
// source rect aligns with the top/left of the destination bounds
|
||||
final float scale = Math.max((float) destinationBounds.width() / sourceBounds.width(),
|
||||
(float) destinationBounds.height() / sourceBounds.height());
|
||||
final float scale = sourceBounds.width() <= sourceBounds.height()
|
||||
? (float) destinationBounds.width() / sourceBounds.width()
|
||||
: (float) destinationBounds.height() / sourceBounds.height();
|
||||
mTmpTransform.setRotate(degree, 0, 0);
|
||||
mTmpTransform.postScale(scale, scale);
|
||||
final float cornerRadius = getScaledCornerRadius(mTmpDestinationRect, destinationBounds);
|
||||
// adjust the positions, take account also the insets
|
||||
final float adjustedPositionX, adjustedPositionY;
|
||||
if (degree < 0) {
|
||||
// Counter-clockwise rotation.
|
||||
adjustedPositionX = positionX - insets.top * scale;
|
||||
adjustedPositionX = positionX + insets.top * scale;
|
||||
adjustedPositionY = positionY + insets.left * scale;
|
||||
} else {
|
||||
// Clockwise rotation.
|
||||
adjustedPositionX = positionX + insets.top * scale;
|
||||
adjustedPositionX = positionX - insets.top * scale;
|
||||
adjustedPositionY = positionY - insets.left * scale;
|
||||
}
|
||||
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
|
||||
|
||||
@@ -27,10 +27,9 @@ public interface PluginEnabler {
|
||||
int DISABLED_INVALID_VERSION = 2;
|
||||
int DISABLED_FROM_EXPLICIT_CRASH = 3;
|
||||
int DISABLED_FROM_SYSTEM_CRASH = 4;
|
||||
int DISABLED_UNKNOWN = 100;
|
||||
|
||||
@IntDef({ENABLED, DISABLED_MANUALLY, DISABLED_INVALID_VERSION, DISABLED_FROM_EXPLICIT_CRASH,
|
||||
DISABLED_FROM_SYSTEM_CRASH, DISABLED_UNKNOWN})
|
||||
DISABLED_FROM_SYSTEM_CRASH})
|
||||
@interface DisableReason {
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,6 @@ import com.android.systemui.plugins.Plugin;
|
||||
import com.android.systemui.plugins.PluginFragment;
|
||||
import com.android.systemui.plugins.PluginLifecycleManager;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.plugins.PluginProtector;
|
||||
import com.android.systemui.plugins.PluginWrapper;
|
||||
import com.android.systemui.plugins.ProtectedPluginListener;
|
||||
|
||||
import dalvik.system.PathClassLoader;
|
||||
|
||||
@@ -52,8 +49,7 @@ import java.util.function.Supplier;
|
||||
*
|
||||
* @param <T> The type of plugin that this contains.
|
||||
*/
|
||||
public class PluginInstance<T extends Plugin>
|
||||
implements PluginLifecycleManager, ProtectedPluginListener {
|
||||
public class PluginInstance<T extends Plugin> implements PluginLifecycleManager {
|
||||
private static final String TAG = "PluginInstance";
|
||||
|
||||
private final Context mAppContext;
|
||||
@@ -62,7 +58,6 @@ public class PluginInstance<T extends Plugin>
|
||||
private final PluginFactory<T> mPluginFactory;
|
||||
private final String mTag;
|
||||
|
||||
private boolean mHasError = false;
|
||||
private BiConsumer<String, String> mLogConsumer = null;
|
||||
private Context mPluginContext;
|
||||
private T mPlugin;
|
||||
@@ -92,11 +87,6 @@ public class PluginInstance<T extends Plugin>
|
||||
return mTag;
|
||||
}
|
||||
|
||||
/** */
|
||||
public boolean hasError() {
|
||||
return mHasError;
|
||||
}
|
||||
|
||||
public void setLogFunc(BiConsumer logConsumer) {
|
||||
mLogConsumer = logConsumer;
|
||||
}
|
||||
@@ -107,22 +97,8 @@ public class PluginInstance<T extends Plugin>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean onFail(String className, String methodName, Throwable failure) {
|
||||
Log.e(TAG, "Failure from " + mPlugin + ". Disabling Plugin.");
|
||||
mHasError = true;
|
||||
unloadPlugin();
|
||||
mListener.onPluginDetached(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Alerts listener and plugin that the plugin has been created. */
|
||||
public synchronized void onCreate() {
|
||||
if (mHasError) {
|
||||
log("Previous Fatal Exception detected for plugin class");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean loadPlugin = mListener.onPluginAttached(this);
|
||||
if (!loadPlugin) {
|
||||
if (mPlugin != null) {
|
||||
@@ -133,17 +109,13 @@ public class PluginInstance<T extends Plugin>
|
||||
}
|
||||
|
||||
if (mPlugin == null) {
|
||||
log("onCreate: auto-load");
|
||||
log("onCreate auto-load");
|
||||
loadPlugin();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkVersion()) {
|
||||
log("onCreate: version check failed");
|
||||
return;
|
||||
}
|
||||
|
||||
log("onCreate: load callbacks");
|
||||
mPluginFactory.checkVersion(mPlugin);
|
||||
if (!(mPlugin instanceof PluginFragment)) {
|
||||
// Only call onCreate for plugins that aren't fragments, as fragments
|
||||
// will get the onCreate as part of the fragment lifecycle.
|
||||
@@ -154,12 +126,6 @@ public class PluginInstance<T extends Plugin>
|
||||
|
||||
/** Alerts listener and plugin that the plugin is being shutdown. */
|
||||
public synchronized void onDestroy() {
|
||||
if (mHasError) {
|
||||
// Detached in error handler
|
||||
log("onDestroy - no-op");
|
||||
return;
|
||||
}
|
||||
|
||||
log("onDestroy");
|
||||
unloadPlugin();
|
||||
mListener.onPluginDetached(this);
|
||||
@@ -168,37 +134,28 @@ public class PluginInstance<T extends Plugin>
|
||||
/** Returns the current plugin instance (if it is loaded). */
|
||||
@Nullable
|
||||
public T getPlugin() {
|
||||
return mHasError ? null : mPlugin;
|
||||
return mPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and creates the plugin if it does not exist.
|
||||
*/
|
||||
public synchronized void loadPlugin() {
|
||||
if (mHasError) {
|
||||
log("Previous Fatal Exception detected for plugin class");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPlugin != null) {
|
||||
log("Load request when already loaded");
|
||||
return;
|
||||
}
|
||||
|
||||
// Both of these calls take about 1 - 1.5 seconds in test runs
|
||||
mPlugin = mPluginFactory.createPlugin(this);
|
||||
mPlugin = mPluginFactory.createPlugin();
|
||||
mPluginContext = mPluginFactory.createPluginContext();
|
||||
if (mPlugin == null || mPluginContext == null) {
|
||||
Log.e(mTag, "Requested load, but failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!checkVersion()) {
|
||||
log("loadPlugin: version check failed");
|
||||
return;
|
||||
}
|
||||
|
||||
log("Loaded plugin; running callbacks");
|
||||
mPluginFactory.checkVersion(mPlugin);
|
||||
if (!(mPlugin instanceof PluginFragment)) {
|
||||
// Only call onCreate for plugins that aren't fragments, as fragments
|
||||
// will get the onCreate as part of the fragment lifecycle.
|
||||
@@ -207,29 +164,6 @@ public class PluginInstance<T extends Plugin>
|
||||
mListener.onPluginLoaded(mPlugin, mPluginContext, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the plugin version, and permanently destroys the plugin instance on a failure
|
||||
*/
|
||||
private synchronized boolean checkVersion() {
|
||||
if (mHasError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mPlugin == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mPluginFactory.checkVersion(mPlugin)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Log.wtf(TAG, "Version check failed for " + mPlugin.getClass().getSimpleName());
|
||||
mHasError = true;
|
||||
unloadPlugin();
|
||||
mListener.onPluginDetached(this);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads and destroys the current plugin instance if it exists.
|
||||
*
|
||||
@@ -270,7 +204,7 @@ public class PluginInstance<T extends Plugin>
|
||||
}
|
||||
|
||||
public VersionInfo getVersionInfo() {
|
||||
return mPluginFactory.getVersionInfo(mPlugin);
|
||||
return mPluginFactory.checkVersion(mPlugin);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -361,19 +295,16 @@ public class PluginInstance<T extends Plugin>
|
||||
|
||||
/** Class that compares a plugin class against an implementation for version matching. */
|
||||
public interface VersionChecker {
|
||||
/** Compares two plugin classes. Returns true when match. */
|
||||
<T extends Plugin> boolean checkVersion(
|
||||
/** Compares two plugin classes. */
|
||||
<T extends Plugin> VersionInfo checkVersion(
|
||||
Class<T> instanceClass, Class<T> pluginClass, Plugin plugin);
|
||||
|
||||
/** Returns VersionInfo for the target class */
|
||||
<T extends Plugin> VersionInfo getVersionInfo(Class<T> instanceclass);
|
||||
}
|
||||
|
||||
/** Class that compares a plugin class against an implementation for version matching. */
|
||||
public static class VersionCheckerImpl implements VersionChecker {
|
||||
@Override
|
||||
/** Compares two plugin classes. */
|
||||
public <T extends Plugin> boolean checkVersion(
|
||||
public <T extends Plugin> VersionInfo checkVersion(
|
||||
Class<T> instanceClass, Class<T> pluginClass, Plugin plugin) {
|
||||
VersionInfo pluginVersion = new VersionInfo().addClass(pluginClass);
|
||||
VersionInfo instanceVersion = new VersionInfo().addClass(instanceClass);
|
||||
@@ -382,17 +313,11 @@ public class PluginInstance<T extends Plugin>
|
||||
} else if (plugin != null) {
|
||||
int fallbackVersion = plugin.getVersion();
|
||||
if (fallbackVersion != pluginVersion.getDefaultVersion()) {
|
||||
return false;
|
||||
throw new VersionInfo.InvalidVersionException("Invalid legacy version", false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
/** Returns the version info for the class */
|
||||
public <T extends Plugin> VersionInfo getVersionInfo(Class<T> instanceClass) {
|
||||
VersionInfo instanceVersion = new VersionInfo().addClass(instanceClass);
|
||||
return instanceVersion.hasVersionInfo() ? instanceVersion : null;
|
||||
return instanceVersion;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,16 +364,20 @@ public class PluginInstance<T extends Plugin>
|
||||
}
|
||||
|
||||
/** Creates the related plugin object from the factory */
|
||||
public T createPlugin(ProtectedPluginListener listener) {
|
||||
public T createPlugin() {
|
||||
try {
|
||||
ClassLoader loader = mClassLoaderFactory.get();
|
||||
Class<T> instanceClass = (Class<T>) Class.forName(
|
||||
mComponentName.getClassName(), true, loader);
|
||||
T result = (T) mInstanceFactory.create(instanceClass);
|
||||
Log.v(TAG, "Created plugin: " + result);
|
||||
return PluginProtector.protectIfAble(result, listener);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
Log.wtf(TAG, "Failed to load plugin", ex);
|
||||
return result;
|
||||
} catch (ClassNotFoundException ex) {
|
||||
Log.e(TAG, "Failed to load plugin", ex);
|
||||
} catch (IllegalAccessException ex) {
|
||||
Log.e(TAG, "Failed to load plugin", ex);
|
||||
} catch (InstantiationException ex) {
|
||||
Log.e(TAG, "Failed to load plugin", ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -465,27 +394,13 @@ public class PluginInstance<T extends Plugin>
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Check Version for the instance */
|
||||
public boolean checkVersion(T instance) {
|
||||
/** Check Version and create VersionInfo for instance */
|
||||
public VersionInfo checkVersion(T instance) {
|
||||
if (instance == null) {
|
||||
instance = createPlugin(null);
|
||||
}
|
||||
if (instance instanceof PluginWrapper) {
|
||||
instance = ((PluginWrapper<T>) instance).getPlugin();
|
||||
instance = createPlugin();
|
||||
}
|
||||
return mVersionChecker.checkVersion(
|
||||
(Class<T>) instance.getClass(), mPluginClass, instance);
|
||||
}
|
||||
|
||||
/** Get Version Info for the instance */
|
||||
public VersionInfo getVersionInfo(T instance) {
|
||||
if (instance == null) {
|
||||
instance = createPlugin(null);
|
||||
}
|
||||
if (instance instanceof PluginWrapper) {
|
||||
instance = ((PluginWrapper<T>) instance).getPlugin();
|
||||
}
|
||||
return mVersionChecker.getVersionInfo((Class<T>) instance.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@ import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
|
||||
import com.android.systemui.plugins.Plugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
@@ -64,7 +62,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
public PluginManagerImpl(Context context,
|
||||
PluginActionManager.Factory actionManagerFactory,
|
||||
boolean debuggable,
|
||||
@Nullable UncaughtExceptionPreHandlerManager preHandlerManager,
|
||||
UncaughtExceptionPreHandlerManager preHandlerManager,
|
||||
PluginEnabler pluginEnabler,
|
||||
PluginPrefs pluginPrefs,
|
||||
List<String> privilegedPlugins) {
|
||||
@@ -75,9 +73,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
mPluginPrefs = pluginPrefs;
|
||||
mPluginEnabler = pluginEnabler;
|
||||
|
||||
if (preHandlerManager != null) {
|
||||
preHandlerManager.registerHandler(new PluginExceptionHandler());
|
||||
}
|
||||
preHandlerManager.registerHandler(new PluginExceptionHandler());
|
||||
}
|
||||
|
||||
public boolean isDebuggable() {
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import com.android.internal.util.ScreenshotRequest;
|
||||
|
||||
@@ -69,10 +68,10 @@ interface ISystemUiProxy {
|
||||
|
||||
/**
|
||||
* Indicates that the given Assist invocation types should be handled by Launcher via
|
||||
* LauncherProxy#onAssistantOverrideInvoked and should not be invoked by SystemUI.
|
||||
* OverviewProxy#onAssistantOverrideInvoked and should not be invoked by SystemUI.
|
||||
*
|
||||
* @param invocationTypes The invocation types that will henceforth be handled via
|
||||
* LauncherProxy (Launcher); other invocation types should be handled by SysUI.
|
||||
* OverviewProxy (Launcher); other invocation types should be handled by SysUI.
|
||||
*/
|
||||
oneway void setAssistantOverridesRequested(in int[] invocationTypes) = 53;
|
||||
|
||||
@@ -103,9 +102,9 @@ interface ISystemUiProxy {
|
||||
oneway void expandNotificationPanel() = 29;
|
||||
|
||||
/**
|
||||
* Notifies SystemUI of a back KeyEvent.
|
||||
* Notifies SystemUI to invoke Back.
|
||||
*/
|
||||
oneway void onBackEvent(in KeyEvent keyEvent) = 44;
|
||||
oneway void onBackPressed() = 44;
|
||||
|
||||
/** Sets home rotation enabled. */
|
||||
oneway void setHomeRotationEnabled(boolean enabled) = 45;
|
||||
@@ -121,7 +120,7 @@ interface ISystemUiProxy {
|
||||
oneway void notifyTaskbarAutohideSuspend(boolean suspend) = 48;
|
||||
|
||||
/**
|
||||
* Notifies that the IME switcher button has been pressed.
|
||||
* Notifies SystemUI to invoke IME Switcher.
|
||||
*/
|
||||
oneway void onImeSwitcherPressed() = 49;
|
||||
|
||||
@@ -168,15 +167,5 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
oneway void toggleQuickSettingsPanel() = 56;
|
||||
|
||||
/**
|
||||
* Notifies that the IME Switcher button has been long pressed.
|
||||
*/
|
||||
oneway void onImeSwitcherLongPress() = 57;
|
||||
|
||||
/**
|
||||
* Updates contextual education stats when target gesture type is triggered.
|
||||
*/
|
||||
oneway void updateContextualEduStats(boolean isTrackpadGesture, String gestureType) = 58;
|
||||
|
||||
// Next id = 59
|
||||
// Next id = 57
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ package com.android.systemui.shared.recents.model;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
|
||||
import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE;
|
||||
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
|
||||
import static com.android.wm.shell.common.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES_WHEN_ACTIVE;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.TaskDescription;
|
||||
@@ -72,25 +72,6 @@ public class Task {
|
||||
@ViewDebug.ExportedProperty(category = "recents")
|
||||
public final int displayId;
|
||||
|
||||
/**
|
||||
* The component of the first activity in the task, can be considered the "application" of
|
||||
* this task.
|
||||
*/
|
||||
@Nullable
|
||||
public ComponentName baseActivity;
|
||||
/**
|
||||
* The number of activities in this task (including running).
|
||||
*/
|
||||
public int numActivities;
|
||||
/**
|
||||
* Whether the top activity is to be displayed. See {@link android.R.attr#windowNoDisplay}.
|
||||
*/
|
||||
public boolean isTopActivityNoDisplay;
|
||||
/**
|
||||
* Whether fillsParent() is false for every activity in the tasks stack.
|
||||
*/
|
||||
public boolean isActivityStackTransparent;
|
||||
|
||||
// The source component name which started this task
|
||||
public final ComponentName sourceComponent;
|
||||
|
||||
@@ -109,10 +90,6 @@ public class Task {
|
||||
this.userId = t.userId;
|
||||
this.lastActiveTime = t.lastActiveTime;
|
||||
this.displayId = t.displayId;
|
||||
this.baseActivity = t.baseActivity;
|
||||
this.numActivities = t.numActivities;
|
||||
this.isTopActivityNoDisplay = t.isTopActivityNoDisplay;
|
||||
this.isActivityStackTransparent = t.isActivityStackTransparent;
|
||||
updateHashCode();
|
||||
}
|
||||
|
||||
@@ -129,9 +106,7 @@ public class Task {
|
||||
}
|
||||
|
||||
public TaskKey(int id, int windowingMode, @NonNull Intent intent,
|
||||
ComponentName sourceComponent, int userId, long lastActiveTime, int displayId,
|
||||
@Nullable ComponentName baseActivity, int numActivities,
|
||||
boolean isTopActivityNoDisplay, boolean isActivityStackTransparent) {
|
||||
ComponentName sourceComponent, int userId, long lastActiveTime, int displayId) {
|
||||
this.id = id;
|
||||
this.windowingMode = windowingMode;
|
||||
this.baseIntent = intent;
|
||||
@@ -139,10 +114,6 @@ public class Task {
|
||||
this.userId = userId;
|
||||
this.lastActiveTime = lastActiveTime;
|
||||
this.displayId = displayId;
|
||||
this.baseActivity = baseActivity;
|
||||
this.numActivities = numActivities;
|
||||
this.isTopActivityNoDisplay = isTopActivityNoDisplay;
|
||||
this.isActivityStackTransparent = isActivityStackTransparent;
|
||||
updateHashCode();
|
||||
}
|
||||
|
||||
@@ -214,10 +185,6 @@ public class Task {
|
||||
parcel.writeLong(lastActiveTime);
|
||||
parcel.writeInt(displayId);
|
||||
parcel.writeTypedObject(sourceComponent, flags);
|
||||
parcel.writeTypedObject(baseActivity, flags);
|
||||
parcel.writeInt(numActivities);
|
||||
parcel.writeBoolean(isTopActivityNoDisplay);
|
||||
parcel.writeBoolean(isActivityStackTransparent);
|
||||
}
|
||||
|
||||
private static TaskKey readFromParcel(Parcel parcel) {
|
||||
@@ -228,14 +195,9 @@ public class Task {
|
||||
long lastActiveTime = parcel.readLong();
|
||||
int displayId = parcel.readInt();
|
||||
ComponentName sourceComponent = parcel.readTypedObject(ComponentName.CREATOR);
|
||||
ComponentName baseActivity = parcel.readTypedObject(ComponentName.CREATOR);
|
||||
int numActivities = parcel.readInt();
|
||||
boolean isTopActivityNoDisplay = parcel.readBoolean();
|
||||
boolean isActivityStackTransparent = parcel.readBoolean();
|
||||
|
||||
return new TaskKey(id, windowingMode, baseIntent, sourceComponent, userId,
|
||||
lastActiveTime, displayId, baseActivity, numActivities, isTopActivityNoDisplay,
|
||||
isActivityStackTransparent);
|
||||
lastActiveTime, displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -256,7 +218,6 @@ public class Task {
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public String title;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Nullable
|
||||
public String titleDescription;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public int colorPrimary;
|
||||
@@ -281,11 +242,9 @@ public class Task {
|
||||
|
||||
public Rect appBounds;
|
||||
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public boolean isVisible;
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "recents")
|
||||
public boolean isMinimized;
|
||||
// Last snapshot data, only used for recent tasks
|
||||
public ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
|
||||
new ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData();
|
||||
|
||||
public Task() {
|
||||
// Do nothing
|
||||
@@ -309,13 +268,6 @@ public class Task {
|
||||
taskInfo.topActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a task object from the given [taskInfo].
|
||||
*/
|
||||
public static Task from(TaskInfo taskInfo) {
|
||||
return from(new TaskKey(taskInfo), taskInfo, /* isLocked= */ false);
|
||||
}
|
||||
|
||||
public Task(TaskKey key) {
|
||||
this.key = key;
|
||||
this.taskDescription = new TaskDescription();
|
||||
@@ -324,10 +276,9 @@ public class Task {
|
||||
public Task(Task other) {
|
||||
this(other.key, other.colorPrimary, other.colorBackground, other.isDockable,
|
||||
other.isLocked, other.taskDescription, other.topActivity);
|
||||
lastSnapshotData.set(other.lastSnapshotData);
|
||||
positionInParent = other.positionInParent;
|
||||
appBounds = other.appBounds;
|
||||
isVisible = other.isVisible;
|
||||
isMinimized = other.isMinimized;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,10 +306,33 @@ public class Task {
|
||||
: key.baseIntent.getComponent();
|
||||
}
|
||||
|
||||
public void setLastSnapshotData(ActivityManager.RecentTaskInfo rawTask) {
|
||||
lastSnapshotData.set(rawTask.lastSnapshotData);
|
||||
}
|
||||
|
||||
public TaskKey getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the visible width to height ratio. Returns 0f if snapshot data is not available.
|
||||
*/
|
||||
public float getVisibleThumbnailRatio(boolean clipInsets) {
|
||||
if (lastSnapshotData.taskSize == null || lastSnapshotData.contentInsets == null) {
|
||||
return 0f;
|
||||
}
|
||||
|
||||
float availableWidth = lastSnapshotData.taskSize.x;
|
||||
float availableHeight = lastSnapshotData.taskSize.y;
|
||||
if (clipInsets) {
|
||||
availableWidth -=
|
||||
(lastSnapshotData.contentInsets.left + lastSnapshotData.contentInsets.right);
|
||||
availableHeight -=
|
||||
(lastSnapshotData.contentInsets.top + lastSnapshotData.contentInsets.bottom);
|
||||
}
|
||||
return availableWidth / availableHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) {
|
||||
@@ -374,11 +348,6 @@ public class Task {
|
||||
return key.equals(t.key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return key.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + key.toString() + "] " + title;
|
||||
|
||||
+8
-15
@@ -10,6 +10,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.wm.shell.util.SplitBounds;
|
||||
|
||||
/**
|
||||
* Utility class to position the thumbnail in the TaskView
|
||||
@@ -34,6 +35,8 @@ public class PreviewPositionHelper {
|
||||
|
||||
private final Matrix mMatrix = new Matrix();
|
||||
private boolean mIsOrientationChanged;
|
||||
private SplitBounds mSplitBounds;
|
||||
private int mDesiredStagePosition;
|
||||
|
||||
public Matrix getMatrix() {
|
||||
return mMatrix;
|
||||
@@ -47,6 +50,11 @@ public class PreviewPositionHelper {
|
||||
return mIsOrientationChanged;
|
||||
}
|
||||
|
||||
public void setSplitBounds(SplitBounds splitBounds, int desiredStagePosition) {
|
||||
mSplitBounds = splitBounds;
|
||||
mDesiredStagePosition = desiredStagePosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the matrix based on the provided parameters
|
||||
*/
|
||||
@@ -208,19 +216,4 @@ public class PreviewPositionHelper {
|
||||
}
|
||||
mMatrix.postTranslate(translateX, translateY);
|
||||
}
|
||||
|
||||
/**
|
||||
* A factory that returns a new instance of the {@link PreviewPositionHelper}.
|
||||
* <p>{@link PreviewPositionHelper} is a stateful helper, and hence when using it in distinct
|
||||
* scenarios, prefer fetching an object using this factory</p>
|
||||
* <p>Additionally, helpful for injecting mocks in tests</p>
|
||||
*/
|
||||
public static class PreviewPositionHelperFactory {
|
||||
/**
|
||||
* Returns a new {@link PreviewPositionHelper} for use in a distinct scenario.
|
||||
*/
|
||||
public PreviewPositionHelper create() {
|
||||
return new PreviewPositionHelper();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,16 @@
|
||||
|
||||
package com.android.systemui.shared.recents.utilities;
|
||||
|
||||
import static android.app.StatusBarManager.NAVBAR_BACK_DISMISS_IME;
|
||||
import static android.app.StatusBarManager.NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
|
||||
import static android.app.StatusBarManager.NAVBAR_IME_VISIBLE;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
|
||||
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
|
||||
import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SWITCHER_SHOWN;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.StatusBarManager.NavbarFlags;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.inputmethodservice.InputMethodService.BackDispositionMode;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -36,9 +33,6 @@ import android.util.DisplayMetrics;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.utils.windowmanager.WindowManagerUtils;
|
||||
|
||||
/* Common code */
|
||||
public class Utilities {
|
||||
|
||||
@@ -108,52 +102,44 @@ public class Utilities {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the navigation bar state flags with the given IME state.
|
||||
*
|
||||
* @param oldFlags current navigation bar state flags.
|
||||
* @param backDisposition the IME back disposition mode. Only takes effect if
|
||||
* {@code isImeVisible} is {@code true}.
|
||||
* @param isImeVisible whether the IME is currently visible.
|
||||
* @param showImeSwitcher whether the IME Switcher button should be shown. Only takes effect if
|
||||
* {@code isImeVisible} is {@code true}.
|
||||
* @return updated set of flags from InputMethodService based off {@param oldHints}
|
||||
* Leaves original hints unmodified
|
||||
*/
|
||||
@NavbarFlags
|
||||
public static int updateNavbarFlagsFromIme(@NavbarFlags int oldFlags,
|
||||
@BackDispositionMode int backDisposition, boolean isImeVisible,
|
||||
boolean showImeSwitcher) {
|
||||
int flags = oldFlags;
|
||||
public static int calculateBackDispositionHints(int oldHints, int backDisposition,
|
||||
boolean imeShown, boolean showImeSwitcher) {
|
||||
int hints = oldHints;
|
||||
switch (backDisposition) {
|
||||
case InputMethodService.BACK_DISPOSITION_DEFAULT:
|
||||
case InputMethodService.BACK_DISPOSITION_WILL_NOT_DISMISS:
|
||||
case InputMethodService.BACK_DISPOSITION_WILL_DISMISS:
|
||||
if (isImeVisible) {
|
||||
flags |= NAVBAR_BACK_DISMISS_IME;
|
||||
if (imeShown) {
|
||||
hints |= NAVIGATION_HINT_BACK_ALT;
|
||||
} else {
|
||||
flags &= ~NAVBAR_BACK_DISMISS_IME;
|
||||
hints &= ~NAVIGATION_HINT_BACK_ALT;
|
||||
}
|
||||
break;
|
||||
case InputMethodService.BACK_DISPOSITION_ADJUST_NOTHING:
|
||||
flags &= ~NAVBAR_BACK_DISMISS_IME;
|
||||
hints &= ~NAVIGATION_HINT_BACK_ALT;
|
||||
break;
|
||||
}
|
||||
if (isImeVisible) {
|
||||
flags |= NAVBAR_IME_VISIBLE;
|
||||
if (imeShown) {
|
||||
hints |= NAVIGATION_HINT_IME_SHOWN;
|
||||
} else {
|
||||
flags &= ~NAVBAR_IME_VISIBLE;
|
||||
hints &= ~NAVIGATION_HINT_IME_SHOWN;
|
||||
}
|
||||
if (showImeSwitcher && isImeVisible) {
|
||||
flags |= NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
|
||||
if (showImeSwitcher) {
|
||||
hints |= NAVIGATION_HINT_IME_SWITCHER_SHOWN;
|
||||
} else {
|
||||
flags &= ~NAVBAR_IME_SWITCHER_BUTTON_VISIBLE;
|
||||
hints &= ~NAVIGATION_HINT_IME_SWITCHER_SHOWN;
|
||||
}
|
||||
|
||||
return flags;
|
||||
return hints;
|
||||
}
|
||||
|
||||
/** @return whether or not {@param context} represents that of a large screen device or not */
|
||||
@TargetApi(Build.VERSION_CODES.R)
|
||||
public static boolean isLargeScreen(Context context) {
|
||||
return isLargeScreen(WindowManagerUtils.getWindowManager(context), context.getResources());
|
||||
return isLargeScreen(context.getSystemService(WindowManager.class), context.getResources());
|
||||
}
|
||||
|
||||
/** @return whether or not {@param context} represents that of a large screen device or not */
|
||||
@@ -169,10 +155,4 @@ public class Utilities {
|
||||
float densityRatio = (float) densityDpi / DisplayMetrics.DENSITY_DEFAULT;
|
||||
return (size / densityRatio);
|
||||
}
|
||||
|
||||
/** Whether a task is in freeform mode. */
|
||||
public static boolean isFreeformTask(Task task) {
|
||||
return task != null && task.getKey() != null
|
||||
&& task.getKey().windowingMode == WINDOWING_MODE_FREEFORM;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,36 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class RecentsTransition {
|
||||
|
||||
/**
|
||||
* Creates a new transition aspect scaled transition activity options.
|
||||
*/
|
||||
public static ActivityOptions createAspectScaleAnimation(Context context, Handler handler,
|
||||
boolean scaleUp, AppTransitionAnimationSpecsFuture animationSpecsFuture,
|
||||
final Runnable animationStartCallback) {
|
||||
final OnAnimationStartedListener animStartedListener = new OnAnimationStartedListener() {
|
||||
private boolean mHandled;
|
||||
|
||||
@Override
|
||||
public void onAnimationStarted(long elapsedRealTime) {
|
||||
// OnAnimationStartedListener can be called numerous times, so debounce here to
|
||||
// prevent multiple callbacks
|
||||
if (mHandled) {
|
||||
return;
|
||||
}
|
||||
mHandled = true;
|
||||
|
||||
if (animationStartCallback != null) {
|
||||
animationStartCallback.run();
|
||||
}
|
||||
}
|
||||
};
|
||||
final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(
|
||||
context, handler,
|
||||
animationSpecsFuture != null ? animationSpecsFuture.getFuture() : null,
|
||||
animStartedListener, scaleUp);
|
||||
return opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a animation-start callback in a binder that can be called from window manager.
|
||||
*/
|
||||
|
||||
@@ -136,9 +136,9 @@ constructor(
|
||||
val sampledRegionWithOffset = convertBounds(screenLocationBounds)
|
||||
if (
|
||||
sampledRegionWithOffset.left < 0.0 ||
|
||||
sampledRegionWithOffset.right > 1.0 ||
|
||||
sampledRegionWithOffset.top < 0.0 ||
|
||||
sampledRegionWithOffset.bottom > 1.0
|
||||
sampledRegionWithOffset.right > 1.0 ||
|
||||
sampledRegionWithOffset.top < 0.0 ||
|
||||
sampledRegionWithOffset.bottom > 1.0
|
||||
) {
|
||||
if (DEBUG)
|
||||
Log.d(
|
||||
@@ -192,7 +192,7 @@ constructor(
|
||||
pw.println("screen width: ${displaySize.x}, screen height: ${displaySize.y}")
|
||||
pw.println(
|
||||
"sampledRegionWithOffset: ${convertBounds(
|
||||
calculateScreenLocation(sampledView) ?: RectF())}"
|
||||
calculateScreenLocation(sampledView) ?: RectF())}"
|
||||
)
|
||||
pw.println(
|
||||
"initialSampling for ${if (isLockscreen) "lockscreen" else "homescreen" }" +
|
||||
|
||||
+1
-10
@@ -39,7 +39,6 @@ import androidx.annotation.BoolRes;
|
||||
import androidx.core.view.OneShotPreDrawListener;
|
||||
|
||||
import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position;
|
||||
import com.android.systemui.utils.windowmanager.WindowManagerUtils;
|
||||
|
||||
/**
|
||||
* Containing logic for the rotation button on the physical left bottom corner of the screen.
|
||||
@@ -89,7 +88,7 @@ public class FloatingRotationButton implements RotationButton {
|
||||
@DimenRes int taskbarBottomMargin, @DimenRes int buttonDiameter,
|
||||
@DimenRes int rippleMaxWidth, @BoolRes int floatingRotationBtnPositionLeftResource) {
|
||||
mContext = context;
|
||||
mWindowManager = WindowManagerUtils.getWindowManager(mContext);
|
||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
||||
mKeyButtonContainer = (ViewGroup) LayoutInflater.from(mContext).inflate(layout, null);
|
||||
mKeyButtonView = mKeyButtonContainer.findViewById(keyButtonId);
|
||||
mKeyButtonView.setVisibility(View.VISIBLE);
|
||||
@@ -126,7 +125,6 @@ public class FloatingRotationButton implements RotationButton {
|
||||
taskbarMarginLeft, taskbarMarginBottom, floatingRotationButtonPositionLeft);
|
||||
|
||||
final int diameter = res.getDimensionPixelSize(mButtonDiameterResource);
|
||||
mKeyButtonView.setDiameter(diameter);
|
||||
mContainerSize = diameter + Math.max(defaultMargin, Math.max(taskbarMarginLeft,
|
||||
taskbarMarginBottom));
|
||||
}
|
||||
@@ -197,7 +195,6 @@ public class FloatingRotationButton implements RotationButton {
|
||||
public void updateIcon(int lightIconColor, int darkIconColor) {
|
||||
mAnimatedDrawable = (AnimatedVectorDrawable) mKeyButtonView.getContext()
|
||||
.getDrawable(mRotationButtonController.getIconResId());
|
||||
mAnimatedDrawable.setBounds(0, 0, mKeyButtonView.getWidth(), mKeyButtonView.getHeight());
|
||||
mKeyButtonView.setImageDrawable(mAnimatedDrawable);
|
||||
mKeyButtonView.setColors(lightIconColor, darkIconColor);
|
||||
}
|
||||
@@ -251,14 +248,8 @@ public class FloatingRotationButton implements RotationButton {
|
||||
updateDimensionResources();
|
||||
|
||||
if (mIsShowing) {
|
||||
updateIcon(mRotationButtonController.getLightIconColor(),
|
||||
mRotationButtonController.getDarkIconColor());
|
||||
final LayoutParams layoutParams = adjustViewPositionAndCreateLayoutParams();
|
||||
mWindowManager.updateViewLayout(mKeyButtonContainer, layoutParams);
|
||||
if (mAnimatedDrawable != null) {
|
||||
mAnimatedDrawable.reset();
|
||||
mAnimatedDrawable.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-16
@@ -37,7 +37,6 @@ public class FloatingRotationButtonView extends ImageView {
|
||||
private static final float BACKGROUND_ALPHA = 0.92f;
|
||||
|
||||
private KeyButtonRipple mRipple;
|
||||
private int mDiameter;
|
||||
private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
|
||||
|
||||
private final Configuration mLastConfiguration;
|
||||
@@ -94,25 +93,10 @@ public class FloatingRotationButtonView extends ImageView {
|
||||
mRipple.setDarkIntensity(darkIntensity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the view's diameter.
|
||||
*
|
||||
* @param diameter the diameter value for the view
|
||||
*/
|
||||
void setDiameter(int diameter) {
|
||||
mDiameter = diameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
int d = Math.min(getWidth(), getHeight());
|
||||
canvas.drawOval(0, 0, d, d, mOvalBgPaint);
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
setMeasuredDimension(mDiameter, mDiameter);
|
||||
}
|
||||
}
|
||||
|
||||
+25
-15
@@ -53,9 +53,6 @@ import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.UiEvent;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
@@ -145,14 +142,12 @@ public class RotationButtonController {
|
||||
};
|
||||
|
||||
private final IRotationWatcher.Stub mRotationWatcher = new IRotationWatcher.Stub() {
|
||||
@WorkerThread
|
||||
@Override
|
||||
public void onRotationChanged(final int rotation) {
|
||||
@Nullable Boolean rotationLocked = RotationPolicyUtil.isRotationLocked(mContext);
|
||||
// We need this to be scheduled as early as possible to beat the redrawing of
|
||||
// window in response to the orientation change.
|
||||
mMainThreadHandler.postAtFrontOfQueue(() -> {
|
||||
onRotationWatcherChanged(rotation, rotationLocked);
|
||||
onRotationWatcherChanged(rotation);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -286,8 +281,8 @@ public class RotationButtonController {
|
||||
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
|
||||
}
|
||||
|
||||
public void setRotationLockedAtAngle(
|
||||
@Nullable Boolean isLocked, int rotationSuggestion, String caller) {
|
||||
public void setRotationLockedAtAngle(int rotationSuggestion, String caller) {
|
||||
final Boolean isLocked = isRotationLocked();
|
||||
if (isLocked == null) {
|
||||
// Ignore if we can't read the setting for the current user
|
||||
return;
|
||||
@@ -296,6 +291,21 @@ public class RotationButtonController {
|
||||
/* rotation= */ rotationSuggestion, caller);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether rotation is currently locked, or <code>null</code> if the setting couldn't
|
||||
* be read
|
||||
*/
|
||||
public Boolean isRotationLocked() {
|
||||
try {
|
||||
return RotationPolicy.isRotationLocked(mContext);
|
||||
} catch (SecurityException e) {
|
||||
// TODO(b/279561841): RotationPolicy uses the current user to resolve the setting which
|
||||
// may change before the rotation watcher can be unregistered
|
||||
Log.e(TAG, "Failed to get isRotationLocked", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setRotateSuggestionButtonState(boolean visible) {
|
||||
setRotateSuggestionButtonState(visible, false /* force */);
|
||||
}
|
||||
@@ -459,7 +469,7 @@ public class RotationButtonController {
|
||||
* Called when the rotation watcher rotation changes, either from the watcher registered
|
||||
* internally in this class, or a signal propagated from NavBarHelper.
|
||||
*/
|
||||
public void onRotationWatcherChanged(int rotation, @Nullable Boolean isRotationLocked) {
|
||||
public void onRotationWatcherChanged(int rotation) {
|
||||
if (!mListenersRegistered) {
|
||||
// Ignore if not registered
|
||||
return;
|
||||
@@ -467,16 +477,17 @@ public class RotationButtonController {
|
||||
|
||||
// If the screen rotation changes while locked, potentially update lock to flow with
|
||||
// new screen rotation and hide any showing suggestions.
|
||||
if (isRotationLocked == null) {
|
||||
Boolean rotationLocked = isRotationLocked();
|
||||
if (rotationLocked == null) {
|
||||
// Ignore if we can't read the setting for the current user
|
||||
return;
|
||||
}
|
||||
// The isVisible check makes the rotation button disappear when we are not locked
|
||||
// (e.g. for tabletop auto-rotate).
|
||||
if (isRotationLocked || mRotationButton.isVisible()) {
|
||||
if (rotationLocked || mRotationButton.isVisible()) {
|
||||
// Do not allow a change in rotation to set user rotation when docked.
|
||||
if (shouldOverrideUserLockPrefs(rotation) && isRotationLocked && !mDocked) {
|
||||
setRotationLockedAtAngle(true, rotation, /* caller= */
|
||||
if (shouldOverrideUserLockPrefs(rotation) && rotationLocked && !mDocked) {
|
||||
setRotationLockedAtAngle(rotation, /* caller= */
|
||||
"RotationButtonController#onRotationWatcherChanged");
|
||||
}
|
||||
setRotateSuggestionButtonState(false /* visible */, true /* forced */);
|
||||
@@ -581,8 +592,7 @@ public class RotationButtonController {
|
||||
private void onRotateSuggestionClick(View v) {
|
||||
mUiEventLogger.log(RotationButtonEvent.ROTATION_SUGGESTION_ACCEPTED);
|
||||
incrementNumAcceptedRotationSuggestionsIfNeeded();
|
||||
setRotationLockedAtAngle(
|
||||
RotationPolicyUtil.isRotationLocked(mContext), mLastRotationSuggestion,
|
||||
setRotationLockedAtAngle(mLastRotationSuggestion,
|
||||
/* caller= */ "RotationButtonController#onRotateSuggestionClick");
|
||||
Log.i(TAG, "onRotateSuggestionClick() mLastRotationSuggestion=" + mLastRotationSuggestion);
|
||||
v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.android.systemui.shared.shadow
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.TypedArray
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
@@ -32,23 +31,19 @@ constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
defStyleRes: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : TextView(context, attrs, defStyleAttr, defStyleRes) {
|
||||
private lateinit var mKeyShadowInfo: ShadowInfo
|
||||
private lateinit var mAmbientShadowInfo: ShadowInfo
|
||||
private val mKeyShadowInfo: ShadowInfo
|
||||
private val mAmbientShadowInfo: ShadowInfo
|
||||
|
||||
init {
|
||||
updateShadowDrawables(
|
||||
val attributes =
|
||||
context.obtainStyledAttributes(
|
||||
attrs,
|
||||
R.styleable.DoubleShadowTextView,
|
||||
defStyleAttr,
|
||||
defStyleRes,
|
||||
defStyleRes
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateShadowDrawables(attributes: TypedArray) {
|
||||
val drawableSize: Int
|
||||
val drawableInsetSize: Int
|
||||
try {
|
||||
@@ -75,17 +70,17 @@ constructor(
|
||||
ambientShadowBlur,
|
||||
ambientShadowOffsetX,
|
||||
ambientShadowOffsetY,
|
||||
ambientShadowAlpha,
|
||||
ambientShadowAlpha
|
||||
)
|
||||
drawableSize =
|
||||
attributes.getDimensionPixelSize(
|
||||
R.styleable.DoubleShadowTextView_drawableIconSize,
|
||||
0,
|
||||
0
|
||||
)
|
||||
drawableInsetSize =
|
||||
attributes.getDimensionPixelSize(
|
||||
R.styleable.DoubleShadowTextView_drawableIconInsetSize,
|
||||
0,
|
||||
0
|
||||
)
|
||||
} finally {
|
||||
attributes.recycle()
|
||||
@@ -100,19 +95,12 @@ constructor(
|
||||
mAmbientShadowInfo,
|
||||
drawable,
|
||||
drawableSize,
|
||||
drawableInsetSize,
|
||||
drawableInsetSize
|
||||
)
|
||||
}
|
||||
setCompoundDrawablesRelative(drawables[0], drawables[1], drawables[2], drawables[3])
|
||||
}
|
||||
|
||||
override fun setTextAppearance(resId: Int) {
|
||||
super.setTextAppearance(resId)
|
||||
updateShadowDrawables(
|
||||
context.obtainStyledAttributes(resId, R.styleable.DoubleShadowTextView)
|
||||
)
|
||||
}
|
||||
|
||||
public override fun onDraw(canvas: Canvas) {
|
||||
applyShadows(mKeyShadowInfo, mAmbientShadowInfo, this, canvas) { super.onDraw(canvas) }
|
||||
}
|
||||
|
||||
+124
-31
@@ -18,16 +18,13 @@ package com.android.systemui.shared.system;
|
||||
|
||||
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
|
||||
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
|
||||
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
import static app.lawnchair.compat.LawnchairQuickstepCompat.ATLEAST_R;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityClient;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RecentTaskInfo;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.ActivityTaskManager;
|
||||
@@ -41,7 +38,7 @@ import android.content.pm.UserInfo;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.DeadSystemException;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
@@ -49,6 +46,8 @@ import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import com.android.internal.app.IVoiceInteractionManagerService;
|
||||
@@ -59,6 +58,11 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
import app.lawnchair.compatlib.RecentsAnimationRunnerCompat;
|
||||
import app.lawnchair.compatlib.eleven.ActivityManagerCompatVR;
|
||||
|
||||
public class ActivityManagerWrapper {
|
||||
|
||||
@@ -83,17 +87,13 @@ public class ActivityManagerWrapper {
|
||||
/**
|
||||
* @return the current user's id.
|
||||
*/
|
||||
public int getCurrentUserId() throws DeadSystemException {
|
||||
public int getCurrentUserId() {
|
||||
UserInfo ui;
|
||||
try {
|
||||
ui = ActivityManager.getService().getCurrentUser();
|
||||
return ui != null ? ui.id : 0;
|
||||
} catch (RemoteException e) {
|
||||
if (ATLEAST_R) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
} else {
|
||||
throw new DeadSystemException();
|
||||
}
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,14 @@ public class ActivityManagerWrapper {
|
||||
return getRunningTask(false /* filterVisibleRecents */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list of the recents tasks.
|
||||
*/
|
||||
@NonNull
|
||||
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
return LawnchairQuickstepCompat.getActivityManagerCompat().getRecentTasks(numTasks, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the top running task filtering only for tasks that can be visible in the recent tasks
|
||||
* list (can be {@code null}).
|
||||
@@ -212,13 +220,96 @@ public class ActivityManagerWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads the recents activity. The caller should manage the thread on which this is called.
|
||||
* Starts the recents activity. The caller should manage the thread on which this is called.
|
||||
*/
|
||||
public void preloadRecentsActivity(Intent intent) {
|
||||
public void startRecentsActivity(Intent intent, long eventTime,
|
||||
final RecentsAnimationListener animationHandler, final Consumer<Boolean> resultCallback,
|
||||
Handler resultCallbackHandler) {
|
||||
boolean result = startRecentsActivity(intent, eventTime, animationHandler);
|
||||
if (resultCallback != null && resultCallbackHandler != null) {
|
||||
resultCallbackHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resultCallback.accept(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the recents activity. The caller should manage the thread on which this is called.
|
||||
*/
|
||||
public boolean startRecentsActivity(
|
||||
Intent intent, long eventTime, RecentsAnimationListener animationHandler) {
|
||||
try {
|
||||
getService().preloadRecentsActivity(intent);
|
||||
RecentsAnimationRunnerCompat runner = null;
|
||||
if (animationHandler != null) {
|
||||
runner = new RecentsAnimationRunnerCompat() {
|
||||
@Override
|
||||
public void onAnimationStart(IRecentsAnimationController controller,
|
||||
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds) {
|
||||
final RecentsAnimationControllerCompat controllerCompat =
|
||||
new RecentsAnimationControllerCompat(controller);
|
||||
animationHandler.onAnimationStart(controllerCompat, apps,
|
||||
wallpapers, homeContentInsets, minimizedHomeBounds, new Bundle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCanceled(int[] taskIds, TaskSnapshot[] taskSnapshots) {
|
||||
animationHandler.onAnimationCanceled(
|
||||
ThumbnailData.wrap(taskIds, taskSnapshots));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* compat for android 12/11/10
|
||||
*/
|
||||
public void onAnimationCanceled(Object taskSnapshot) {
|
||||
if (LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
animationHandler.onAnimationCanceled(
|
||||
ThumbnailData.wrap(new int[]{0}, new TaskSnapshot[]{(TaskSnapshot) taskSnapshot}));
|
||||
} else if (LawnchairQuickstepCompat.ATLEAST_R) {
|
||||
ActivityManagerCompatVR compat = (ActivityManagerCompatVR) LawnchairQuickstepCompat.getActivityManagerCompat();
|
||||
ActivityManagerCompatVR.ThumbnailData data = compat.convertTaskSnapshotToThumbnailData(taskSnapshot);
|
||||
HashMap<Integer, ThumbnailData> thumbnailDatas = new HashMap<>();
|
||||
if (data != null) {
|
||||
thumbnailDatas.put(0, new ThumbnailData());
|
||||
}
|
||||
animationHandler.onAnimationCanceled(thumbnailDatas);
|
||||
} else {
|
||||
animationHandler.onAnimationCanceled(new HashMap<>());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* compat for android 12/11
|
||||
*/
|
||||
public void onTaskAppeared(RemoteAnimationTarget app) {
|
||||
animationHandler.onTasksAppeared(new RemoteAnimationTarget[]{app});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTasksAppeared(RemoteAnimationTarget[] apps) {
|
||||
animationHandler.onTasksAppeared(apps);
|
||||
}
|
||||
};
|
||||
}
|
||||
LawnchairQuickstepCompat.getActivityManagerCompat().startRecentsActivity(intent, eventTime, runner);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Failed to preload recents activity", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the remote recents animation started from {@link #startRecentsActivity}.
|
||||
*/
|
||||
public void cancelRecentsAnimation(boolean restoreHomeRootTaskPosition) {
|
||||
try {
|
||||
getService().cancelRecentsAnimation(restoreHomeRootTaskPosition);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to cancel recents animation", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,6 +320,24 @@ public class ActivityManagerWrapper {
|
||||
return startActivityFromRecents(taskKey.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Preloads the recents activity. The caller should manage the thread on which this is called.
|
||||
*/
|
||||
public void preloadRecentsActivity(Intent intent) {
|
||||
try {
|
||||
Class<?> activityTaskManagerClass = Class.forName("android.app.ActivityTaskManager");
|
||||
Method getServiceMethod = activityTaskManagerClass.getMethod("getService");
|
||||
Object activityTaskManagerService = getServiceMethod.invoke(null);
|
||||
Method preloadRecentsActivityMethod = activityTaskManagerService.getClass()
|
||||
.getMethod("preloadRecentsActivity", Intent.class);
|
||||
|
||||
preloadRecentsActivityMethod.invoke(activityTaskManagerService, intent);
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed to preload recents activity", e);
|
||||
startRecentsActivity(intent, 0, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a task from Recents synchronously.
|
||||
*/
|
||||
@@ -254,17 +363,6 @@ public class ActivityManagerWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the specified task is perceptible.
|
||||
*/
|
||||
public boolean setTaskIsPerceptible(int taskId, boolean isPerceptible) {
|
||||
try {
|
||||
return getService().setTaskIsPerceptible(taskId, isPerceptible);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a task by id.
|
||||
*/
|
||||
@@ -321,7 +419,7 @@ public class ActivityManagerWrapper {
|
||||
* Shows a voice session identified by {@code token}
|
||||
* @return true if the session was shown, false otherwise
|
||||
*/
|
||||
public boolean showVoiceSession(IBinder token, @NonNull Bundle args, int flags,
|
||||
public boolean showVoiceSession(@NonNull IBinder token, @NonNull Bundle args, int flags,
|
||||
@Nullable String attributionTag) {
|
||||
IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface(
|
||||
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
|
||||
@@ -356,9 +454,4 @@ public class ActivityManagerWrapper {
|
||||
return info.configuration.windowConfiguration.getActivityType()
|
||||
== WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
}
|
||||
|
||||
public boolean isRunningInTestHarness() {
|
||||
return ActivityManager.isRunningInTestHarness()
|
||||
|| ActivityManager.isRunningInUserTestHarness();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
|
||||
import android.app.ActivityManager;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
|
||||
public abstract class BlurUtils {
|
||||
|
||||
/**
|
||||
@@ -29,7 +31,7 @@ public abstract class BlurUtils {
|
||||
* @return {@code true} when supported.
|
||||
*/
|
||||
public static boolean supportsBlursOnWindows() {
|
||||
return CROSS_WINDOW_BLUR_SUPPORTED && ActivityManager.isHighEndGfx()
|
||||
return LawnchairQuickstepCompat.ATLEAST_R && CROSS_WINDOW_BLUR_SUPPORTED && ActivityManager.isHighEndGfx()
|
||||
&& !SystemProperties.getBoolean("persist.sysui.disableBlur", false);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -32,7 +32,7 @@ public final class InteractionJankMonitorWrapper {
|
||||
* @param cujType the specific {@link Cuj.CujType}.
|
||||
*/
|
||||
public static void begin(View v, @Cuj.CujType int cujType) {
|
||||
if (true) return; // LC-Ignored
|
||||
if (true) return;
|
||||
InteractionJankMonitor.getInstance().begin(v, cujType);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public final class InteractionJankMonitorWrapper {
|
||||
* @param timeout duration to cancel the instrumentation in ms
|
||||
*/
|
||||
public static void begin(View v, @Cuj.CujType int cujType, long timeout) {
|
||||
if (true) return; // LC-Ignored
|
||||
if (true) return;
|
||||
Configuration.Builder builder =
|
||||
Configuration.Builder.withView(cujType, v)
|
||||
.setTimeout(timeout);
|
||||
@@ -59,7 +59,7 @@ public final class InteractionJankMonitorWrapper {
|
||||
* @param tag the tag to distinguish different flow of same type CUJ.
|
||||
*/
|
||||
public static void begin(View v, @Cuj.CujType int cujType, String tag) {
|
||||
if (true) return; // LC-Ignored
|
||||
if (true) return;
|
||||
Configuration.Builder builder =
|
||||
Configuration.Builder.withView(cujType, v);
|
||||
if (!TextUtils.isEmpty(tag)) {
|
||||
@@ -74,7 +74,7 @@ public final class InteractionJankMonitorWrapper {
|
||||
* @param cujType the specific {@link Cuj.CujType}.
|
||||
*/
|
||||
public static void end(@Cuj.CujType int cujType) {
|
||||
if (true) return; // LC-Ignored
|
||||
if (true) return;
|
||||
InteractionJankMonitor.getInstance().end(cujType);
|
||||
}
|
||||
|
||||
@@ -82,13 +82,13 @@ public final class InteractionJankMonitorWrapper {
|
||||
* Cancel the trace session.
|
||||
*/
|
||||
public static void cancel(@Cuj.CujType int cujType) {
|
||||
if (true) return; // LC-Ignored
|
||||
if (true) return;
|
||||
InteractionJankMonitor.getInstance().cancel(cujType);
|
||||
}
|
||||
|
||||
/** Return true if currently instrumenting a trace session. */
|
||||
public static boolean isInstrumenting(@Cuj.CujType int cujType) {
|
||||
if (true) return true; // LC-Ignored
|
||||
if (true) return true;
|
||||
return InteractionJankMonitor.getInstance().isInstrumenting(cujType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,17 +25,9 @@ import static com.android.systemui.shared.Flags.shadeAllowBackGesture;
|
||||
import android.annotation.LongDef;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.policy.ScreenDecorationsUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
@@ -49,7 +41,10 @@ import app.lawnchair.compat.LawnchairQuickstepCompat;
|
||||
*/
|
||||
public class QuickStepContract {
|
||||
|
||||
private static final String TAG = "QuickStepContract";
|
||||
public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
|
||||
public static final String KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER = "extra_unfold_animation";
|
||||
// See ISysuiUnlockAnimationController.aidl
|
||||
public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation";
|
||||
|
||||
public static final String NAV_BAR_MODE_3BUTTON_OVERLAY =
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
|
||||
@@ -99,12 +94,12 @@ public class QuickStepContract {
|
||||
public static final long SYSUI_STATE_ONE_HANDED_ACTIVE = 1L << 16;
|
||||
// Allow system gesture no matter the system bar(s) is visible or not
|
||||
public static final long SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1L << 17;
|
||||
// The IME is visible.
|
||||
public static final long SYSUI_STATE_IME_VISIBLE = 1L << 18;
|
||||
// The IME is showing
|
||||
public static final long SYSUI_STATE_IME_SHOWING = 1L << 18;
|
||||
// The window magnification is overlapped with system gesture insets at the bottom.
|
||||
public static final long SYSUI_STATE_MAGNIFICATION_OVERLAP = 1L << 19;
|
||||
// The IME Switcher button is visible.
|
||||
public static final long SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE = 1L << 20;
|
||||
// ImeSwitcher is showing
|
||||
public static final long SYSUI_STATE_IME_SWITCHER_SHOWING = 1L << 20;
|
||||
// Device dozing/AOD state
|
||||
public static final long SYSUI_STATE_DEVICE_DOZING = 1L << 21;
|
||||
// The home feature is disabled (either by SUW/SysUI/device policy)
|
||||
@@ -131,14 +126,6 @@ public class QuickStepContract {
|
||||
public static final long SYSUI_STATE_SHORTCUT_HELPER_SHOWING = 1L << 32;
|
||||
// Touchpad gestures are disabled
|
||||
public static final long SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED = 1L << 33;
|
||||
// PiP animation is running
|
||||
public static final long SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING = 1L << 34;
|
||||
// Communal hub is showing
|
||||
public static final long SYSUI_STATE_COMMUNAL_HUB_SHOWING = 1L << 35;
|
||||
// The back button is visually adjusted to indicate that it will dismiss the IME when pressed.
|
||||
// This only takes effect while the IME is visible. By default, it is set while the IME is
|
||||
// visible, but may be overridden by the backDispositionMode set by the IME.
|
||||
public static final long SYSUI_STATE_BACK_DISMISS_IME = 1L << 36;
|
||||
|
||||
// Mask for SystemUiStateFlags to isolate SYSUI_STATE_AWAKE and
|
||||
// SYSUI_STATE_WAKEFULNESS_TRANSITION, to match WAKEFULNESS_* constants
|
||||
@@ -152,7 +139,7 @@ public class QuickStepContract {
|
||||
SYSUI_STATE_WAKEFULNESS_TRANSITION | SYSUI_STATE_AWAKE;
|
||||
|
||||
// Whether the back gesture is allowed (or ignored) by the Shade
|
||||
public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = shadeAllowBackGesture();
|
||||
public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = false;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@LongDef({SYSUI_STATE_SCREEN_PINNING,
|
||||
@@ -173,9 +160,9 @@ public class QuickStepContract {
|
||||
SYSUI_STATE_DIALOG_SHOWING,
|
||||
SYSUI_STATE_ONE_HANDED_ACTIVE,
|
||||
SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
|
||||
SYSUI_STATE_IME_VISIBLE,
|
||||
SYSUI_STATE_IME_SHOWING,
|
||||
SYSUI_STATE_MAGNIFICATION_OVERLAP,
|
||||
SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE,
|
||||
SYSUI_STATE_IME_SWITCHER_SHOWING,
|
||||
SYSUI_STATE_DEVICE_DOZING,
|
||||
SYSUI_STATE_BACK_DISABLED,
|
||||
SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED,
|
||||
@@ -188,9 +175,6 @@ public class QuickStepContract {
|
||||
SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY,
|
||||
SYSUI_STATE_SHORTCUT_HELPER_SHOWING,
|
||||
SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED,
|
||||
SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING,
|
||||
SYSUI_STATE_COMMUNAL_HUB_SHOWING,
|
||||
SYSUI_STATE_BACK_DISMISS_IME,
|
||||
})
|
||||
public @interface SystemUiStateFlags {}
|
||||
|
||||
@@ -250,14 +234,14 @@ public class QuickStepContract {
|
||||
if ((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
|
||||
str.add("allow_gesture");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_IME_VISIBLE) != 0) {
|
||||
if ((flags & SYSUI_STATE_IME_SHOWING) != 0) {
|
||||
str.add("ime_visible");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0) {
|
||||
str.add("magnification_overlap");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_IME_SWITCHER_BUTTON_VISIBLE) != 0) {
|
||||
str.add("ime_switcher_button_visible");
|
||||
if ((flags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0) {
|
||||
str.add("ime_switcher_showing");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_DEVICE_DOZING) != 0) {
|
||||
str.add("device_dozing");
|
||||
@@ -295,15 +279,6 @@ public class QuickStepContract {
|
||||
if ((flags & SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED) != 0) {
|
||||
str.add("touchpad_gestures_disabled");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_DISABLE_GESTURE_PIP_ANIMATING) != 0) {
|
||||
str.add("disable_gesture_pip_animating");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) {
|
||||
str.add("communal_hub_showing");
|
||||
}
|
||||
if ((flags & SYSUI_STATE_BACK_DISMISS_IME) != 0) {
|
||||
str.add("back_dismiss_ime");
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
@@ -360,15 +335,6 @@ public class QuickStepContract {
|
||||
|| (sysuiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) {
|
||||
return false;
|
||||
}
|
||||
// Disable back gesture on the hub, but not when the shade is showing.
|
||||
if ((sysuiStateFlags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) {
|
||||
// Use QS expanded signal as the notification panel is always considered visible
|
||||
// expanded when on the lock screen and when opening hub over lock screen. This does
|
||||
// mean that back gesture is disabled when opening shade over hub while in portrait
|
||||
// mode, since QS is not expanded.
|
||||
// TODO(b/370108274): allow back gesture on shade over hub in portrait
|
||||
return (sysuiStateFlags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) == 0;
|
||||
}
|
||||
if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
|
||||
sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
|
||||
}
|
||||
@@ -412,18 +378,21 @@ public class QuickStepContract {
|
||||
return mode == NAV_BAR_MODE_3BUTTON;
|
||||
}
|
||||
|
||||
// LC-specific
|
||||
public static boolean sRecentsDisabled = false;
|
||||
public static boolean sHasCustomCornerRadius = false;
|
||||
public static float sCustomCornerRadius = 0f;
|
||||
|
||||
/**
|
||||
* Corner radius that should be used on windows in order to cover the display.
|
||||
* These values are expressed in pixels because they should not respect display or font
|
||||
* scaling. The corner radius may change when folding/unfolding the device.
|
||||
*/
|
||||
public static boolean sRecentsDisabled = false;
|
||||
public static boolean sHasCustomCornerRadius = false;
|
||||
public static float sCustomCornerRadius = 0f;
|
||||
|
||||
/**
|
||||
* Corner radius that should be used on windows in order to cover the display.
|
||||
* These values are expressed in pixels because they should not respect display or font
|
||||
* scaling, this means that we don't have to reload them on config changes.
|
||||
*/
|
||||
public static float getWindowCornerRadius(Context context) {
|
||||
// LC-Wrapped
|
||||
if (sRecentsDisabled || !LawnchairQuickstepCompat.ATLEAST_S) {
|
||||
return 0;
|
||||
}
|
||||
@@ -441,27 +410,11 @@ public class QuickStepContract {
|
||||
* If live rounded corners are supported on windows.
|
||||
*/
|
||||
public static boolean supportsRoundedCornersOnWindows(Resources resources) {
|
||||
// LC-Wrapped
|
||||
try {
|
||||
return ScreenDecorationsUtils.supportsRoundedCornersOnWindows(resources);
|
||||
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the provided interface to the bundle using the interface descriptor as the key
|
||||
*/
|
||||
public static void addInterface(@Nullable IInterface iInterface, @NonNull Bundle out) {
|
||||
if (iInterface != null) {
|
||||
IBinder binder = iInterface.asBinder();
|
||||
if (binder != null) {
|
||||
try {
|
||||
out.putIBinder(binder.getInterfaceDescriptor(), binder);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Invalid interface description " + binder, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+55
-7
@@ -19,13 +19,13 @@ package com.android.systemui.shared.system;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.PictureInPictureSurfaceTransaction;
|
||||
import android.window.WindowAnimationState;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import com.android.internal.os.IResultReceiver;
|
||||
import com.android.wm.shell.recents.IRecentsAnimationController;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -41,6 +41,18 @@ public class RecentsAnimationControllerCompat {
|
||||
mAnimationController = animationController;
|
||||
}
|
||||
|
||||
public ThumbnailData screenshotTask(int taskId) {
|
||||
try {
|
||||
final TaskSnapshot snapshot = mAnimationController.screenshotTask(taskId);
|
||||
if (snapshot != null) {
|
||||
return ThumbnailData.fromSnapshot(snapshot);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to screenshot task", e);
|
||||
}
|
||||
return new ThumbnailData();
|
||||
}
|
||||
|
||||
public void setInputConsumerEnabled(boolean enabled) {
|
||||
try {
|
||||
mAnimationController.setInputConsumerEnabled(enabled);
|
||||
@@ -49,6 +61,14 @@ public class RecentsAnimationControllerCompat {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
|
||||
try {
|
||||
mAnimationController.setAnimationTargetsBehindSystemBars(behindSystemBars);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to set whether animation targets are behind system bars", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the final surface transaction on a Task. This is used by Launcher to notify the system
|
||||
* that animating Activity to PiP has completed and the associated task surface should be
|
||||
@@ -103,6 +123,22 @@ public class RecentsAnimationControllerCompat {
|
||||
}
|
||||
}
|
||||
|
||||
public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
|
||||
try {
|
||||
mAnimationController.setDeferCancelUntilNextTransition(defer, screenshot);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to set deferred cancel with screenshot", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanupScreenshot() {
|
||||
try {
|
||||
mAnimationController.cleanupScreenshot();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to clean up screenshot of recents animation", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see {{@link IRecentsAnimationController#setWillFinishToHome(boolean)}}.
|
||||
*/
|
||||
@@ -115,13 +151,14 @@ public class RecentsAnimationControllerCompat {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IRecentsAnimationController#handOffAnimation
|
||||
* @see IRecentsAnimationController#removeTask
|
||||
*/
|
||||
public void handOffAnimation(RemoteAnimationTarget[] targets, WindowAnimationState[] states) {
|
||||
public boolean removeTask(int taskId) {
|
||||
try {
|
||||
mAnimationController.handOffAnimation(targets, states);
|
||||
return mAnimationController.removeTask(taskId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to hand off animation", e);
|
||||
Log.e(TAG, "Failed to remove remote animation target", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,4 +172,15 @@ public class RecentsAnimationControllerCompat {
|
||||
Log.e(TAG, "Failed to detach the navigation bar from app", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IRecentsAnimationController#animateNavigationBarToApp(long)
|
||||
*/
|
||||
public void animateNavigationBarToApp(long duration) {
|
||||
try {
|
||||
mAnimationController.animateNavigationBarToApp(duration);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to animate the navigation bar to app", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+19
-3
@@ -16,10 +16,10 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -32,7 +32,13 @@ public interface RecentsAnimationListener {
|
||||
*/
|
||||
void onAnimationStart(RecentsAnimationControllerCompat controller,
|
||||
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras, TransitionInfo info);
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras);
|
||||
|
||||
// Introduced in NothingOS 2.5.5, needed in 2.6
|
||||
void onAnimationStart(RecentsAnimationControllerCompat controller,
|
||||
TransitionInfo transitionInfo, SurfaceControl.Transaction transaction,
|
||||
RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds);
|
||||
|
||||
/**
|
||||
* Called when the animation into Recents was canceled. This call is made on the binder thread.
|
||||
@@ -43,5 +49,15 @@ public interface RecentsAnimationListener {
|
||||
* Called when the task of an activity that has been started while the recents animation
|
||||
* was running becomes ready for control.
|
||||
*/
|
||||
void onTasksAppeared(RemoteAnimationTarget[] app, @Nullable TransitionInfo transitionInfo);
|
||||
void onTasksAppeared(RemoteAnimationTarget[] app);
|
||||
|
||||
/**
|
||||
* Called to request that the current task tile be switched out for a screenshot (if not
|
||||
* already). Once complete, onFinished should be called.
|
||||
* @return true if this impl will call onFinished. No other onSwitchToScreenshot impls will
|
||||
* be called afterwards (to avoid multiple calls to onFinished).
|
||||
*/
|
||||
default boolean onSwitchToScreenshot(Runnable onFinished) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -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,9 +169,10 @@ public class TaskStackChangeListeners {
|
||||
if (!mRegistered) {
|
||||
// Register mTaskStackListener to IActivityManager only once if needed.
|
||||
try {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
|
||||
ActivityTaskManager.getService().registerTaskStackListener(this);
|
||||
mRegistered = true;
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed to call registerTaskStackListener", e);
|
||||
}
|
||||
}
|
||||
@@ -184,9 +187,10 @@ public class TaskStackChangeListeners {
|
||||
if (isEmpty && mRegistered) {
|
||||
// Unregister mTaskStackListener once we have no more listeners
|
||||
try {
|
||||
if (!LawnchairQuickstepCompat.ATLEAST_V) return;
|
||||
ActivityTaskManager.getService().unregisterTaskStackListener(this);
|
||||
mRegistered = false;
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed to call unregisterTaskStackListener", e);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -28,7 +28,14 @@ class UncaughtExceptionPreHandlerManager @Inject constructor() {
|
||||
* Verifies that the global handler is set in Thread. If not, sets is up.
|
||||
*/
|
||||
private fun checkGlobalHandlerSetup() {
|
||||
// LC-Ignored
|
||||
val currentHandler = Thread.getDefaultUncaughtExceptionHandler()
|
||||
if (currentHandler != globalUncaughtExceptionPreHandler) {
|
||||
if (currentHandler is GlobalUncaughtExceptionHandler) {
|
||||
throw IllegalStateException("Two UncaughtExceptionPreHandlerManagers created")
|
||||
}
|
||||
currentHandler?.let { addHandler(it) }
|
||||
Thread.setDefaultUncaughtExceptionHandler(globalUncaughtExceptionPreHandler)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,4 +68,4 @@ class UncaughtExceptionPreHandlerManager @Inject constructor() {
|
||||
handleUncaughtException(thread, throwable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user