Update SystemUIShared
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
compileSdkVersion COMPILE_SDK
|
||||
@@ -28,6 +29,10 @@ android {
|
||||
options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
@@ -37,5 +42,5 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.pip;
|
||||
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.view.Choreographer;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.PictureInPictureSurfaceTransaction;
|
||||
|
||||
/**
|
||||
* TODO(b/171721389): unify this class with
|
||||
* {@link com.android.wm.shell.pip.PipSurfaceTransactionHelper}, for instance, there should be one
|
||||
* source of truth on enabling/disabling and the actual value of corner radius.
|
||||
*/
|
||||
public class PipSurfaceTransactionHelper {
|
||||
private final int mCornerRadius;
|
||||
private final Matrix mTmpTransform = new Matrix();
|
||||
private final float[] mTmpFloat9 = new float[9];
|
||||
private final RectF mTmpSourceRectF = new RectF();
|
||||
private final RectF mTmpDestinationRectF = new RectF();
|
||||
private final Rect mTmpDestinationRect = new Rect();
|
||||
|
||||
public PipSurfaceTransactionHelper(int cornerRadius) {
|
||||
mCornerRadius = cornerRadius;
|
||||
}
|
||||
|
||||
public PictureInPictureSurfaceTransaction scale(
|
||||
SurfaceControl.Transaction tx, SurfaceControl leash,
|
||||
Rect sourceBounds, Rect destinationBounds) {
|
||||
float positionX = destinationBounds.left;
|
||||
float positionY = destinationBounds.top;
|
||||
mTmpSourceRectF.set(sourceBounds);
|
||||
mTmpDestinationRectF.set(destinationBounds);
|
||||
mTmpDestinationRectF.offsetTo(0, 0);
|
||||
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
|
||||
final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
|
||||
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
|
||||
.setPosition(leash, positionX, positionY)
|
||||
.setCornerRadius(leash, cornerRadius);
|
||||
return new PictureInPictureSurfaceTransaction(
|
||||
positionX, positionY, mTmpFloat9, 0 /* rotation */, cornerRadius, sourceBounds);
|
||||
}
|
||||
|
||||
public PictureInPictureSurfaceTransaction scale(
|
||||
SurfaceControl.Transaction tx, SurfaceControl leash,
|
||||
Rect sourceBounds, Rect destinationBounds,
|
||||
float degree, float positionX, float positionY) {
|
||||
mTmpSourceRectF.set(sourceBounds);
|
||||
mTmpDestinationRectF.set(destinationBounds);
|
||||
mTmpDestinationRectF.offsetTo(0, 0);
|
||||
mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
|
||||
mTmpTransform.postRotate(degree, 0, 0);
|
||||
final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
|
||||
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
|
||||
.setPosition(leash, positionX, positionY)
|
||||
.setCornerRadius(leash, cornerRadius);
|
||||
return new PictureInPictureSurfaceTransaction(
|
||||
positionX, positionY, mTmpFloat9, degree, cornerRadius, sourceBounds);
|
||||
}
|
||||
|
||||
public PictureInPictureSurfaceTransaction scaleAndCrop(
|
||||
SurfaceControl.Transaction tx, SurfaceControl leash,
|
||||
Rect sourceBounds, Rect destinationBounds, Rect insets) {
|
||||
mTmpSourceRectF.set(sourceBounds);
|
||||
mTmpDestinationRect.set(sourceBounds);
|
||||
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 = sourceBounds.width() <= sourceBounds.height()
|
||||
? (float) destinationBounds.width() / sourceBounds.width()
|
||||
: (float) destinationBounds.height() / sourceBounds.height();
|
||||
final float left = destinationBounds.left - (insets.left + sourceBounds.left) * scale;
|
||||
final float top = destinationBounds.top - (insets.top + sourceBounds.top) * scale;
|
||||
mTmpTransform.setScale(scale, scale);
|
||||
final float cornerRadius = getScaledCornerRadius(mTmpDestinationRect, destinationBounds);
|
||||
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
|
||||
.setWindowCrop(leash, mTmpDestinationRect)
|
||||
.setPosition(leash, left, top)
|
||||
.setCornerRadius(leash, cornerRadius);
|
||||
return new PictureInPictureSurfaceTransaction(
|
||||
left, top, mTmpFloat9, 0 /* rotation */, cornerRadius, mTmpDestinationRect);
|
||||
}
|
||||
|
||||
public PictureInPictureSurfaceTransaction scaleAndRotate(
|
||||
SurfaceControl.Transaction tx, SurfaceControl leash,
|
||||
Rect sourceBounds, Rect destinationBounds, Rect insets,
|
||||
float degree, float positionX, float positionY) {
|
||||
mTmpSourceRectF.set(sourceBounds);
|
||||
mTmpDestinationRect.set(sourceBounds);
|
||||
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 = 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) {
|
||||
adjustedPositionX = positionX + insets.top * scale;
|
||||
adjustedPositionY = positionY + insets.left * scale;
|
||||
} else {
|
||||
adjustedPositionX = positionX - insets.top * scale;
|
||||
adjustedPositionY = positionY - insets.left * scale;
|
||||
}
|
||||
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
|
||||
.setWindowCrop(leash, mTmpDestinationRect)
|
||||
.setPosition(leash, adjustedPositionX, adjustedPositionY)
|
||||
.setCornerRadius(leash, cornerRadius);
|
||||
return new PictureInPictureSurfaceTransaction(
|
||||
adjustedPositionX, adjustedPositionY,
|
||||
mTmpFloat9, degree, cornerRadius, mTmpDestinationRect);
|
||||
}
|
||||
|
||||
/** @return the round corner radius scaled by given from and to bounds */
|
||||
private float getScaledCornerRadius(Rect fromBounds, Rect toBounds) {
|
||||
final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
|
||||
/ Math.hypot(toBounds.width(), toBounds.height()));
|
||||
return mCornerRadius * scale;
|
||||
}
|
||||
|
||||
/** @return {@link SurfaceControl.Transaction} instance with vsync-id */
|
||||
public static SurfaceControl.Transaction newSurfaceControlTransaction() {
|
||||
final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
|
||||
tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
|
||||
return tx;
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,9 @@ public interface PluginEnabler {
|
||||
|
||||
int ENABLED = 0;
|
||||
int DISABLED_MANUALLY = 1;
|
||||
int DISABLED_INVALID_VERSION = 1;
|
||||
int DISABLED_FROM_EXPLICIT_CRASH = 2;
|
||||
int DISABLED_FROM_SYSTEM_CRASH = 3;
|
||||
int DISABLED_INVALID_VERSION = 2;
|
||||
int DISABLED_FROM_EXPLICIT_CRASH = 3;
|
||||
int DISABLED_FROM_SYSTEM_CRASH = 4;
|
||||
|
||||
@IntDef({ENABLED, DISABLED_MANUALLY, DISABLED_INVALID_VERSION, DISABLED_FROM_EXPLICIT_CRASH,
|
||||
DISABLED_FROM_SYSTEM_CRASH})
|
||||
|
||||
@@ -37,4 +37,9 @@ public interface PluginInitializer {
|
||||
* Called from {@link PluginManagerImpl#handleWtfs()}.
|
||||
*/
|
||||
void handleWtfs();
|
||||
|
||||
/**
|
||||
* Returns if pluging manager should run in debug mode.
|
||||
*/
|
||||
boolean isDebuggable();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
@@ -72,7 +71,7 @@ public class PluginInstanceManager<T extends Plugin> {
|
||||
PluginInstanceManager(Context context, String action, PluginListener<T> listener,
|
||||
boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager) {
|
||||
this(context, context.getPackageManager(), action, listener, allowMultiple, looper, version,
|
||||
manager, Build.IS_DEBUGGABLE, manager.getWhitelistedPlugins());
|
||||
manager, manager.isDebuggable(), manager.getWhitelistedPlugins());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -386,7 +385,8 @@ public class PluginInstanceManager<T extends Plugin> {
|
||||
}
|
||||
Intent i = new Intent(PluginManagerImpl.DISABLE_PLUGIN).setData(
|
||||
Uri.parse("package://" + component.flattenToString()));
|
||||
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
|
||||
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i,
|
||||
PendingIntent.FLAG_IMMUTABLE);
|
||||
nb.addAction(new Action.Builder(null, "Disable plugin", pi).build());
|
||||
mContext.getSystemService(NotificationManager.class)
|
||||
.notify(SystemMessage.NOTE_PLUGIN, nb.build());
|
||||
|
||||
@@ -66,8 +66,6 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
private static final String TAG = PluginManagerImpl.class.getSimpleName();
|
||||
static final String DISABLE_PLUGIN = "com.android.systemui.action.DISABLE_PLUGIN";
|
||||
|
||||
private static PluginManager sInstance;
|
||||
|
||||
private final ArrayMap<PluginListener<?>, PluginInstanceManager> mPluginMap
|
||||
= new ArrayMap<>();
|
||||
private final Map<String, ClassLoader> mClassLoaders = new ArrayMap<>();
|
||||
@@ -75,7 +73,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
private final ArraySet<String> mWhitelistedPlugins = new ArraySet<>();
|
||||
private final Context mContext;
|
||||
private final PluginInstanceManagerFactory mFactory;
|
||||
private final boolean isDebuggable;
|
||||
private final boolean mIsDebuggable;
|
||||
private final PluginPrefs mPluginPrefs;
|
||||
private final PluginEnabler mPluginEnabler;
|
||||
private final PluginInitializer mPluginInitializer;
|
||||
@@ -85,7 +83,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
private Looper mLooper;
|
||||
|
||||
public PluginManagerImpl(Context context, PluginInitializer initializer) {
|
||||
this(context, new PluginInstanceManagerFactory(), Build.IS_DEBUGGABLE,
|
||||
this(context, new PluginInstanceManagerFactory(), initializer.isDebuggable(),
|
||||
(UncaughtExceptionHandler) invoke(sGetUncaughtExceptionPreHandler, null), initializer);
|
||||
}
|
||||
|
||||
@@ -95,7 +93,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
mContext = context;
|
||||
mFactory = factory;
|
||||
mLooper = initializer.getBgLooper();
|
||||
isDebuggable = debuggable;
|
||||
mIsDebuggable = debuggable;
|
||||
mWhitelistedPlugins.addAll(Arrays.asList(initializer.getWhitelistedPlugins(mContext)));
|
||||
mPluginPrefs = new PluginPrefs(mContext);
|
||||
mPluginEnabler = initializer.getPluginEnabler(mContext);
|
||||
@@ -113,6 +111,10 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
});
|
||||
}
|
||||
|
||||
public boolean isDebuggable() {
|
||||
return mIsDebuggable;
|
||||
}
|
||||
|
||||
public String[] getWhitelistedPlugins() {
|
||||
return mWhitelistedPlugins.toArray(new String[0]);
|
||||
}
|
||||
@@ -197,10 +199,12 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addDataScheme("package");
|
||||
mContext.registerReceiver(this, filter);
|
||||
filter.addAction(PLUGIN_CHANGED);
|
||||
filter.addAction(DISABLE_PLUGIN);
|
||||
filter.addDataScheme("package");
|
||||
mContext.registerReceiver(this, filter);
|
||||
mContext.registerReceiver(this, filter, PluginInstanceManager.PLUGIN_PERMISSION, null);
|
||||
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
|
||||
mContext.registerReceiver(this, filter);
|
||||
}
|
||||
@@ -259,7 +263,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
.setContentText("Restart SysUI for changes to take effect.");
|
||||
Intent i = new Intent("com.android.systemui.action.RESTART").setData(
|
||||
Uri.parse("package://" + pkg));
|
||||
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, 0);
|
||||
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_MUTABLE_UNAUDITED);
|
||||
nb.addAction(new Action.Builder(null, "Restart SysUI", pi).build());
|
||||
mContext.getSystemService(NotificationManager.class)
|
||||
.notify(SystemMessage.NOTE_PLUGIN, nb.build());
|
||||
@@ -299,7 +303,7 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
|
||||
|
||||
/** Returns class loader specific for the given plugin. */
|
||||
public ClassLoader getClassLoader(ApplicationInfo appInfo) {
|
||||
if (!isDebuggable && !isPluginPackageWhitelisted(appInfo.packageName)) {
|
||||
if (!mIsDebuggable && !isPluginPackageWhitelisted(appInfo.packageName)) {
|
||||
Log.w(TAG, "Cannot get class loader for non-whitelisted plugin. Src:"
|
||||
+ appInfo.sourceDir + ", pkg: " + appInfo.packageName);
|
||||
return null;
|
||||
|
||||
@@ -75,4 +75,10 @@ oneway interface IOverviewProxy {
|
||||
* Sent when the split screen is resized
|
||||
*/
|
||||
void onSplitScreenSecondaryBoundsChanged(in Rect bounds, in Rect insets) = 17;
|
||||
|
||||
/**
|
||||
* Sent IME status changes
|
||||
*/
|
||||
void onImeWindowStatusChanged(int displayId, IBinder token, int vis, int backDisposition,
|
||||
boolean showImeSwitcher) = 18;
|
||||
}
|
||||
|
||||
@@ -20,34 +20,22 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.RemoteTransitionCompat;
|
||||
|
||||
/**
|
||||
* Temporary callbacks into SystemUI.
|
||||
* Next id = 27
|
||||
*/
|
||||
interface ISystemUiProxy {
|
||||
|
||||
/**
|
||||
* Proxies SurfaceControl.screenshotToBuffer().
|
||||
* @Removed
|
||||
* GraphicBufferCompat screenshot(in Rect sourceCrop, int width, int height, int minLayer,
|
||||
* int maxLayer, boolean useIdentityTransform, int rotation) = 0;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Begins screen pinning on the provided {@param taskId}.
|
||||
*/
|
||||
void startScreenPinning(int taskId) = 1;
|
||||
|
||||
/**
|
||||
* Notifies SystemUI that split screen has been invoked.
|
||||
*/
|
||||
void onSplitScreenInvoked() = 5;
|
||||
|
||||
/**
|
||||
* Notifies SystemUI that Overview is shown.
|
||||
*/
|
||||
@@ -58,16 +46,10 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
Rect getNonMinimizedSplitScreenSecondaryBounds() = 7;
|
||||
|
||||
/**
|
||||
* Control the {@param alpha} of the back button in the navigation bar and {@param animate} if
|
||||
* needed from current value
|
||||
* @deprecated
|
||||
*/
|
||||
void setBackButtonAlpha(float alpha, boolean animate) = 8;
|
||||
|
||||
/**
|
||||
* Control the {@param alpha} of the option nav bar button (back-button in 2 button mode
|
||||
* and home bar in no-button mode) and {@param animate} if needed from current value
|
||||
* and home handle & background in gestural mode). The {@param animate} is currently only
|
||||
* supported for 2 button mode.
|
||||
*/
|
||||
void setNavBarButtonAlpha(float alpha, boolean animate) = 19;
|
||||
|
||||
@@ -96,11 +78,6 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
void startAssistant(in Bundle bundle) = 13;
|
||||
|
||||
/**
|
||||
* Creates a new gesture monitor
|
||||
*/
|
||||
Bundle monitorGestureInput(String name, int displayId) = 14;
|
||||
|
||||
/**
|
||||
* Notifies that the accessibility button in the system's navigation area has been clicked
|
||||
*/
|
||||
@@ -116,11 +93,6 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
void stopScreenPinning() = 17;
|
||||
|
||||
/**
|
||||
* Sets the shelf height and visibility.
|
||||
*/
|
||||
void setShelfHeight(boolean visible, int shelfHeight) = 20;
|
||||
|
||||
/**
|
||||
* Handle the provided image as if it was a screenshot.
|
||||
*
|
||||
@@ -140,20 +112,33 @@ interface ISystemUiProxy {
|
||||
*/
|
||||
void notifySwipeToHomeFinished() = 23;
|
||||
|
||||
/**
|
||||
* Sets listener to get pinned stack animation callbacks.
|
||||
*/
|
||||
void setPinnedStackAnimationListener(IPinnedStackAnimationListener listener) = 24;
|
||||
|
||||
/**
|
||||
* Notifies that quickstep will switch to a new task
|
||||
* @param rotation indicates which Surface.Rotation the gesture was started in
|
||||
*/
|
||||
void onQuickSwitchToNewTask(int rotation) = 25;
|
||||
void notifyPrioritizedRotation(int rotation) = 25;
|
||||
|
||||
/**
|
||||
* Handle the provided image as if it was a screenshot.
|
||||
*/
|
||||
void handleImageBundleAsScreenshot(in Bundle screenImageBundle, in Rect locationInScreen,
|
||||
in Insets visibleInsets, in Task.TaskKey task) = 26;
|
||||
in Insets visibleInsets, in Task.TaskKey task) = 28;
|
||||
|
||||
/**
|
||||
* Notifies to expand notification panel.
|
||||
*/
|
||||
void expandNotificationPanel() = 29;
|
||||
|
||||
/**
|
||||
* Notifies SystemUI to invoke Back.
|
||||
*/
|
||||
void onBackPressed() = 44;
|
||||
|
||||
/** Sets home rotation enabled. */
|
||||
void setHomeRotationEnabled(boolean enabled) = 45;
|
||||
|
||||
/** Notifies that a swipe-up gesture has started */
|
||||
oneway void notifySwipeUpGestureStarted() = 46;
|
||||
|
||||
// Next id = 47
|
||||
}
|
||||
|
||||
@@ -43,17 +43,6 @@ public class Task {
|
||||
|
||||
public static final String TAG = "Task";
|
||||
|
||||
/* Task callbacks */
|
||||
@Deprecated
|
||||
public interface TaskCallbacks {
|
||||
/* Notifies when a task has been bound */
|
||||
void onTaskDataLoaded(Task task, ThumbnailData thumbnailData);
|
||||
/* Notifies when a task has been unbound */
|
||||
void onTaskDataUnloaded();
|
||||
/* Notifies when a task's windowing mode has changed. */
|
||||
void onTaskWindowingModeChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Task Key represents the unique primary key for the task
|
||||
*/
|
||||
@@ -208,12 +197,6 @@ public class Task {
|
||||
@ViewDebug.ExportedProperty(deepExport=true, prefix="key_")
|
||||
public TaskKey key;
|
||||
|
||||
/**
|
||||
* The temporary sort index in the stack, used when ordering the stack.
|
||||
*/
|
||||
@Deprecated
|
||||
public int temporarySortIndexInStack;
|
||||
|
||||
/**
|
||||
* The icon is the task description icon (if provided), which falls back to the activity icon,
|
||||
* which can then fall back to the application icon.
|
||||
@@ -229,45 +212,24 @@ public class Task {
|
||||
public int colorPrimary;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public int colorBackground;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean useLightOnPrimaryColor;
|
||||
|
||||
/**
|
||||
* The task description for this task, only used to reload task icons.
|
||||
*/
|
||||
public TaskDescription taskDescription;
|
||||
|
||||
/**
|
||||
* The state isLaunchTarget will be set for the correct task upon launching Recents.
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean isLaunchTarget;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean isStackTask;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public boolean isSystemApp;
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public boolean isDockable;
|
||||
|
||||
/**
|
||||
* Resize mode. See {@link ActivityInfo#resizeMode}.
|
||||
*/
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
@Deprecated
|
||||
public int resizeMode;
|
||||
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public ComponentName topActivity;
|
||||
|
||||
@ViewDebug.ExportedProperty(category="recents")
|
||||
public boolean isLocked;
|
||||
|
||||
@Deprecated
|
||||
private ArrayList<TaskCallbacks> mCallbacks = new ArrayList<>();
|
||||
// Last snapshot data, only used for recent tasks
|
||||
public ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData lastSnapshotData =
|
||||
new ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData();
|
||||
|
||||
public Task() {
|
||||
// Do nothing
|
||||
@@ -289,6 +251,16 @@ public class Task {
|
||||
this.taskDescription = new TaskDescription();
|
||||
}
|
||||
|
||||
public Task(Task other) {
|
||||
this(other.key, other.colorPrimary, other.colorBackground, other.isDockable,
|
||||
other.isLocked, other.taskDescription, other.topActivity);
|
||||
lastSnapshotData.set(other.lastSnapshotData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use {@link Task#Task(Task)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Task(TaskKey key, int colorPrimary, int colorBackground,
|
||||
boolean isDockable, boolean isLocked, TaskDescription taskDescription,
|
||||
ComponentName topActivity) {
|
||||
@@ -301,103 +273,6 @@ public class Task {
|
||||
this.topActivity = topActivity;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Task(TaskKey key, Drawable icon, ThumbnailData thumbnail, String title,
|
||||
String titleDescription, int colorPrimary, int colorBackground, boolean isLaunchTarget,
|
||||
boolean isStackTask, boolean isSystemApp, boolean isDockable,
|
||||
TaskDescription taskDescription, int resizeMode, ComponentName topActivity,
|
||||
boolean isLocked) {
|
||||
this.key = key;
|
||||
this.icon = icon;
|
||||
this.thumbnail = thumbnail;
|
||||
this.title = title;
|
||||
this.titleDescription = titleDescription;
|
||||
this.colorPrimary = colorPrimary;
|
||||
this.colorBackground = colorBackground;
|
||||
this.useLightOnPrimaryColor = Utilities.computeContrastBetweenColors(this.colorPrimary,
|
||||
Color.WHITE) > 3f;
|
||||
this.taskDescription = taskDescription;
|
||||
this.isLaunchTarget = isLaunchTarget;
|
||||
this.isStackTask = isStackTask;
|
||||
this.isSystemApp = isSystemApp;
|
||||
this.isDockable = isDockable;
|
||||
this.resizeMode = resizeMode;
|
||||
this.topActivity = topActivity;
|
||||
this.isLocked = isLocked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the metadata from another task, but retains the current callbacks.
|
||||
*/
|
||||
@Deprecated
|
||||
public void copyFrom(Task o) {
|
||||
this.key = o.key;
|
||||
this.icon = o.icon;
|
||||
this.thumbnail = o.thumbnail;
|
||||
this.title = o.title;
|
||||
this.titleDescription = o.titleDescription;
|
||||
this.colorPrimary = o.colorPrimary;
|
||||
this.colorBackground = o.colorBackground;
|
||||
this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
|
||||
this.taskDescription = o.taskDescription;
|
||||
this.isLaunchTarget = o.isLaunchTarget;
|
||||
this.isStackTask = o.isStackTask;
|
||||
this.isSystemApp = o.isSystemApp;
|
||||
this.isDockable = o.isDockable;
|
||||
this.resizeMode = o.resizeMode;
|
||||
this.isLocked = o.isLocked;
|
||||
this.topActivity = o.topActivity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback.
|
||||
*/
|
||||
@Deprecated
|
||||
public void addCallback(TaskCallbacks cb) {
|
||||
if (!mCallbacks.contains(cb)) {
|
||||
mCallbacks.add(cb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a callback.
|
||||
*/
|
||||
@Deprecated
|
||||
public void removeCallback(TaskCallbacks cb) {
|
||||
mCallbacks.remove(cb);
|
||||
}
|
||||
|
||||
/** Updates the task's windowing mode. */
|
||||
@Deprecated
|
||||
public void setWindowingMode(int windowingMode) {
|
||||
key.setWindowingMode(windowingMode);
|
||||
int callbackCount = mCallbacks.size();
|
||||
for (int i = 0; i < callbackCount; i++) {
|
||||
mCallbacks.get(i).onTaskWindowingModeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/** Notifies the callback listeners that this task has been loaded */
|
||||
@Deprecated
|
||||
public void notifyTaskDataLoaded(ThumbnailData thumbnailData, Drawable applicationIcon) {
|
||||
this.icon = applicationIcon;
|
||||
this.thumbnail = thumbnailData;
|
||||
int callbackCount = mCallbacks.size();
|
||||
for (int i = 0; i < callbackCount; i++) {
|
||||
mCallbacks.get(i).onTaskDataLoaded(this, thumbnailData);
|
||||
}
|
||||
}
|
||||
|
||||
/** Notifies the callback listeners that this task has been unloaded */
|
||||
@Deprecated
|
||||
public void notifyTaskDataUnloaded(Drawable defaultApplicationIcon) {
|
||||
icon = defaultApplicationIcon;
|
||||
thumbnail = null;
|
||||
for (int i = mCallbacks.size() - 1; i >= 0; i--) {
|
||||
mCallbacks.get(i).onTaskDataUnloaded();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top activity component.
|
||||
*/
|
||||
@@ -407,6 +282,29 @@ public class Task {
|
||||
: key.baseIntent.getComponent();
|
||||
}
|
||||
|
||||
public void setLastSnapshotData(ActivityManager.RecentTaskInfo rawTask) {
|
||||
lastSnapshotData.set(rawTask.lastSnapshotData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
// Check that the id matches
|
||||
@@ -424,9 +322,6 @@ public class Task {
|
||||
if (!isDockable) {
|
||||
writer.print(" dockable=N");
|
||||
}
|
||||
if (isLaunchTarget) {
|
||||
writer.print(" launchTarget=Y");
|
||||
}
|
||||
if (isLocked) {
|
||||
writer.print(" locked=Y");
|
||||
}
|
||||
|
||||
@@ -22,14 +22,14 @@ import static android.graphics.Bitmap.Config.ARGB_8888;
|
||||
|
||||
import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED;
|
||||
|
||||
import android.app.ActivityManager.TaskSnapshot;
|
||||
import android.window.TaskSnapshot;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.GraphicBuffer;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.util.Log;
|
||||
import android.view.WindowInsetsController.Appearance;
|
||||
|
||||
/**
|
||||
* Data for a single thumbnail.
|
||||
@@ -44,7 +44,7 @@ public class ThumbnailData {
|
||||
public boolean isRealSnapshot;
|
||||
public boolean isTranslucent;
|
||||
public int windowingMode;
|
||||
public int systemUiVisibility;
|
||||
public @Appearance int appearance;
|
||||
public float scale;
|
||||
public long snapshotId;
|
||||
|
||||
@@ -58,22 +58,30 @@ public class ThumbnailData {
|
||||
isRealSnapshot = true;
|
||||
isTranslucent = false;
|
||||
windowingMode = WINDOWING_MODE_UNDEFINED;
|
||||
systemUiVisibility = 0;
|
||||
snapshotId = 0;
|
||||
}
|
||||
|
||||
public ThumbnailData(TaskSnapshot snapshot) {
|
||||
final GraphicBuffer buffer = snapshot.getSnapshot();
|
||||
if (buffer == null || (buffer.getUsage() & HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE) == 0) {
|
||||
private static Bitmap makeThumbnail(TaskSnapshot snapshot) {
|
||||
Bitmap thumbnail = null;
|
||||
try (final HardwareBuffer buffer = snapshot.getHardwareBuffer()) {
|
||||
if (buffer != null) {
|
||||
thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
|
||||
}
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// TODO(b/157562905): Workaround for a crash when we get a snapshot without this state
|
||||
Log.e("ThumbnailData", "Unexpected snapshot without USAGE_GPU_SAMPLED_IMAGE: "
|
||||
+ buffer);
|
||||
+ snapshot.getHardwareBuffer(), ex);
|
||||
}
|
||||
if (thumbnail == null) {
|
||||
Point taskSize = snapshot.getTaskSize();
|
||||
thumbnail = Bitmap.createBitmap(taskSize.x, taskSize.y, ARGB_8888);
|
||||
thumbnail.eraseColor(Color.BLACK);
|
||||
} else {
|
||||
thumbnail = Bitmap.wrapHardwareBuffer(buffer, snapshot.getColorSpace());
|
||||
}
|
||||
return thumbnail;
|
||||
}
|
||||
|
||||
public ThumbnailData(TaskSnapshot snapshot) {
|
||||
thumbnail = makeThumbnail(snapshot);
|
||||
insets = new Rect(snapshot.getContentInsets());
|
||||
orientation = snapshot.getOrientation();
|
||||
rotation = snapshot.getRotation();
|
||||
@@ -84,7 +92,7 @@ public class ThumbnailData {
|
||||
isRealSnapshot = snapshot.isRealSnapshot();
|
||||
isTranslucent = snapshot.isTranslucent();
|
||||
windowingMode = snapshot.getWindowingMode();
|
||||
systemUiVisibility = snapshot.getSystemUiVisibility();
|
||||
appearance = snapshot.getAppearance();
|
||||
snapshotId = snapshot.getId();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ public final class BitmapUtil {
|
||||
HardwareBuffer buffer = bundle.getParcelable(KEY_BUFFER);
|
||||
ParcelableColorSpace colorSpace = bundle.getParcelable(KEY_COLOR_SPACE);
|
||||
|
||||
return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer), colorSpace);
|
||||
return Bitmap.wrapHardwareBuffer(Objects.requireNonNull(buffer),
|
||||
colorSpace.getColorSpace());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -36,6 +36,6 @@ public class AppTransitionAnimationSpecCompat {
|
||||
|
||||
public AppTransitionAnimationSpec toAppTransitionAnimationSpec() {
|
||||
return new AppTransitionAnimationSpec(mTaskId,
|
||||
mBuffer != null ? mBuffer.createGraphicBufferHandle() : null, mRect);
|
||||
mBuffer != null ? mBuffer.getHardwareBuffer() : null, mRect);
|
||||
}
|
||||
}
|
||||
|
||||
+72
-231
@@ -20,39 +20,31 @@ import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
|
||||
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
|
||||
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
|
||||
import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
import static android.app.ActivityTaskManager.getService;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
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.ActivityManager.TaskSnapshot;
|
||||
import android.window.TaskSnapshot;
|
||||
import android.app.ActivityOptions;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.IAssistDataReceiver;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
@@ -61,12 +53,9 @@ import android.view.RemoteAnimationTarget;
|
||||
|
||||
import com.android.internal.app.IVoiceInteractionManagerService;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class ActivityManagerWrapper {
|
||||
@@ -82,16 +71,8 @@ public class ActivityManagerWrapper {
|
||||
// Should match the value in AssistManager
|
||||
private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms";
|
||||
|
||||
private final PackageManager mPackageManager;
|
||||
private final BackgroundExecutor mBackgroundExecutor;
|
||||
private final TaskStackChangeListeners mTaskStackChangeListeners;
|
||||
|
||||
private ActivityManagerWrapper() {
|
||||
final Context context = AppGlobals.getInitialApplication();
|
||||
mPackageManager = context.getPackageManager();
|
||||
mBackgroundExecutor = BackgroundExecutor.get();
|
||||
mTaskStackChangeListeners = new TaskStackChangeListeners(Looper.getMainLooper());
|
||||
}
|
||||
private final ActivityTaskManager mAtm = ActivityTaskManager.getInstance();
|
||||
private ActivityManagerWrapper() { }
|
||||
|
||||
public static ActivityManagerWrapper getInstance() {
|
||||
return sInstance;
|
||||
@@ -123,38 +104,28 @@ public class ActivityManagerWrapper {
|
||||
*/
|
||||
public ActivityManager.RunningTaskInfo getRunningTask(boolean filterOnlyVisibleRecents) {
|
||||
// Note: The set of running tasks from the system is ordered by recency
|
||||
try {
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
ActivityTaskManager.getService().getFilteredTasks(1, filterOnlyVisibleRecents);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.get(0);
|
||||
} catch (RemoteException e) {
|
||||
List<ActivityManager.RunningTaskInfo> tasks =
|
||||
mAtm.getTasks(1, filterOnlyVisibleRecents);
|
||||
if (tasks.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return tasks.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a list of the recents tasks.
|
||||
*/
|
||||
public List<RecentTaskInfo> getRecentTasks(int numTasks, int userId) {
|
||||
try {
|
||||
return ActivityTaskManager.getService().getRecentTasks(numTasks,
|
||||
RECENT_IGNORE_UNAVAILABLE, userId).getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to get recent tasks", e);
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return mAtm.getRecentTasks(numTasks, RECENT_IGNORE_UNAVAILABLE, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the task snapshot for the given {@param taskId}.
|
||||
*/
|
||||
public @NonNull ThumbnailData getTaskThumbnail(int taskId, boolean isLowResolution) {
|
||||
ActivityManager.TaskSnapshot snapshot = null;
|
||||
TaskSnapshot snapshot = null;
|
||||
try {
|
||||
snapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId, isLowResolution);
|
||||
snapshot = getService().getTaskSnapshot(taskId, isLowResolution);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to retrieve task snapshot", e);
|
||||
}
|
||||
@@ -169,80 +140,37 @@ public class ActivityManagerWrapper {
|
||||
* Removes the outdated snapshot of home task.
|
||||
*/
|
||||
public void invalidateHomeTaskSnapshot(final Activity homeActivity) {
|
||||
mBackgroundExecutor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActivityTaskManager.getService().invalidateHomeTaskSnapshot(
|
||||
homeActivity.getActivityToken());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to invalidate home snapshot", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the activity label, badging if necessary.
|
||||
*/
|
||||
public String getBadgedActivityLabel(ActivityInfo info, int userId) {
|
||||
return getBadgedLabel(info.loadLabel(mPackageManager).toString(), userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the application label, badging if necessary.
|
||||
*/
|
||||
public String getBadgedApplicationLabel(ApplicationInfo appInfo, int userId) {
|
||||
return getBadgedLabel(appInfo.loadLabel(mPackageManager).toString(), userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the content description for a given task, badging it if necessary. The content
|
||||
* description joins the app and activity labels.
|
||||
*/
|
||||
public String getBadgedContentDescription(ActivityInfo info, int userId,
|
||||
ActivityManager.TaskDescription td) {
|
||||
String activityLabel;
|
||||
if (td != null && td.getLabel() != null) {
|
||||
activityLabel = td.getLabel();
|
||||
} else {
|
||||
activityLabel = info.loadLabel(mPackageManager).toString();
|
||||
try {
|
||||
ActivityClient.getInstance().invalidateHomeTaskSnapshot(
|
||||
homeActivity.getActivityToken());
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "Failed to invalidate home snapshot", e);
|
||||
}
|
||||
String applicationLabel = info.applicationInfo.loadLabel(mPackageManager).toString();
|
||||
String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
|
||||
return applicationLabel.equals(activityLabel)
|
||||
? badgedApplicationLabel
|
||||
: badgedApplicationLabel + " " + activityLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the given label for a user, badging if necessary.
|
||||
*/
|
||||
private String getBadgedLabel(String label, int userId) {
|
||||
if (userId != UserHandle.myUserId()) {
|
||||
label = mPackageManager.getUserBadgedLabel(label, new UserHandle(userId)).toString();
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the recents activity. The caller should manage the thread on which this is called.
|
||||
*/
|
||||
public void startRecentsActivity(Intent intent, final AssistDataReceiver assistDataReceiver,
|
||||
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.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 {
|
||||
IAssistDataReceiver receiver = null;
|
||||
if (assistDataReceiver != null) {
|
||||
receiver = new IAssistDataReceiver.Stub() {
|
||||
public void onHandleAssistData(Bundle resultData) {
|
||||
assistDataReceiver.onHandleAssistData(resultData);
|
||||
}
|
||||
public void onHandleAssistScreenshot(Bitmap screenshot) {
|
||||
assistDataReceiver.onHandleAssistScreenshot(screenshot);
|
||||
}
|
||||
};
|
||||
}
|
||||
IRecentsAnimationRunner runner = null;
|
||||
if (animationHandler != null) {
|
||||
runner = new IRecentsAnimationRunner.Stub() {
|
||||
@@ -272,100 +200,58 @@ public class ActivityManagerWrapper {
|
||||
}
|
||||
};
|
||||
}
|
||||
ActivityTaskManager.getService().startRecentsActivity(intent, receiver, runner);
|
||||
if (resultCallback != null) {
|
||||
resultCallbackHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resultCallback.accept(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
getService().startRecentsActivity(intent, eventTime, runner);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
if (resultCallback != null) {
|
||||
resultCallbackHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resultCallback.accept(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the remote recents animation started from {@link #startRecentsActivity}.
|
||||
*/
|
||||
public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
|
||||
public void cancelRecentsAnimation(boolean restoreHomeRootTaskPosition) {
|
||||
try {
|
||||
ActivityTaskManager.getService().cancelRecentsAnimation(restoreHomeStackPosition);
|
||||
getService().cancelRecentsAnimation(restoreHomeRootTaskPosition);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to cancel recents animation", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a task from Recents.
|
||||
*
|
||||
* @see {@link #startActivityFromRecentsAsync(TaskKey, ActivityOptions, int, int, Consumer, Handler)}
|
||||
*/
|
||||
public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
|
||||
Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
|
||||
startActivityFromRecentsAsync(taskKey, options, WINDOWING_MODE_UNDEFINED,
|
||||
ACTIVITY_TYPE_UNDEFINED, resultCallback, resultCallbackHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a task from Recents.
|
||||
*
|
||||
* @param resultCallback The result success callback
|
||||
* @param resultCallbackHandler The handler to receive the result callback
|
||||
*/
|
||||
public void startActivityFromRecentsAsync(final Task.TaskKey taskKey, ActivityOptions options,
|
||||
int windowingMode, int activityType, final Consumer<Boolean> resultCallback,
|
||||
final Handler resultCallbackHandler) {
|
||||
if (taskKey.windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
|
||||
// We show non-visible docked tasks in Recents, but we always want to launch
|
||||
// them in the fullscreen stack.
|
||||
if (options == null) {
|
||||
options = ActivityOptions.makeBasic();
|
||||
}
|
||||
options.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
||||
} else if (windowingMode != WINDOWING_MODE_UNDEFINED
|
||||
|| activityType != ACTIVITY_TYPE_UNDEFINED) {
|
||||
if (options == null) {
|
||||
options = ActivityOptions.makeBasic();
|
||||
}
|
||||
options.setLaunchWindowingMode(windowingMode);
|
||||
options.setLaunchActivityType(activityType);
|
||||
}
|
||||
final ActivityOptions finalOptions = options;
|
||||
|
||||
|
||||
boolean result = false;
|
||||
try {
|
||||
result = startActivityFromRecents(taskKey.id, finalOptions);
|
||||
} catch (Exception e) {
|
||||
// Fall through
|
||||
}
|
||||
final boolean finalResult = result;
|
||||
public void startActivityFromRecentsAsync(Task.TaskKey taskKey, ActivityOptions options,
|
||||
Consumer<Boolean> resultCallback, Handler resultCallbackHandler) {
|
||||
final boolean result = startActivityFromRecents(taskKey, options);
|
||||
if (resultCallback != null) {
|
||||
resultCallbackHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
resultCallback.accept(finalResult);
|
||||
resultCallback.accept(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a task from Recents synchronously.
|
||||
*/
|
||||
public boolean startActivityFromRecents(Task.TaskKey taskKey, ActivityOptions options) {
|
||||
ActivityOptionsCompat.addTaskInfo(options, taskKey);
|
||||
return startActivityFromRecents(taskKey.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a task from Recents synchronously.
|
||||
*/
|
||||
public boolean startActivityFromRecents(int taskId, ActivityOptions options) {
|
||||
try {
|
||||
Bundle optsBundle = options == null ? null : options.toBundle();
|
||||
ActivityTaskManager.getService().startActivityFromRecents(taskId, optsBundle);
|
||||
getService().startActivityFromRecents(taskId, optsBundle);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
@@ -373,94 +259,49 @@ public class ActivityManagerWrapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves an already resumed task to the side of the screen to initiate split screen.
|
||||
*/
|
||||
public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
|
||||
Rect initialBounds) {
|
||||
try {
|
||||
return ActivityTaskManager.getService().setTaskWindowingModeSplitScreenPrimary(taskId,
|
||||
true /* onTop */);
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a task stack listener with the system.
|
||||
* This should be called on the main thread.
|
||||
* @deprecated use {@link TaskStackChangeListeners#registerTaskStackListener}
|
||||
*/
|
||||
public void registerTaskStackListener(TaskStackChangeListener listener) {
|
||||
synchronized (mTaskStackChangeListeners) {
|
||||
mTaskStackChangeListeners.addListener(ActivityManager.getService(), listener);
|
||||
}
|
||||
TaskStackChangeListeners.getInstance().registerTaskStackListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a task stack listener with the system.
|
||||
* This should be called on the main thread.
|
||||
* @deprecated use {@link TaskStackChangeListeners#unregisterTaskStackListener}
|
||||
*/
|
||||
public void unregisterTaskStackListener(TaskStackChangeListener listener) {
|
||||
synchronized (mTaskStackChangeListeners) {
|
||||
mTaskStackChangeListeners.removeListener(listener);
|
||||
}
|
||||
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the system close any open system windows (including other SystemUI).
|
||||
*/
|
||||
public Future<?> closeSystemWindows(final String reason) {
|
||||
return mBackgroundExecutor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActivityManager.getService().closeSystemDialogs(reason);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to close system windows", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
public void closeSystemWindows(final String reason) {
|
||||
try {
|
||||
ActivityManager.getService().closeSystemDialogs(reason);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to close system windows", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a task by id.
|
||||
*/
|
||||
public void removeTask(final int taskId) {
|
||||
mBackgroundExecutor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActivityTaskManager.getService().removeTask(taskId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to remove task=" + taskId, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
getService().removeTask(taskId);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to remove task=" + taskId, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the recent tasks.
|
||||
*/
|
||||
public void removeAllRecentTasks() {
|
||||
mBackgroundExecutor.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
ActivityTaskManager.getService().removeAllVisibleRecentTasks();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to remove all tasks", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the current window transtion to/from Recents for the given task id.
|
||||
*/
|
||||
public void cancelWindowTransition(int taskId) {
|
||||
try {
|
||||
ActivityTaskManager.getService().cancelTaskWindowTransition(taskId);
|
||||
getService().removeAllVisibleRecentTasks();
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed to cancel window transition for task=" + taskId, e);
|
||||
Log.w(TAG, "Failed to remove all tasks", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +310,7 @@ public class ActivityManagerWrapper {
|
||||
*/
|
||||
public boolean isScreenPinningActive() {
|
||||
try {
|
||||
return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED;
|
||||
return getService().getLockTaskModeState() == LOCK_TASK_MODE_PINNED;
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
@@ -488,7 +329,7 @@ public class ActivityManagerWrapper {
|
||||
*/
|
||||
public boolean isLockToAppActive() {
|
||||
try {
|
||||
return ActivityTaskManager.getService().getLockTaskModeState() != LOCK_TASK_MODE_NONE;
|
||||
return getService().getLockTaskModeState() != LOCK_TASK_MODE_NONE;
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
@@ -499,7 +340,7 @@ public class ActivityManagerWrapper {
|
||||
*/
|
||||
public boolean isLockTaskKioskModeActive() {
|
||||
try {
|
||||
return ActivityTaskManager.getService().getLockTaskModeState() == LOCK_TASK_MODE_LOCKED;
|
||||
return getService().getLockTaskModeState() == LOCK_TASK_MODE_LOCKED;
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
|
||||
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
@@ -26,6 +24,8 @@ import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
|
||||
/**
|
||||
* Wrapper around internal ActivityOptions creation.
|
||||
*/
|
||||
@@ -46,9 +46,6 @@ public abstract class ActivityOptionsCompat {
|
||||
options.setLaunchWindowingMode(isPrimary
|
||||
? WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
|
||||
: WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
||||
options.setSplitScreenCreateMode(dockTopLeft
|
||||
? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
|
||||
: SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT);
|
||||
return options;
|
||||
}
|
||||
|
||||
@@ -63,12 +60,25 @@ public abstract class ActivityOptionsCompat {
|
||||
|
||||
public static ActivityOptions makeRemoteAnimation(
|
||||
RemoteAnimationAdapterCompat remoteAnimationAdapter) {
|
||||
return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped());
|
||||
return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped(),
|
||||
remoteAnimationAdapter.getRemoteTransition().getTransition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an ActivityOptions object that will delegate its transition handling to a
|
||||
* `remoteTransition`.
|
||||
*/
|
||||
public static ActivityOptions makeRemoteTransition(RemoteTransitionCompat remoteTransition) {
|
||||
return ActivityOptions.makeRemoteTransition(remoteTransition.getTransition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ActivityOptions for overriding task transition animation.
|
||||
*/
|
||||
public static ActivityOptions makeCustomAnimation(Context context, int enterResId,
|
||||
int exitResId, final Runnable callback, final Handler callbackHandler) {
|
||||
return ActivityOptions.makeCustomAnimation(context, enterResId, exitResId, callbackHandler,
|
||||
return ActivityOptions.makeCustomTaskAnimation(context, enterResId, exitResId,
|
||||
callbackHandler,
|
||||
new ActivityOptions.OnAnimationStartedListener() {
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
@@ -86,4 +96,23 @@ public abstract class ActivityOptionsCompat {
|
||||
opts.setFreezeRecentTasksReordering();
|
||||
return opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the launch event time from launcher.
|
||||
*/
|
||||
public static ActivityOptions setLauncherSourceInfo(ActivityOptions opts, long uptimeMillis) {
|
||||
opts.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER, uptimeMillis);
|
||||
return opts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets Task specific information to the activity options
|
||||
*/
|
||||
public static void addTaskInfo(ActivityOptions opts, Task.TaskKey taskKey) {
|
||||
if (taskKey.windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
|
||||
// We show non-visible docked tasks in Recents, but we always want to launch
|
||||
// them in the fullscreen stack.
|
||||
opts.setLaunchWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Offloads work from other threads by running it in a background thread.
|
||||
*/
|
||||
public class BackgroundExecutor {
|
||||
|
||||
private static final BackgroundExecutor sInstance = new BackgroundExecutor();
|
||||
|
||||
private final ExecutorService mExecutorService = Executors.newFixedThreadPool(2);
|
||||
|
||||
/**
|
||||
* @return the static instance of the background executor.
|
||||
*/
|
||||
public static BackgroundExecutor get() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@param callable} on one of the background executor threads.
|
||||
*/
|
||||
public <T> Future<T> submit(Callable<T> callable) {
|
||||
return mExecutorService.submit(callable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@param runnable} on one of the background executor threads.
|
||||
*/
|
||||
public Future<?> submit(Runnable runnable) {
|
||||
return mExecutorService.submit(runnable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given {@param runnable} on one of the background executor threads. Return
|
||||
* {@param result} when the future is resolved.
|
||||
*/
|
||||
public <T> Future<T> submit(Runnable runnable, T result) {
|
||||
return mExecutorService.submit(runnable, result);
|
||||
}
|
||||
}
|
||||
@@ -16,22 +16,20 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import static android.view.CrossWindowBlurListeners.CROSS_WINDOW_BLUR_SUPPORTED;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
public abstract class BlurUtils {
|
||||
|
||||
private static boolean mBlurSupportedSysProp = SystemProperties
|
||||
.getBoolean("ro.surface_flinger.supports_background_blur", false);
|
||||
private static boolean mBlurDisabledSysProp = SystemProperties
|
||||
.getBoolean("persist.sys.sf.disable_blurs", false);
|
||||
|
||||
/**
|
||||
* If this device can render blurs.
|
||||
*
|
||||
* @return {@code true} when supported.
|
||||
*/
|
||||
public static boolean supportsBlursOnWindows() {
|
||||
return mBlurSupportedSysProp && !mBlurDisabledSysProp && ActivityManager.isHighEndGfx();
|
||||
return CROSS_WINDOW_BLUR_SUPPORTED && ActivityManager.isHighEndGfx()
|
||||
&& !SystemProperties.getBoolean("persist.sysui.disableBlur", false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import static android.view.Choreographer.CALLBACK_INPUT;
|
||||
|
||||
import android.view.Choreographer;
|
||||
|
||||
/**
|
||||
* Wraps the internal choreographer.
|
||||
*/
|
||||
public class ChoreographerCompat {
|
||||
|
||||
/**
|
||||
* Posts an input callback to the choreographer.
|
||||
*/
|
||||
public static void postInputFrame(Choreographer choreographer, Runnable runnable) {
|
||||
choreographer.postCallback(CALLBACK_INPUT, runnable, null);
|
||||
}
|
||||
|
||||
public static Choreographer getSfInstance() {
|
||||
return Choreographer.getSfInstance();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.content.ClipDescription;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* Wrapper around ClipDescription.
|
||||
*/
|
||||
public abstract class ClipDescriptionCompat {
|
||||
|
||||
public static String MIMETYPE_APPLICATION_ACTIVITY =
|
||||
ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
|
||||
|
||||
public static String MIMETYPE_APPLICATION_SHORTCUT =
|
||||
ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
|
||||
|
||||
public static String MIMETYPE_APPLICATION_TASK =
|
||||
ClipDescription.MIMETYPE_APPLICATION_TASK;
|
||||
|
||||
public static String EXTRA_PENDING_INTENT = ClipDescription.EXTRA_PENDING_INTENT;
|
||||
|
||||
public static String EXTRA_TASK_ID = Intent.EXTRA_TASK_ID;
|
||||
}
|
||||
+10
-10
@@ -14,15 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.recents;
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
/**
|
||||
* Listener interface that Launcher attaches to SystemUI to get
|
||||
* pinned stack animation callbacks.
|
||||
*/
|
||||
oneway interface IPinnedStackAnimationListener {
|
||||
/**
|
||||
* Notifies the pinned stack animation is started.
|
||||
*/
|
||||
void onPinnedStackAnimationStarted();
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.Context;
|
||||
|
||||
public class ContextUtils {
|
||||
|
||||
/** Get the user associated with this context */
|
||||
public static @UserIdInt int getUserId(Context context) {
|
||||
return context.getUserId();
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.graphics.Matrix;
|
||||
import android.os.Looper;
|
||||
import android.view.BatchedInputEventReceiver;
|
||||
import android.view.Choreographer;
|
||||
import android.view.InputChannel;
|
||||
import android.view.InputEvent;
|
||||
import android.view.InputEventSender;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
@@ -40,16 +39,6 @@ public class InputChannelCompat {
|
||||
void onInputEvent(InputEvent ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dispatcher from the extras received as part on onInitialize
|
||||
*/
|
||||
public static InputEventReceiver fromBundle(Bundle params, String key,
|
||||
Looper looper, Choreographer choreographer, InputEventListener listener) {
|
||||
|
||||
InputChannel channel = params.getParcelable(key);
|
||||
return new InputEventReceiver(channel, looper, choreographer, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Version of addBatch method which preserves time accuracy in nanoseconds instead of
|
||||
* converting the time to milliseconds.
|
||||
@@ -63,17 +52,21 @@ public class InputChannelCompat {
|
||||
return target.addBatch(src);
|
||||
}
|
||||
|
||||
/** @see MotionEvent#createRotateMatrix */
|
||||
public static Matrix createRotationMatrix(
|
||||
/*@Surface.Rotation*/ int rotation, int displayW, int displayH) {
|
||||
return MotionEvent.createRotateMatrix(rotation, displayW, displayH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BatchedInputEventReceiver
|
||||
*/
|
||||
public static class InputEventReceiver {
|
||||
|
||||
private final BatchedInputEventReceiver mReceiver;
|
||||
private final InputChannel mInputChannel;
|
||||
|
||||
public InputEventReceiver(InputChannel inputChannel, Looper looper,
|
||||
Choreographer choreographer, final InputEventListener listener) {
|
||||
mInputChannel = inputChannel;
|
||||
mReceiver = new BatchedInputEventReceiver(inputChannel, looper, choreographer) {
|
||||
|
||||
@Override
|
||||
@@ -84,41 +77,18 @@ public class InputChannelCompat {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BatchedInputEventReceiver#setBatchingEnabled()
|
||||
*/
|
||||
public void setBatchingEnabled(boolean batchingEnabled) {
|
||||
mReceiver.setBatchingEnabled(batchingEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see BatchedInputEventReceiver#dispose()
|
||||
*/
|
||||
public void dispose() {
|
||||
mReceiver.dispose();
|
||||
mInputChannel.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see InputEventSender
|
||||
*/
|
||||
public static class InputEventDispatcher {
|
||||
|
||||
private final InputChannel mInputChannel;
|
||||
private final InputEventSender mSender;
|
||||
|
||||
public InputEventDispatcher(InputChannel inputChannel, Looper looper) {
|
||||
mInputChannel = inputChannel;
|
||||
mSender = new InputEventSender(inputChannel, looper) { };
|
||||
}
|
||||
|
||||
/**
|
||||
* @see InputEventSender#sendInputEvent(int, InputEvent)
|
||||
*/
|
||||
public void dispatch(InputEvent ev) {
|
||||
mSender.sendInputEvent(ev.getSequenceNumber(), ev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see InputEventSender#dispose()
|
||||
*/
|
||||
public void dispose() {
|
||||
mSender.dispose();
|
||||
mInputChannel.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Manages the input consumer that allows the SystemUI to directly receive input.
|
||||
* TODO: Refactor this for the gesture nav case
|
||||
*/
|
||||
public class InputConsumerController {
|
||||
|
||||
@@ -98,14 +99,6 @@ public class InputConsumerController {
|
||||
mName = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A controller for the pip input consumer.
|
||||
*/
|
||||
public static InputConsumerController getPipInputConsumer() {
|
||||
return new InputConsumerController(WindowManagerGlobal.getWindowManagerService(),
|
||||
INPUT_CONSUMER_PIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A controller for the recents animation input consumer.
|
||||
*/
|
||||
@@ -155,7 +148,6 @@ public class InputConsumerController {
|
||||
if (mInputEventReceiver == null) {
|
||||
final InputChannel inputChannel = new InputChannel();
|
||||
try {
|
||||
// TODO(b/113087003): Support Picture-in-picture in multi-display.
|
||||
mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
|
||||
mWindowManager.createInputConsumer(mToken, mName, DEFAULT_DISPLAY, inputChannel);
|
||||
} catch (RemoteException e) {
|
||||
@@ -175,7 +167,6 @@ public class InputConsumerController {
|
||||
public void unregisterInputConsumer() {
|
||||
if (mInputEventReceiver != null) {
|
||||
try {
|
||||
// TODO(b/113087003): Support Picture-in-picture in multi-display.
|
||||
mWindowManager.destroyInputConsumer(mName, DEFAULT_DISPLAY);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to destroy input consumer", e);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.hardware.input.InputManager;
|
||||
import android.os.Looper;
|
||||
import android.view.Choreographer;
|
||||
import android.view.InputMonitor;
|
||||
@@ -27,11 +27,13 @@ import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
|
||||
* @see android.view.InputMonitor
|
||||
*/
|
||||
public class InputMonitorCompat {
|
||||
|
||||
private final InputMonitor mInputMonitor;
|
||||
|
||||
private InputMonitorCompat(InputMonitor monitor) {
|
||||
mInputMonitor = monitor;
|
||||
/**
|
||||
* Monitor input on the specified display for gestures.
|
||||
*/
|
||||
public InputMonitorCompat(String name, int displayId) {
|
||||
mInputMonitor = InputManager.getInstance().monitorGestureInput(name, displayId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,11 +58,4 @@ public class InputMonitorCompat {
|
||||
return new InputEventReceiver(mInputMonitor.getInputChannel(), looper, choreographer,
|
||||
listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the input monitor stored in a bundle
|
||||
*/
|
||||
public static InputMonitorCompat fromBundle(Bundle bundle, String key) {
|
||||
return new InputMonitorCompat((InputMonitor) bundle.getParcelable(key));
|
||||
}
|
||||
}
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.jank.InteractionJankMonitor.Configuration;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
public final class InteractionJankMonitorWrapper {
|
||||
private static final String TAG = "JankMonitorWrapper";
|
||||
|
||||
// Launcher journeys.
|
||||
public static final int CUJ_APP_LAUNCH_FROM_RECENTS =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_RECENTS;
|
||||
public static final int CUJ_APP_LAUNCH_FROM_ICON =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_ICON;
|
||||
public static final int CUJ_APP_CLOSE_TO_HOME =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_HOME;
|
||||
public static final int CUJ_APP_CLOSE_TO_PIP =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_APP_CLOSE_TO_PIP;
|
||||
public static final int CUJ_QUICK_SWITCH =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_QUICK_SWITCH;
|
||||
public static final int CUJ_OPEN_ALL_APPS =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_OPEN_ALL_APPS;
|
||||
public static final int CUJ_ALL_APPS_SCROLL =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_ALL_APPS_SCROLL;
|
||||
public static final int CUJ_APP_LAUNCH_FROM_WIDGET =
|
||||
InteractionJankMonitor.CUJ_LAUNCHER_APP_LAUNCH_FROM_WIDGET;
|
||||
|
||||
@IntDef({
|
||||
CUJ_APP_LAUNCH_FROM_RECENTS,
|
||||
CUJ_APP_LAUNCH_FROM_ICON,
|
||||
CUJ_APP_CLOSE_TO_HOME,
|
||||
CUJ_APP_CLOSE_TO_PIP,
|
||||
CUJ_QUICK_SWITCH,
|
||||
CUJ_APP_LAUNCH_FROM_WIDGET,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CujType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a trace session.
|
||||
*
|
||||
* @param v an attached view.
|
||||
* @param cujType the specific {@link InteractionJankMonitor.CujType}.
|
||||
*/
|
||||
public static void begin(View v, @CujType int cujType) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
|
||||
InteractionJankMonitor.getInstance().begin(v, cujType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Begin a trace session.
|
||||
*
|
||||
* @param v an attached view.
|
||||
* @param cujType the specific {@link InteractionJankMonitor.CujType}.
|
||||
* @param timeout duration to cancel the instrumentation in ms
|
||||
*/
|
||||
public static void begin(View v, @CujType int cujType, long timeout) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
|
||||
Configuration.Builder builder =
|
||||
new Configuration.Builder(cujType)
|
||||
.setView(v)
|
||||
.setTimeout(timeout);
|
||||
InteractionJankMonitor.getInstance().begin(builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* End a trace session.
|
||||
*
|
||||
* @param cujType the specific {@link InteractionJankMonitor.CujType}.
|
||||
*/
|
||||
public static void end(@CujType int cujType) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
|
||||
InteractionJankMonitor.getInstance().end(cujType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the trace session.
|
||||
*/
|
||||
public static void cancel(@CujType int cujType) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return;
|
||||
InteractionJankMonitor.getInstance().cancel(cujType);
|
||||
}
|
||||
}
|
||||
@@ -24,11 +24,18 @@ import com.android.internal.util.LatencyTracker;
|
||||
* @see LatencyTracker
|
||||
*/
|
||||
public class LatencyTrackerCompat {
|
||||
public static boolean isEnabled(Context context) {
|
||||
return LatencyTracker.isEnabled(context);
|
||||
/**
|
||||
* @see LatencyTracker
|
||||
* @deprecated Please use {@link LatencyTrackerCompat#logToggleRecents(Context, int)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void logToggleRecents(int duration) {
|
||||
LatencyTracker.logActionDeprecated(LatencyTracker.ACTION_TOGGLE_RECENTS, duration, false);
|
||||
}
|
||||
|
||||
public static void logToggleRecents(int duration) {
|
||||
LatencyTracker.logAction(LatencyTracker.ACTION_TOGGLE_RECENTS, duration);
|
||||
/** @see LatencyTracker */
|
||||
public static void logToggleRecents(Context context, int duration) {
|
||||
LatencyTracker.getInstance(context).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS,
|
||||
duration);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
|
||||
/**
|
||||
* Wrapper around LauncherApps.
|
||||
*/
|
||||
public abstract class LauncherAppsCompat {
|
||||
|
||||
public static PendingIntent getMainActivityLaunchIntent(LauncherApps launcherApps,
|
||||
ComponentName component, Bundle startActivityOptions, UserHandle user) {
|
||||
return launcherApps.getMainActivityLaunchIntent(component, startActivityOptions, user);
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,4 @@ public class LauncherEventUtil {
|
||||
// Constants for the Action
|
||||
public static final int VISIBLE = 0;
|
||||
public static final int DISMISS = 1;
|
||||
|
||||
// Constants for the Target (View)
|
||||
public static final int RECENTS_SWIPE_UP_ONBOARDING_TIP = 0;
|
||||
public static final int RECENTS_QUICK_SCRUB_ONBOARDING_TIP = 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
/**
|
||||
* These strings are part of the {@link com.android.systemui.people.PeopleProvider} API
|
||||
* contract. The API returns a People Tile preview that can be displayed by calling packages.
|
||||
* The provider is part of the SystemUI service, and the strings live here for shared access with
|
||||
* Launcher (caller).
|
||||
*/
|
||||
public class PeopleProviderUtils {
|
||||
/**
|
||||
* ContentProvider URI scheme.
|
||||
* @hide
|
||||
*/
|
||||
public static final String PEOPLE_PROVIDER_SCHEME = "content://";
|
||||
|
||||
/**
|
||||
* ContentProvider URI authority.
|
||||
* @hide
|
||||
*/
|
||||
public static final String PEOPLE_PROVIDER_AUTHORITY =
|
||||
"com.android.systemui.people.PeopleProvider";
|
||||
|
||||
/**
|
||||
* Method name for getting People Tile preview.
|
||||
* @hide
|
||||
*/
|
||||
public static final String GET_PEOPLE_TILE_PREVIEW_METHOD = "get_people_tile_preview";
|
||||
|
||||
/**
|
||||
* Extras bundle key specifying shortcut Id of the People Tile preview requested.
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRAS_KEY_SHORTCUT_ID = "shortcut_id";
|
||||
|
||||
/**
|
||||
* Extras bundle key specifying package name of the People Tile preview requested.
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRAS_KEY_PACKAGE_NAME = "package_name";
|
||||
|
||||
/**
|
||||
* Extras bundle key specifying {@code UserHandle} of the People Tile preview requested.
|
||||
* @hide
|
||||
*/
|
||||
public static final String EXTRAS_KEY_USER_HANDLE = "user_handle";
|
||||
|
||||
/**
|
||||
* Response bundle key to access the returned People Tile preview.
|
||||
* @hide
|
||||
*/
|
||||
public static final String RESPONSE_KEY_REMOTE_VIEWS = "remote_views";
|
||||
|
||||
/**
|
||||
* Name of the permission needed to get a People Tile preview for a given conversation shortcut.
|
||||
* @hide
|
||||
*/
|
||||
public static final String GET_PEOPLE_TILE_PREVIEW_PERMISSION =
|
||||
"android.permission.GET_PEOPLE_TILE_PREVIEW";
|
||||
|
||||
}
|
||||
-124
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.IPinnedStackController;
|
||||
import android.view.IPinnedStackListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PinnedStackListener that simply forwards all calls to each listener added via
|
||||
* {@link #addListener}. This is necessary since calling
|
||||
* {@link com.android.server.wm.WindowManagerService#registerPinnedStackListener} replaces any
|
||||
* previously set listener.
|
||||
*/
|
||||
public class PinnedStackListenerForwarder extends IPinnedStackListener.Stub {
|
||||
private List<PinnedStackListener> mListeners = new ArrayList<>();
|
||||
|
||||
/** Adds a listener to receive updates from the WindowManagerService. */
|
||||
public void addListener(PinnedStackListener listener) {
|
||||
mListeners.add(listener);
|
||||
}
|
||||
|
||||
/** Removes a listener so it will no longer receive updates from the WindowManagerService. */
|
||||
public void removeListener(PinnedStackListener listener) {
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onListenerRegistered(IPinnedStackController controller) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onListenerRegistered(controller);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMovementBoundsChanged(boolean fromImeAdjustment) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onMovementBoundsChanged(fromImeAdjustment);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onImeVisibilityChanged(imeVisible, imeHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActionsChanged(ParceledListSlice actions) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onActionsChanged(actions);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityHidden(ComponentName componentName) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onActivityHidden(componentName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayInfoChanged(DisplayInfo displayInfo) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onDisplayInfoChanged(displayInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged() {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onConfigurationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAspectRatioChanged(float aspectRatio) {
|
||||
for (PinnedStackListener listener : mListeners) {
|
||||
listener.onAspectRatioChanged(aspectRatio);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A counterpart of {@link IPinnedStackListener} with empty implementations.
|
||||
* Subclasses can ignore those methods they do not intend to take action upon.
|
||||
*/
|
||||
public static class PinnedStackListener {
|
||||
public void onListenerRegistered(IPinnedStackController controller) {}
|
||||
|
||||
public void onMovementBoundsChanged(boolean fromImeAdjustment) {}
|
||||
|
||||
public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {}
|
||||
|
||||
public void onActionsChanged(ParceledListSlice actions) {}
|
||||
|
||||
public void onActivityHidden(ComponentName componentName) {}
|
||||
|
||||
public void onDisplayInfoChanged(DisplayInfo displayInfo) {}
|
||||
|
||||
public void onConfigurationChanged() {}
|
||||
|
||||
public void onAspectRatioChanged(float aspectRatio) {}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
||||
import android.annotation.IntDef;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
|
||||
@@ -37,11 +36,27 @@ import java.util.StringJoiner;
|
||||
* Various shared constants between Launcher and SysUI as part of quickstep
|
||||
*/
|
||||
public class QuickStepContract {
|
||||
// Fully qualified name of the Launcher activity.
|
||||
public static final String LAUNCHER_ACTIVITY_CLASS_NAME =
|
||||
"com.google.android.apps.nexuslauncher.NexusLauncherActivity";
|
||||
|
||||
public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
|
||||
public static final String KEY_EXTRA_INPUT_MONITOR = "extra_input_monitor";
|
||||
public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
|
||||
public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
|
||||
// See IPip.aidl
|
||||
public static final String KEY_EXTRA_SHELL_PIP = "extra_shell_pip";
|
||||
// See ISplitScreen.aidl
|
||||
public static final String KEY_EXTRA_SHELL_SPLIT_SCREEN = "extra_shell_split_screen";
|
||||
// See IOneHanded.aidl
|
||||
public static final String KEY_EXTRA_SHELL_ONE_HANDED = "extra_shell_one_handed";
|
||||
// See IShellTransitions.aidl
|
||||
public static final String KEY_EXTRA_SHELL_SHELL_TRANSITIONS =
|
||||
"extra_shell_shell_transitions";
|
||||
// See IStartingWindow.aidl
|
||||
public static final String KEY_EXTRA_SHELL_STARTING_WINDOW =
|
||||
"extra_shell_starting_window";
|
||||
// See ISmartspaceTransitionController.aidl
|
||||
public static final String KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER = "smartspace_transition";
|
||||
|
||||
public static final String NAV_BAR_MODE_2BUTTON_OVERLAY =
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
|
||||
@@ -89,6 +104,14 @@ public class QuickStepContract {
|
||||
public static final int SYSUI_STATE_BUBBLES_EXPANDED = 1 << 14;
|
||||
// The global actions dialog is showing
|
||||
public static final int SYSUI_STATE_GLOBAL_ACTIONS_SHOWING = 1 << 15;
|
||||
// The one-handed mode is active
|
||||
public static final int SYSUI_STATE_ONE_HANDED_ACTIVE = 1 << 16;
|
||||
// Allow system gesture no matter the system bar(s) is visible or not
|
||||
public static final int SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1 << 17;
|
||||
// The IME is showing
|
||||
public static final int SYSUI_STATE_IME_SHOWING = 1 << 18;
|
||||
// The window magnification is overlapped with system gesture insets at the bottom.
|
||||
public static final int SYSUI_STATE_MAGNIFICATION_OVERLAP = 1 << 19;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({SYSUI_STATE_SCREEN_PINNING,
|
||||
@@ -106,7 +129,11 @@ public class QuickStepContract {
|
||||
SYSUI_STATE_TRACING_ENABLED,
|
||||
SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
|
||||
SYSUI_STATE_BUBBLES_EXPANDED,
|
||||
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
|
||||
SYSUI_STATE_GLOBAL_ACTIONS_SHOWING,
|
||||
SYSUI_STATE_ONE_HANDED_ACTIVE,
|
||||
SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
|
||||
SYSUI_STATE_IME_SHOWING,
|
||||
SYSUI_STATE_MAGNIFICATION_OVERLAP
|
||||
})
|
||||
public @interface SystemUiStateFlags {}
|
||||
|
||||
@@ -130,6 +157,11 @@ public class QuickStepContract {
|
||||
str.add((flags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0
|
||||
? "asst_gesture_constrain" : "");
|
||||
str.add((flags & SYSUI_STATE_BUBBLES_EXPANDED) != 0 ? "bubbles_expanded" : "");
|
||||
str.add((flags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0 ? "one_handed_active" : "");
|
||||
str.add((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0
|
||||
? "allow_gesture" : "");
|
||||
str.add((flags & SYSUI_STATE_IME_SHOWING) != 0 ? "ime_visible" : "");
|
||||
str.add((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0 ? "magnification_overlap" : "");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
@@ -172,6 +204,9 @@ public class QuickStepContract {
|
||||
* disabled.
|
||||
*/
|
||||
public static boolean isAssistantGestureDisabled(int sysuiStateFlags) {
|
||||
if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
|
||||
sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
|
||||
}
|
||||
// Disable when in quick settings, screen pinning, immersive, the bouncer is showing,
|
||||
// or search is disabled
|
||||
int disableFlags = SYSUI_STATE_SCREEN_PINNING
|
||||
@@ -202,6 +237,9 @@ public class QuickStepContract {
|
||||
|| (sysuiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0) {
|
||||
return false;
|
||||
}
|
||||
if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
|
||||
sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
|
||||
}
|
||||
// Disable when in immersive, or the notifications are interactive
|
||||
int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
|
||||
| SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
|
||||
@@ -236,9 +274,6 @@ public class QuickStepContract {
|
||||
* scaling, this means that we don't have to reload them on config changes.
|
||||
*/
|
||||
public static float getWindowCornerRadius(Resources resources) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
return 0;
|
||||
}
|
||||
return ScreenDecorationsUtils.getWindowCornerRadius(resources);
|
||||
}
|
||||
|
||||
@@ -246,9 +281,6 @@ public class QuickStepContract {
|
||||
* If live rounded corners are supported on windows.
|
||||
*/
|
||||
public static boolean supportsRoundedCornersOnWindows(Resources resources) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
return false;
|
||||
}
|
||||
return ScreenDecorationsUtils.supportsRoundedCornersOnWindows(resources);
|
||||
}
|
||||
}
|
||||
|
||||
+44
-2
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.app.ActivityManager.TaskSnapshot;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.PictureInPictureSurfaceTransaction;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
@@ -69,6 +71,24 @@ public class RecentsAnimationControllerCompat {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* updated accordingly. This should be called before `finish`
|
||||
* @param taskId Task id of the Activity in PiP mode.
|
||||
* @param finishTransaction leash operations for the final transform.
|
||||
* @param overlay the surface control for an overlay being shown above the pip (can be null)
|
||||
*/
|
||||
public void setFinishTaskTransaction(int taskId,
|
||||
PictureInPictureSurfaceTransaction finishTransaction,
|
||||
SurfaceControl overlay) {
|
||||
try {
|
||||
mAnimationController.setFinishTaskTransaction(taskId, finishTransaction, overlay);
|
||||
} catch (RemoteException e) {
|
||||
Log.d(TAG, "Failed to set finish task bounds", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the current recents animation.
|
||||
* @param toHome Going to home or back to the previous app.
|
||||
@@ -121,4 +141,26 @@ public class RecentsAnimationControllerCompat {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IRecentsAnimationController#detachNavigationBarFromApp
|
||||
*/
|
||||
public void detachNavigationBarFromApp(boolean moveHomeToTop) {
|
||||
try {
|
||||
mAnimationController.detachNavigationBarFromApp(moveHomeToTop);
|
||||
} catch (RemoteException e) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+214
-3
@@ -16,12 +16,30 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OLD_NONE;
|
||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
import static android.view.WindowManager.TransitionOldType;
|
||||
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.IRemoteAnimationFinishedCallback;
|
||||
import android.view.IRemoteAnimationRunner;
|
||||
import android.view.RemoteAnimationAdapter;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.IRemoteTransitionFinishedCallback;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @see RemoteAnimationAdapter
|
||||
@@ -29,28 +47,43 @@ import android.view.RemoteAnimationTarget;
|
||||
public class RemoteAnimationAdapterCompat {
|
||||
|
||||
private final RemoteAnimationAdapter mWrapped;
|
||||
private final RemoteTransitionCompat mRemoteTransition;
|
||||
|
||||
public RemoteAnimationAdapterCompat(RemoteAnimationRunnerCompat runner, long duration,
|
||||
long statusBarTransitionDelay) {
|
||||
mWrapped = new RemoteAnimationAdapter(wrapRemoteAnimationRunner(runner), duration,
|
||||
statusBarTransitionDelay);
|
||||
mRemoteTransition = buildRemoteTransition(runner);
|
||||
}
|
||||
|
||||
RemoteAnimationAdapter getWrapped() {
|
||||
return mWrapped;
|
||||
}
|
||||
|
||||
/** Helper to just build a remote transition. Use this if the legacy adapter isn't needed. */
|
||||
public static RemoteTransitionCompat buildRemoteTransition(RemoteAnimationRunnerCompat runner) {
|
||||
return new RemoteTransitionCompat(wrapRemoteTransition(runner));
|
||||
}
|
||||
|
||||
public RemoteTransitionCompat getRemoteTransition() {
|
||||
return mRemoteTransition;
|
||||
}
|
||||
|
||||
private static IRemoteAnimationRunner.Stub wrapRemoteAnimationRunner(
|
||||
final RemoteAnimationRunnerCompat remoteAnimationAdapter) {
|
||||
return new IRemoteAnimationRunner.Stub() {
|
||||
@Override
|
||||
public void onAnimationStart(RemoteAnimationTarget[] apps,
|
||||
public void onAnimationStart(@TransitionOldType int transit,
|
||||
RemoteAnimationTarget[] apps,
|
||||
RemoteAnimationTarget[] wallpapers,
|
||||
RemoteAnimationTarget[] nonApps,
|
||||
final IRemoteAnimationFinishedCallback finishedCallback) {
|
||||
final RemoteAnimationTargetCompat[] appsCompat =
|
||||
RemoteAnimationTargetCompat.wrap(apps);
|
||||
final RemoteAnimationTargetCompat[] wallpapersCompat =
|
||||
RemoteAnimationTargetCompat.wrap(wallpapers);
|
||||
final RemoteAnimationTargetCompat[] nonAppsCompat =
|
||||
RemoteAnimationTargetCompat.wrap(nonApps);
|
||||
final Runnable animationFinishedCallback = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -62,8 +95,8 @@ public class RemoteAnimationAdapterCompat {
|
||||
}
|
||||
}
|
||||
};
|
||||
remoteAnimationAdapter.onAnimationStart(appsCompat, wallpapersCompat,
|
||||
animationFinishedCallback);
|
||||
remoteAnimationAdapter.onAnimationStart(transit, appsCompat, wallpapersCompat,
|
||||
nonAppsCompat, animationFinishedCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,4 +105,182 @@ public class RemoteAnimationAdapterCompat {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class CounterRotator {
|
||||
SurfaceControl mSurface = null;
|
||||
ArrayList<SurfaceControl> mRotateChildren = null;
|
||||
|
||||
void setup(SurfaceControl.Transaction t, SurfaceControl parent, int rotateDelta,
|
||||
float displayW, float displayH) {
|
||||
if (rotateDelta == 0) return;
|
||||
mRotateChildren = new ArrayList<>();
|
||||
// We want to counter-rotate, so subtract from 4
|
||||
rotateDelta = 4 - (rotateDelta + 4) % 4;
|
||||
mSurface = new SurfaceControl.Builder()
|
||||
.setName("Transition Unrotate")
|
||||
.setContainerLayer()
|
||||
.setParent(parent)
|
||||
.build();
|
||||
// column-major
|
||||
if (rotateDelta == 1) {
|
||||
t.setMatrix(mSurface, 0, 1, -1, 0);
|
||||
t.setPosition(mSurface, displayW, 0);
|
||||
} else if (rotateDelta == 2) {
|
||||
t.setMatrix(mSurface, -1, 0, 0, -1);
|
||||
t.setPosition(mSurface, displayW, displayH);
|
||||
} else if (rotateDelta == 3) {
|
||||
t.setMatrix(mSurface, 0, -1, 1, 0);
|
||||
t.setPosition(mSurface, 0, displayH);
|
||||
}
|
||||
t.show(mSurface);
|
||||
}
|
||||
|
||||
void addChild(SurfaceControl.Transaction t, SurfaceControl child) {
|
||||
if (mSurface == null) return;
|
||||
t.reparent(child, mSurface);
|
||||
mRotateChildren.add(child);
|
||||
}
|
||||
|
||||
void cleanUp(SurfaceControl rootLeash) {
|
||||
if (mSurface == null) return;
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
for (int i = mRotateChildren.size() - 1; i >= 0; --i) {
|
||||
t.reparent(mRotateChildren.get(i), rootLeash);
|
||||
}
|
||||
t.remove(mSurface);
|
||||
t.apply();
|
||||
}
|
||||
}
|
||||
|
||||
private static IRemoteTransition.Stub wrapRemoteTransition(
|
||||
final RemoteAnimationRunnerCompat remoteAnimationAdapter) {
|
||||
return new IRemoteTransition.Stub() {
|
||||
@Override
|
||||
public void startAnimation(IBinder token, TransitionInfo info,
|
||||
SurfaceControl.Transaction t,
|
||||
IRemoteTransitionFinishedCallback finishCallback) {
|
||||
final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
|
||||
final RemoteAnimationTargetCompat[] appsCompat =
|
||||
RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap);
|
||||
final RemoteAnimationTargetCompat[] wallpapersCompat =
|
||||
RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap);
|
||||
// TODO(bc-unlock): Build wrapped object for non-apps target.
|
||||
final RemoteAnimationTargetCompat[] nonAppsCompat =
|
||||
new RemoteAnimationTargetCompat[0];
|
||||
|
||||
// TODO(b/177438007): Move this set-up logic into launcher's animation impl.
|
||||
boolean isReturnToHome = false;
|
||||
TransitionInfo.Change launcherTask = null;
|
||||
TransitionInfo.Change wallpaper = null;
|
||||
int launcherLayer = 0;
|
||||
int rotateDelta = 0;
|
||||
float displayW = 0;
|
||||
float displayH = 0;
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (change.getTaskInfo() != null
|
||||
&& change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME) {
|
||||
isReturnToHome = change.getMode() == TRANSIT_OPEN
|
||||
|| change.getMode() == TRANSIT_TO_FRONT;
|
||||
launcherTask = change;
|
||||
launcherLayer = info.getChanges().size() - i;
|
||||
} else if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
|
||||
wallpaper = change;
|
||||
}
|
||||
if (change.getParent() == null && change.getEndRotation() >= 0
|
||||
&& change.getEndRotation() != change.getStartRotation()) {
|
||||
rotateDelta = change.getEndRotation() - change.getStartRotation();
|
||||
displayW = change.getEndAbsBounds().width();
|
||||
displayH = change.getEndAbsBounds().height();
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare for rotation if there is one
|
||||
final CounterRotator counterLauncher = new CounterRotator();
|
||||
final CounterRotator counterWallpaper = new CounterRotator();
|
||||
if (launcherTask != null && rotateDelta != 0 && launcherTask.getParent() != null) {
|
||||
counterLauncher.setup(t, info.getChange(launcherTask.getParent()).getLeash(),
|
||||
rotateDelta, displayW, displayH);
|
||||
if (counterLauncher.mSurface != null) {
|
||||
t.setLayer(counterLauncher.mSurface, launcherLayer);
|
||||
}
|
||||
}
|
||||
|
||||
if (isReturnToHome) {
|
||||
if (counterLauncher.mSurface != null) {
|
||||
t.setLayer(counterLauncher.mSurface, info.getChanges().size() * 3);
|
||||
}
|
||||
// Need to "boost" the closing things since that's what launcher expects.
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
final SurfaceControl leash = leashMap.get(change.getLeash());
|
||||
final int mode = info.getChanges().get(i).getMode();
|
||||
// Only deal with independent layers
|
||||
if (!TransitionInfo.isIndependent(change, info)) continue;
|
||||
if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
|
||||
t.setLayer(leash, info.getChanges().size() * 3 - i);
|
||||
counterLauncher.addChild(t, leash);
|
||||
}
|
||||
}
|
||||
// Make wallpaper visible immediately since launcher apparently won't do this.
|
||||
for (int i = wallpapersCompat.length - 1; i >= 0; --i) {
|
||||
t.show(wallpapersCompat[i].leash.getSurfaceControl());
|
||||
t.setAlpha(wallpapersCompat[i].leash.getSurfaceControl(), 1.f);
|
||||
}
|
||||
} else {
|
||||
if (launcherTask != null) {
|
||||
counterLauncher.addChild(t, leashMap.get(launcherTask.getLeash()));
|
||||
}
|
||||
if (wallpaper != null && rotateDelta != 0 && wallpaper.getParent() != null) {
|
||||
counterWallpaper.setup(t, info.getChange(wallpaper.getParent()).getLeash(),
|
||||
rotateDelta, displayW, displayH);
|
||||
if (counterWallpaper.mSurface != null) {
|
||||
t.setLayer(counterWallpaper.mSurface, -1);
|
||||
counterWallpaper.addChild(t, leashMap.get(wallpaper.getLeash()));
|
||||
}
|
||||
}
|
||||
}
|
||||
t.apply();
|
||||
|
||||
final Runnable animationFinishedCallback = new Runnable() {
|
||||
@Override
|
||||
@SuppressLint("NewApi")
|
||||
public void run() {
|
||||
try {
|
||||
counterLauncher.cleanUp(info.getRootLeash());
|
||||
counterWallpaper.cleanUp(info.getRootLeash());
|
||||
// Release surface references now. This is apparently to free GPU
|
||||
// memory while doing quick operations (eg. during CTS).
|
||||
for (int i = 0; i < info.getChanges().size(); ++i) {
|
||||
info.getChanges().get(i).getLeash().release();
|
||||
}
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
for (int i = 0; i < leashMap.size(); ++i) {
|
||||
if (leashMap.keyAt(i) == leashMap.valueAt(i)) continue;
|
||||
t.remove(leashMap.valueAt(i));
|
||||
}
|
||||
t.apply();
|
||||
finishCallback.onTransitionFinished(null /* wct */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
|
||||
+ " finished callback", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
// TODO(bc-unlcok): Pass correct transit type.
|
||||
remoteAnimationAdapter.onAnimationStart(
|
||||
TRANSIT_OLD_NONE,
|
||||
appsCompat, wallpapersCompat, nonAppsCompat,
|
||||
animationFinishedCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeAnimation(IBinder token, TransitionInfo info,
|
||||
SurfaceControl.Transaction t, IBinder mergeTarget,
|
||||
IRemoteTransitionFinishedCallback finishCallback) {
|
||||
// TODO: hook up merge to recents onTaskAppeared if applicable. Until then, ignore
|
||||
// any incoming merges.
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+5
-2
@@ -16,8 +16,11 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.view.WindowManager;
|
||||
|
||||
public interface RemoteAnimationRunnerCompat {
|
||||
void onAnimationStart(RemoteAnimationTargetCompat[] apps,
|
||||
RemoteAnimationTargetCompat[] wallpapers, Runnable finishedCallback);
|
||||
void onAnimationStart(@WindowManager.TransitionOldType int transit,
|
||||
RemoteAnimationTargetCompat[] apps, RemoteAnimationTargetCompat[] wallpapers,
|
||||
RemoteAnimationTargetCompat[] nonApps, Runnable finishedCallback);
|
||||
void onAnimationCancelled();
|
||||
}
|
||||
+177
-4
@@ -16,11 +16,28 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
|
||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
|
||||
import static android.window.TransitionInfo.FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @see RemoteAnimationTarget
|
||||
@@ -29,6 +46,7 @@ public class RemoteAnimationTargetCompat {
|
||||
|
||||
public static final int MODE_OPENING = RemoteAnimationTarget.MODE_OPENING;
|
||||
public static final int MODE_CLOSING = RemoteAnimationTarget.MODE_CLOSING;
|
||||
public static final int MODE_CHANGING = RemoteAnimationTarget.MODE_CHANGING;
|
||||
public final int mode;
|
||||
|
||||
public static final int ACTIVITY_TYPE_UNDEFINED = WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
@@ -49,6 +67,9 @@ public class RemoteAnimationTargetCompat {
|
||||
public final Rect screenSpaceBounds;
|
||||
public final boolean isNotInRecents;
|
||||
public final Rect contentInsets;
|
||||
public final ActivityManager.RunningTaskInfo taskInfo;
|
||||
public final int rotationChange;
|
||||
public final int windowType;
|
||||
|
||||
private final SurfaceControl mStartLeash;
|
||||
|
||||
@@ -66,19 +87,171 @@ public class RemoteAnimationTargetCompat {
|
||||
isNotInRecents = app.isNotInRecents;
|
||||
contentInsets = app.contentInsets;
|
||||
activityType = app.windowConfiguration.getActivityType();
|
||||
taskInfo = app.taskInfo;
|
||||
rotationChange = 0;
|
||||
|
||||
mStartLeash = app.startLeash;
|
||||
windowType = app.windowType;
|
||||
}
|
||||
|
||||
private static int newModeToLegacyMode(int newMode) {
|
||||
switch (newMode) {
|
||||
case WindowManager.TRANSIT_OPEN:
|
||||
case WindowManager.TRANSIT_TO_FRONT:
|
||||
return MODE_OPENING;
|
||||
case WindowManager.TRANSIT_CLOSE:
|
||||
case WindowManager.TRANSIT_TO_BACK:
|
||||
return MODE_CLOSING;
|
||||
default:
|
||||
return 2; // MODE_CHANGING
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Almost a copy of Transitions#setupStartState.
|
||||
* TODO: remove when there is proper cross-process transaction sync.
|
||||
*/
|
||||
@SuppressLint("NewApi")
|
||||
private static void setupLeash(@NonNull SurfaceControl leash,
|
||||
@NonNull TransitionInfo.Change change, int layer,
|
||||
@NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t) {
|
||||
boolean isOpening = info.getType() == TRANSIT_OPEN || info.getType() == TRANSIT_TO_FRONT;
|
||||
// Put animating stuff above this line and put static stuff below it.
|
||||
int zSplitLine = info.getChanges().size();
|
||||
// changes should be ordered top-to-bottom in z
|
||||
final int mode = change.getMode();
|
||||
|
||||
// Don't move anything that isn't independent within its parents
|
||||
if (!TransitionInfo.isIndependent(change, info)) {
|
||||
if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT || mode == TRANSIT_CHANGE) {
|
||||
t.show(leash);
|
||||
t.setPosition(leash, change.getEndRelOffset().x, change.getEndRelOffset().y);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasParent = change.getParent() != null;
|
||||
|
||||
if (!hasParent) {
|
||||
t.reparent(leash, info.getRootLeash());
|
||||
t.setPosition(leash, change.getStartAbsBounds().left - info.getRootOffset().x,
|
||||
change.getStartAbsBounds().top - info.getRootOffset().y);
|
||||
}
|
||||
t.show(leash);
|
||||
// Put all the OPEN/SHOW on top
|
||||
if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
|
||||
if (isOpening) {
|
||||
t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
|
||||
if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
|
||||
// if transferred, it should be left visible.
|
||||
t.setAlpha(leash, 0.f);
|
||||
}
|
||||
} else {
|
||||
// put on bottom and leave it visible
|
||||
t.setLayer(leash, zSplitLine - layer);
|
||||
}
|
||||
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
|
||||
if (isOpening) {
|
||||
// put on bottom and leave visible
|
||||
t.setLayer(leash, zSplitLine - layer);
|
||||
} else {
|
||||
// put on top
|
||||
t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
|
||||
}
|
||||
} else { // CHANGE
|
||||
t.setLayer(leash, zSplitLine + info.getChanges().size() - layer);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
private static SurfaceControl createLeash(TransitionInfo info, TransitionInfo.Change change,
|
||||
int order, SurfaceControl.Transaction t) {
|
||||
// TODO: once we can properly sync transactions across process, then get rid of this leash.
|
||||
if (change.getParent() != null && (change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
|
||||
// Special case for wallpaper atm. Normally these are left alone; but, a quirk of
|
||||
// making leashes means we have to handle them specially.
|
||||
return change.getLeash();
|
||||
}
|
||||
SurfaceControl leashSurface = new SurfaceControl.Builder()
|
||||
.setName(change.getLeash().toString() + "_transition-leash")
|
||||
.setContainerLayer().setParent(change.getParent() == null ? info.getRootLeash()
|
||||
: info.getChange(change.getParent()).getLeash()).build();
|
||||
// Copied Transitions setup code (which expects bottom-to-top order, so we swap here)
|
||||
setupLeash(leashSurface, change, info.getChanges().size() - order, info, t);
|
||||
t.reparent(change.getLeash(), leashSurface);
|
||||
t.setAlpha(change.getLeash(), 1.0f);
|
||||
t.show(change.getLeash());
|
||||
t.setPosition(change.getLeash(), 0, 0);
|
||||
t.setLayer(change.getLeash(), 0);
|
||||
return leashSurface;
|
||||
}
|
||||
|
||||
public RemoteAnimationTargetCompat(TransitionInfo.Change change, int order,
|
||||
TransitionInfo info, SurfaceControl.Transaction t) {
|
||||
taskId = change.getTaskInfo() != null ? change.getTaskInfo().taskId : -1;
|
||||
mode = newModeToLegacyMode(change.getMode());
|
||||
|
||||
// TODO: once we can properly sync transactions across process, then get rid of this leash.
|
||||
leash = new SurfaceControlCompat(createLeash(info, change, order, t));
|
||||
|
||||
isTranslucent = (change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0
|
||||
|| (change.getFlags() & TransitionInfo.FLAG_SHOW_WALLPAPER) != 0;
|
||||
clipRect = null;
|
||||
position = null;
|
||||
localBounds = new Rect(change.getEndAbsBounds());
|
||||
localBounds.offsetTo(change.getEndRelOffset().x, change.getEndRelOffset().y);
|
||||
sourceContainerBounds = null;
|
||||
screenSpaceBounds = new Rect(change.getEndAbsBounds());
|
||||
prefixOrderIndex = order;
|
||||
// TODO(shell-transitions): I guess we need to send content insets? evaluate how its used.
|
||||
contentInsets = new Rect(0, 0, 0, 0);
|
||||
if (change.getTaskInfo() != null) {
|
||||
isNotInRecents = !change.getTaskInfo().isRunning;
|
||||
activityType = change.getTaskInfo().getActivityType();
|
||||
} else {
|
||||
isNotInRecents = true;
|
||||
activityType = ACTIVITY_TYPE_UNDEFINED;
|
||||
}
|
||||
taskInfo = change.getTaskInfo();
|
||||
mStartLeash = null;
|
||||
rotationChange = change.getEndRotation() - change.getStartRotation();
|
||||
windowType = INVALID_WINDOW_TYPE;
|
||||
}
|
||||
|
||||
public static RemoteAnimationTargetCompat[] wrap(RemoteAnimationTarget[] apps) {
|
||||
final RemoteAnimationTargetCompat[] appsCompat =
|
||||
new RemoteAnimationTargetCompat[apps != null ? apps.length : 0];
|
||||
for (int i = 0; i < apps.length; i++) {
|
||||
final int length = apps != null ? apps.length : 0;
|
||||
final RemoteAnimationTargetCompat[] appsCompat = new RemoteAnimationTargetCompat[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
appsCompat[i] = new RemoteAnimationTargetCompat(apps[i]);
|
||||
}
|
||||
return appsCompat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a TransitionInfo object as an array of old-style targets
|
||||
*
|
||||
* @param wallpapers If true, this will return wallpaper targets; otherwise it returns
|
||||
* non-wallpaper targets.
|
||||
* @param leashMap Temporary map of change leash -> launcher leash. Is an output, so should be
|
||||
* populated by this function. If null, it is ignored.
|
||||
*/
|
||||
public static RemoteAnimationTargetCompat[] wrap(TransitionInfo info, boolean wallpapers,
|
||||
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
|
||||
final ArrayList<RemoteAnimationTargetCompat> out = new ArrayList<>();
|
||||
for (int i = 0; i < info.getChanges().size(); i++) {
|
||||
boolean changeIsWallpaper =
|
||||
(info.getChanges().get(i).getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0;
|
||||
if (wallpapers != changeIsWallpaper) continue;
|
||||
out.add(new RemoteAnimationTargetCompat(info.getChanges().get(i),
|
||||
info.getChanges().size() - i, info, t));
|
||||
if (leashMap == null) continue;
|
||||
leashMap.put(info.getChanges().get(i).getLeash(),
|
||||
out.get(out.size() - 1).leash.mSurfaceControl);
|
||||
}
|
||||
return out.toArray(new RemoteAnimationTargetCompat[out.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SurfaceControl#release()
|
||||
*/
|
||||
@@ -88,4 +261,4 @@ public class RemoteAnimationTargetCompat {
|
||||
mStartLeash.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-17
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,19 +16,4 @@
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* Wraps a context to expose some methods for launcher to call.
|
||||
*/
|
||||
public class ContextCompat {
|
||||
private final Context mWrapped;
|
||||
|
||||
public ContextCompat(Context context) {
|
||||
mWrapped = context;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return mWrapped.getUserId();
|
||||
}
|
||||
}
|
||||
parcelable RemoteTransitionCompat;
|
||||
@@ -0,0 +1,465 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcelable;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.IRecentsAnimationController;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.IRemoteTransition;
|
||||
import android.window.IRemoteTransitionFinishedCallback;
|
||||
import android.window.PictureInPictureSurfaceTransaction;
|
||||
import android.window.TransitionFilter;
|
||||
import android.window.TransitionInfo;
|
||||
import android.window.WindowContainerToken;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.DataClass;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Wrapper to expose RemoteTransition (shell transitions) to Launcher.
|
||||
*
|
||||
* @see IRemoteTransition
|
||||
* @see TransitionFilter
|
||||
*/
|
||||
@DataClass
|
||||
public class RemoteTransitionCompat implements Parcelable {
|
||||
private static final String TAG = "RemoteTransitionCompat";
|
||||
|
||||
@NonNull final IRemoteTransition mTransition;
|
||||
@Nullable TransitionFilter mFilter = null;
|
||||
|
||||
RemoteTransitionCompat(IRemoteTransition transition) {
|
||||
mTransition = transition;
|
||||
}
|
||||
|
||||
public RemoteTransitionCompat(@NonNull RemoteTransitionRunner runner,
|
||||
@NonNull Executor executor) {
|
||||
mTransition = new IRemoteTransition.Stub() {
|
||||
@Override
|
||||
public void startAnimation(IBinder transition, TransitionInfo info,
|
||||
SurfaceControl.Transaction t,
|
||||
IRemoteTransitionFinishedCallback finishedCallback) {
|
||||
final Runnable finishAdapter = () -> {
|
||||
try {
|
||||
finishedCallback.onTransitionFinished(null /* wct */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to call transition finished callback", e);
|
||||
}
|
||||
};
|
||||
executor.execute(() -> runner.startAnimation(transition, info, t, finishAdapter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeAnimation(IBinder transition, TransitionInfo info,
|
||||
SurfaceControl.Transaction t, IBinder mergeTarget,
|
||||
IRemoteTransitionFinishedCallback finishedCallback) {
|
||||
final Runnable finishAdapter = () -> {
|
||||
try {
|
||||
finishedCallback.onTransitionFinished(null /* wct */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to call transition finished callback", e);
|
||||
}
|
||||
};
|
||||
executor.execute(() -> runner.mergeAnimation(transition, info, t, mergeTarget,
|
||||
finishAdapter));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Constructor specifically for recents animation */
|
||||
public RemoteTransitionCompat(RecentsAnimationListener recents,
|
||||
RecentsAnimationControllerCompat controller) {
|
||||
mTransition = new IRemoteTransition.Stub() {
|
||||
final RecentsControllerWrap mRecentsSession = new RecentsControllerWrap();
|
||||
IBinder mToken = null;
|
||||
|
||||
@Override
|
||||
public void startAnimation(IBinder transition, TransitionInfo info,
|
||||
SurfaceControl.Transaction t,
|
||||
IRemoteTransitionFinishedCallback finishedCallback) {
|
||||
final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
|
||||
final RemoteAnimationTargetCompat[] apps =
|
||||
RemoteAnimationTargetCompat.wrap(info, false /* wallpapers */, t, leashMap);
|
||||
final RemoteAnimationTargetCompat[] wallpapers =
|
||||
RemoteAnimationTargetCompat.wrap(info, true /* wallpapers */, t, leashMap);
|
||||
// TODO(b/177438007): Move this set-up logic into launcher's animation impl.
|
||||
mToken = transition;
|
||||
// This transition is for opening recents, so recents is on-top. We want to draw
|
||||
// the current going-away task on top of recents, though, so move it to front
|
||||
WindowContainerToken pausingTask = null;
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
|
||||
t.setLayer(leashMap.get(change.getLeash()),
|
||||
info.getChanges().size() * 3 - i);
|
||||
if (change.getTaskInfo() != null) {
|
||||
pausingTask = change.getTaskInfo().token;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Also make all the wallpapers opaque since we want the visible from the start
|
||||
for (int i = wallpapers.length - 1; i >= 0; --i) {
|
||||
t.setAlpha(wallpapers[i].leash.mSurfaceControl, 1);
|
||||
}
|
||||
t.apply();
|
||||
mRecentsSession.setup(controller, info, finishedCallback, pausingTask,
|
||||
leashMap);
|
||||
recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
|
||||
new Rect());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeAnimation(IBinder transition, TransitionInfo info,
|
||||
SurfaceControl.Transaction t, IBinder mergeTarget,
|
||||
IRemoteTransitionFinishedCallback finishedCallback) {
|
||||
if (!mergeTarget.equals(mToken)) return;
|
||||
if (!mRecentsSession.merge(info, t, recents)) return;
|
||||
try {
|
||||
finishedCallback.onTransitionFinished(null /* wct */);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error merging transition.", e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** Adds a filter check that restricts this remote transition to home open transitions. */
|
||||
public void addHomeOpenCheck() {
|
||||
if (mFilter == null) {
|
||||
mFilter = new TransitionFilter();
|
||||
}
|
||||
mFilter.mRequirements =
|
||||
new TransitionFilter.Requirement[]{new TransitionFilter.Requirement()};
|
||||
mFilter.mRequirements[0].mActivityType = ACTIVITY_TYPE_HOME;
|
||||
mFilter.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT};
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to hook up parts of recents animation to shell transition.
|
||||
* TODO(b/177438007): Remove this once Launcher handles shell transitions directly.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
|
||||
private RecentsAnimationControllerCompat mWrapped = null;
|
||||
private IRemoteTransitionFinishedCallback mFinishCB = null;
|
||||
private WindowContainerToken mPausingTask = null;
|
||||
private TransitionInfo mInfo = null;
|
||||
private SurfaceControl mOpeningLeash = null;
|
||||
private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
|
||||
|
||||
void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
|
||||
IRemoteTransitionFinishedCallback finishCB, WindowContainerToken pausingTask,
|
||||
ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
|
||||
if (mInfo != null) {
|
||||
throw new IllegalStateException("Trying to run a new recents animation while"
|
||||
+ " recents is already active.");
|
||||
}
|
||||
mWrapped = wrapped;
|
||||
mInfo = info;
|
||||
mFinishCB = finishCB;
|
||||
mPausingTask = pausingTask;
|
||||
mLeashMap = leashMap;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
boolean merge(TransitionInfo info, SurfaceControl.Transaction t,
|
||||
RecentsAnimationListener recents) {
|
||||
TransitionInfo.Change openingTask = null;
|
||||
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(i);
|
||||
if (change.getMode() == TRANSIT_OPEN || change.getMode() == TRANSIT_TO_FRONT) {
|
||||
if (change.getTaskInfo() != null) {
|
||||
if (openingTask != null) {
|
||||
Log.w(TAG, " Expecting to merge a task-open, but got >1 opening "
|
||||
+ "tasks");
|
||||
}
|
||||
openingTask = change;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (openingTask == null) return false;
|
||||
mOpeningLeash = openingTask.getLeash();
|
||||
if (openingTask.getContainer().equals(mPausingTask)) {
|
||||
// In this case, we are "returning" to the already running app, so just consume
|
||||
// the merge and do nothing.
|
||||
return true;
|
||||
}
|
||||
// We are receiving a new opening task, so convert to onTaskAppeared.
|
||||
final int layer = mInfo.getChanges().size() * 3;
|
||||
final RemoteAnimationTargetCompat target = new RemoteAnimationTargetCompat(
|
||||
openingTask, layer, mInfo, t);
|
||||
mLeashMap.put(mOpeningLeash, target.leash.mSurfaceControl);
|
||||
t.reparent(target.leash.mSurfaceControl, mInfo.getRootLeash());
|
||||
t.setLayer(target.leash.mSurfaceControl, layer);
|
||||
t.hide(target.leash.mSurfaceControl);
|
||||
t.apply();
|
||||
recents.onTaskAppeared(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public ThumbnailData screenshotTask(int taskId) {
|
||||
return mWrapped != null ? mWrapped.screenshotTask(taskId) : null;
|
||||
}
|
||||
|
||||
@Override public void setInputConsumerEnabled(boolean enabled) {
|
||||
if (mWrapped != null) mWrapped.setInputConsumerEnabled(enabled);
|
||||
}
|
||||
|
||||
@Override public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
|
||||
if (mWrapped != null) mWrapped.setAnimationTargetsBehindSystemBars(behindSystemBars);
|
||||
}
|
||||
|
||||
@Override public void hideCurrentInputMethod() {
|
||||
mWrapped.hideCurrentInputMethod();
|
||||
}
|
||||
|
||||
@Override public void setFinishTaskTransaction(int taskId,
|
||||
PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
|
||||
if (mWrapped != null) {
|
||||
mWrapped.setFinishTaskTransaction(taskId, finishTransaction, overlay);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressLint("NewApi")
|
||||
public void finish(boolean toHome, boolean sendUserLeaveHint) {
|
||||
if (mFinishCB == null) {
|
||||
Log.e(TAG, "Duplicate call to finish", new RuntimeException());
|
||||
return;
|
||||
}
|
||||
if (mWrapped != null) mWrapped.finish(toHome, sendUserLeaveHint);
|
||||
try {
|
||||
if (!toHome && mPausingTask != null && mOpeningLeash == null) {
|
||||
// The gesture went back to opening the app rather than continuing with
|
||||
// recents, so end the transition by moving the app back to the top.
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.reorder(mPausingTask, true /* onTop */);
|
||||
mFinishCB.onTransitionFinished(wct);
|
||||
} else {
|
||||
if (mOpeningLeash != null) {
|
||||
// TODO: the launcher animation should handle this
|
||||
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
t.show(mOpeningLeash);
|
||||
t.setAlpha(mOpeningLeash, 1.f);
|
||||
t.apply();
|
||||
}
|
||||
mFinishCB.onTransitionFinished(null /* wct */);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e("RemoteTransitionCompat", "Failed to call animation finish callback", e);
|
||||
}
|
||||
// Release surface references now. This is apparently to free GPU
|
||||
// memory while doing quick operations (eg. during CTS).
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
for (int i = 0; i < mLeashMap.size(); ++i) {
|
||||
if (mLeashMap.keyAt(i) == mLeashMap.valueAt(i)) continue;
|
||||
t.remove(mLeashMap.valueAt(i));
|
||||
}
|
||||
t.apply();
|
||||
for (int i = 0; i < mInfo.getChanges().size(); ++i) {
|
||||
mInfo.getChanges().get(i).getLeash().release();
|
||||
}
|
||||
// Reset all members.
|
||||
mWrapped = null;
|
||||
mFinishCB = null;
|
||||
mPausingTask = null;
|
||||
mInfo = null;
|
||||
mOpeningLeash = null;
|
||||
mLeashMap = null;
|
||||
}
|
||||
|
||||
@Override public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) {
|
||||
if (mWrapped != null) mWrapped.setDeferCancelUntilNextTransition(defer, screenshot);
|
||||
}
|
||||
|
||||
@Override public void cleanupScreenshot() {
|
||||
if (mWrapped != null) mWrapped.cleanupScreenshot();
|
||||
}
|
||||
|
||||
@Override public void setWillFinishToHome(boolean willFinishToHome) {
|
||||
if (mWrapped != null) mWrapped.setWillFinishToHome(willFinishToHome);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IRecentsAnimationController#removeTask
|
||||
*/
|
||||
@Override public boolean removeTask(int taskId) {
|
||||
return mWrapped != null ? mWrapped.removeTask(taskId) : false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Code below generated by codegen v1.0.21.
|
||||
//
|
||||
// DO NOT MODIFY!
|
||||
// CHECKSTYLE:OFF Generated code
|
||||
//
|
||||
// To regenerate run:
|
||||
// $ codegen $ANDROID_BUILD_TOP/frameworks/base/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
|
||||
//
|
||||
// To exclude the generated code from IntelliJ auto-formatting enable (one-time):
|
||||
// Settings > Editor > Code Style > Formatter Control
|
||||
//@formatter:off
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull IRemoteTransition getTransition() {
|
||||
return mTransition;
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @Nullable TransitionFilter getFilter() {
|
||||
return mFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
|
||||
// You can override field parcelling by defining methods like:
|
||||
// void parcelFieldName(Parcel dest, int flags) { ... }
|
||||
|
||||
byte flg = 0;
|
||||
if (mFilter != null) flg |= 0x2;
|
||||
dest.writeByte(flg);
|
||||
dest.writeStrongInterface(mTransition);
|
||||
if (mFilter != null) dest.writeTypedObject(mFilter, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DataClass.Generated.Member
|
||||
public int describeContents() { return 0; }
|
||||
|
||||
/** @hide */
|
||||
@SuppressWarnings({"unchecked", "RedundantCast"})
|
||||
@DataClass.Generated.Member
|
||||
protected RemoteTransitionCompat(@NonNull android.os.Parcel in) {
|
||||
// You can override field unparcelling by defining methods like:
|
||||
// static FieldType unparcelFieldName(Parcel in) { ... }
|
||||
|
||||
byte flg = in.readByte();
|
||||
IRemoteTransition transition = IRemoteTransition.Stub.asInterface(in.readStrongBinder());
|
||||
TransitionFilter filter = (flg & 0x2) == 0 ? null : (TransitionFilter) in.readTypedObject(TransitionFilter.CREATOR);
|
||||
|
||||
this.mTransition = transition;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mTransition);
|
||||
this.mFilter = filter;
|
||||
|
||||
// onConstructed(); // You can define this method to get a callback
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public static final @NonNull Parcelable.Creator<RemoteTransitionCompat> CREATOR
|
||||
= new Parcelable.Creator<RemoteTransitionCompat>() {
|
||||
@Override
|
||||
public RemoteTransitionCompat[] newArray(int size) {
|
||||
return new RemoteTransitionCompat[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public RemoteTransitionCompat createFromParcel(@NonNull android.os.Parcel in) {
|
||||
return new RemoteTransitionCompat(in);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A builder for {@link RemoteTransitionCompat}
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@DataClass.Generated.Member
|
||||
public static class Builder {
|
||||
|
||||
private @NonNull IRemoteTransition mTransition;
|
||||
private @Nullable TransitionFilter mFilter;
|
||||
|
||||
private long mBuilderFieldsSet = 0L;
|
||||
|
||||
public Builder(
|
||||
@NonNull IRemoteTransition transition) {
|
||||
mTransition = transition;
|
||||
com.android.internal.util.AnnotationValidations.validate(
|
||||
NonNull.class, null, mTransition);
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull Builder setTransition(@NonNull IRemoteTransition value) {
|
||||
checkNotUsed();
|
||||
mBuilderFieldsSet |= 0x1;
|
||||
mTransition = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@DataClass.Generated.Member
|
||||
public @NonNull Builder setFilter(@NonNull TransitionFilter value) {
|
||||
checkNotUsed();
|
||||
mBuilderFieldsSet |= 0x2;
|
||||
mFilter = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds the instance. This builder should not be touched after calling this! */
|
||||
public @NonNull RemoteTransitionCompat build() {
|
||||
checkNotUsed();
|
||||
mBuilderFieldsSet |= 0x4; // Mark builder used
|
||||
|
||||
if ((mBuilderFieldsSet & 0x2) == 0) {
|
||||
mFilter = null;
|
||||
}
|
||||
RemoteTransitionCompat o = new RemoteTransitionCompat(mTransition);
|
||||
o.mFilter = this.mFilter;
|
||||
return o;
|
||||
}
|
||||
|
||||
private void checkNotUsed() {
|
||||
if ((mBuilderFieldsSet & 0x4) != 0) {
|
||||
throw new IllegalStateException(
|
||||
"This Builder should not be reused. Use a new Builder instance instead");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DataClass.Generated(
|
||||
time = 1606862689344L,
|
||||
codegenVersion = "1.0.21",
|
||||
sourceFile = "frameworks/base/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java",
|
||||
inputSignatures = "final @android.annotation.NonNull com.android.systemui.shared.system.IRemoteTransition mTransition\n @android.annotation.Nullable android.window.TransitionFilter mFilter\npublic void addHomeOpenCheck()\nclass RemoteTransitionCompat extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
|
||||
@Deprecated
|
||||
private void __metadata() {}
|
||||
|
||||
|
||||
//@formatter:on
|
||||
// End of generated code
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.os.IBinder;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
/** Interface for something that runs a remote transition animation. */
|
||||
public interface RemoteTransitionRunner {
|
||||
/**
|
||||
* Starts a transition animation. Once complete, the implementation should call
|
||||
* `finishCallback`.
|
||||
*/
|
||||
void startAnimation(IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
|
||||
Runnable finishCallback);
|
||||
|
||||
/**
|
||||
* Attempts to merge a transition into the currently-running animation. If merge is not
|
||||
* possible/supported, this should do nothing. Otherwise, the implementation should call
|
||||
* `finishCallback` immediately to indicate that it merged the transition.
|
||||
*
|
||||
* @param transition The transition that wants to be merged into the running animation.
|
||||
* @param mergeTarget The transition to merge into (that this runner is currently animating).
|
||||
*/
|
||||
default void mergeAnimation(IBinder transition, TransitionInfo info,
|
||||
SurfaceControl.Transaction t, IBinder mergeTarget, Runnable finishCallback) { }
|
||||
}
|
||||
+30
-27
@@ -47,6 +47,7 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
public static final int FLAG_BACKGROUND_BLUR_RADIUS = 1 << 5;
|
||||
public static final int FLAG_VISIBILITY = 1 << 6;
|
||||
public static final int FLAG_RELATIVE_LAYER = 1 << 7;
|
||||
public static final int FLAG_SHADOW_RADIUS = 1 << 8;
|
||||
|
||||
private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
|
||||
|
||||
@@ -64,7 +65,7 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
public SyncRtSurfaceTransactionApplierCompat(View targetView) {
|
||||
mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
|
||||
mBarrierSurfaceControl = mTargetViewRootImpl != null
|
||||
? mTargetViewRootImpl.getRenderSurfaceControl() : null;
|
||||
? mTargetViewRootImpl.getSurfaceControl() : null;
|
||||
|
||||
mApplyHandler = new Handler(new Callback() {
|
||||
@Override
|
||||
@@ -113,10 +114,13 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
for (int i = params.length - 1; i >= 0; i--) {
|
||||
SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams =
|
||||
params[i];
|
||||
t.deferTransactionUntil(surfaceParams.surface, mBarrierSurfaceControl, frame);
|
||||
surfaceParams.applyTo(t);
|
||||
}
|
||||
t.apply();
|
||||
if (mTargetViewRootImpl != null) {
|
||||
mTargetViewRootImpl.mergeWithNextTransaction(t, frame);
|
||||
} else {
|
||||
t.apply();
|
||||
}
|
||||
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||
Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
|
||||
.sendToTarget();
|
||||
@@ -196,6 +200,7 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
SurfaceControl relativeTo;
|
||||
int relativeLayer;
|
||||
boolean visible;
|
||||
float shadowRadius;
|
||||
|
||||
/**
|
||||
* @param surface The surface to modify.
|
||||
@@ -226,7 +231,7 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
* @return this Builder
|
||||
*/
|
||||
public Builder withMatrix(Matrix matrix) {
|
||||
this.matrix = matrix;
|
||||
this.matrix = new Matrix(matrix);
|
||||
flags |= FLAG_MATRIX;
|
||||
return this;
|
||||
}
|
||||
@@ -236,7 +241,7 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
* @return this Builder
|
||||
*/
|
||||
public Builder withWindowCrop(Rect windowCrop) {
|
||||
this.windowCrop = windowCrop;
|
||||
this.windowCrop = new Rect(windowCrop);
|
||||
flags |= FLAG_WINDOW_CROP;
|
||||
return this;
|
||||
}
|
||||
@@ -273,6 +278,16 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param radius the Radius for the shadows to apply to the surface.
|
||||
* @return this Builder
|
||||
*/
|
||||
public Builder withShadowRadius(float radius) {
|
||||
this.shadowRadius = radius;
|
||||
flags |= FLAG_SHADOW_RADIUS;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param radius the Radius for blur to apply to the background surfaces.
|
||||
* @return this Builder
|
||||
@@ -298,42 +313,26 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
*/
|
||||
public SurfaceParams build() {
|
||||
return new SurfaceParams(surface, flags, alpha, matrix, windowCrop, layer,
|
||||
relativeTo, relativeLayer, cornerRadius, backgroundBlurRadius, visible);
|
||||
relativeTo, relativeLayer, cornerRadius, backgroundBlurRadius, visible,
|
||||
shadowRadius);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs surface parameters to be applied when the current view state gets pushed to
|
||||
* RenderThread.
|
||||
*
|
||||
* @param surface The surface to modify.
|
||||
* @param alpha Alpha to apply.
|
||||
* @param matrix Matrix to apply.
|
||||
* @param windowCrop Crop to apply, only applied if not {@code null}
|
||||
*/
|
||||
public SurfaceParams(SurfaceControlCompat surface, float alpha, Matrix matrix,
|
||||
Rect windowCrop, int layer, SurfaceControl relativeTo, int relativeLayer,
|
||||
float cornerRadius) {
|
||||
this(surface.mSurfaceControl,
|
||||
FLAG_ALL & ~(FLAG_VISIBILITY | FLAG_BACKGROUND_BLUR_RADIUS), alpha,
|
||||
matrix, windowCrop, layer, relativeTo, relativeLayer, cornerRadius,
|
||||
0 /* backgroundBlurRadius */, true);
|
||||
}
|
||||
|
||||
private SurfaceParams(SurfaceControl surface, int flags, float alpha, Matrix matrix,
|
||||
Rect windowCrop, int layer, SurfaceControl relativeTo, int relativeLayer,
|
||||
float cornerRadius, int backgroundBlurRadius, boolean visible) {
|
||||
float cornerRadius, int backgroundBlurRadius, boolean visible, float shadowRadius) {
|
||||
this.flags = flags;
|
||||
this.surface = surface;
|
||||
this.alpha = alpha;
|
||||
this.matrix = new Matrix(matrix);
|
||||
this.windowCrop = windowCrop != null ? new Rect(windowCrop) : null;
|
||||
this.matrix = matrix;
|
||||
this.windowCrop = windowCrop;
|
||||
this.layer = layer;
|
||||
this.relativeTo = relativeTo;
|
||||
this.relativeLayer = relativeLayer;
|
||||
this.cornerRadius = cornerRadius;
|
||||
this.backgroundBlurRadius = backgroundBlurRadius;
|
||||
this.visible = visible;
|
||||
this.shadowRadius = shadowRadius;
|
||||
}
|
||||
|
||||
private final int flags;
|
||||
@@ -349,6 +348,7 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
public final SurfaceControl relativeTo;
|
||||
public final int relativeLayer;
|
||||
public final boolean visible;
|
||||
public final float shadowRadius;
|
||||
|
||||
public void applyTo(SurfaceControl.Transaction t) {
|
||||
if ((flags & FLAG_MATRIX) != 0) {
|
||||
@@ -379,6 +379,9 @@ public class SyncRtSurfaceTransactionApplierCompat {
|
||||
if ((flags & FLAG_RELATIVE_LAYER) != 0) {
|
||||
t.setRelativeLayer(surface, relativeTo, relativeLayer);
|
||||
}
|
||||
if ((flags & FLAG_SHADOW_RADIUS) != 0) {
|
||||
t.setShadowRadius(surface, shadowRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.TaskInfo;
|
||||
import android.content.ComponentName;
|
||||
|
||||
public class TaskInfoCompat {
|
||||
|
||||
public static int getUserId(TaskInfo info) {
|
||||
return info.userId;
|
||||
}
|
||||
|
||||
public static int getActivityType(TaskInfo info) {
|
||||
return info.configuration.windowConfiguration.getActivityType();
|
||||
}
|
||||
|
||||
public static int getWindowingMode(TaskInfo info) {
|
||||
return info.configuration.windowConfiguration.getWindowingMode();
|
||||
}
|
||||
|
||||
public static boolean supportsSplitScreenMultiWindow(TaskInfo info) {
|
||||
return info.supportsSplitScreenMultiWindow;
|
||||
}
|
||||
|
||||
public static ComponentName getTopActivity(TaskInfo info) {
|
||||
return info.topActivity;
|
||||
}
|
||||
|
||||
public static ActivityManager.TaskDescription getTaskDescription(TaskInfo info) {
|
||||
return info.taskDescription;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ package com.android.systemui.shared.system;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ITaskStackListener;
|
||||
import android.content.ComponentName;
|
||||
import android.os.IBinder;
|
||||
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
@@ -62,21 +61,6 @@ public abstract class TaskStackChangeListener {
|
||||
onActivityLaunchOnSecondaryDisplayRerouted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when contents are drawn for the first time on a display which can only contain one
|
||||
* task.
|
||||
*
|
||||
* @param displayId the id of the display on which contents are drawn.
|
||||
*/
|
||||
public void onSingleTaskDisplayDrawn(int displayId) { }
|
||||
|
||||
/**
|
||||
* Called when the last task is removed from a display which can only contain one task.
|
||||
*
|
||||
* @param displayId the id of the display from which the window is removed.
|
||||
*/
|
||||
public void onSingleTaskDisplayEmpty(int displayId) {}
|
||||
|
||||
public void onTaskProfileLocked(int taskId, int userId) { }
|
||||
public void onTaskCreated(int taskId, ComponentName componentName) { }
|
||||
public void onTaskRemoved(int taskId) { }
|
||||
@@ -95,7 +79,6 @@ public abstract class TaskStackChangeListener {
|
||||
public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
|
||||
|
||||
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
|
||||
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) { }
|
||||
|
||||
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) { }
|
||||
|
||||
@@ -117,4 +100,10 @@ public abstract class TaskStackChangeListener {
|
||||
|
||||
/** @see ITaskStackListener#onActivityRotation(int)*/
|
||||
public void onActivityRotation(int displayId) { }
|
||||
|
||||
/**
|
||||
* Called when the lock task mode changes. See ActivityManager#LOCK_TASK_MODE_* and
|
||||
* LockTaskController.
|
||||
*/
|
||||
public void onLockTaskModeChanged(int mode) { }
|
||||
}
|
||||
|
||||
+228
-233
@@ -17,18 +17,15 @@
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityManager.TaskSnapshot;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.IActivityManager;
|
||||
import android.app.TaskStackListener;
|
||||
import android.content.ComponentName;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Trace;
|
||||
import android.util.Log;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -39,211 +36,43 @@ import java.util.List;
|
||||
/**
|
||||
* Tracks all the task stack listeners
|
||||
*/
|
||||
public class TaskStackChangeListeners extends TaskStackListener {
|
||||
public class TaskStackChangeListeners {
|
||||
|
||||
private static final String TAG = TaskStackChangeListeners.class.getSimpleName();
|
||||
private static final TaskStackChangeListeners INSTANCE = new TaskStackChangeListeners();
|
||||
|
||||
private final Impl mImpl;
|
||||
|
||||
private TaskStackChangeListeners() {
|
||||
mImpl = new Impl(Looper.getMainLooper());
|
||||
}
|
||||
|
||||
public static TaskStackChangeListeners getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of {@link TaskStackChangeListener} registered from {@link #addListener}.
|
||||
* Registers a task stack listener with the system.
|
||||
* This should be called on the main thread.
|
||||
*/
|
||||
private final List<TaskStackChangeListener> mTaskStackListeners = new ArrayList<>();
|
||||
private final List<TaskStackChangeListener> mTmpListeners = new ArrayList<>();
|
||||
|
||||
private final Handler mHandler;
|
||||
private boolean mRegistered;
|
||||
|
||||
public TaskStackChangeListeners(Looper looper) {
|
||||
mHandler = new H(looper);
|
||||
}
|
||||
|
||||
public void addListener(IActivityManager am, TaskStackChangeListener listener) {
|
||||
synchronized (mTaskStackListeners) {
|
||||
mTaskStackListeners.add(listener);
|
||||
}
|
||||
if (!mRegistered) {
|
||||
// Register mTaskStackListener to IActivityManager only once if needed.
|
||||
try {
|
||||
ActivityTaskManager.getService().registerTaskStackListener(this);
|
||||
mRegistered = true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Failed to call registerTaskStackListener", e);
|
||||
}
|
||||
public void registerTaskStackListener(TaskStackChangeListener listener) {
|
||||
synchronized (mImpl) {
|
||||
mImpl.addListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(TaskStackChangeListener listener) {
|
||||
boolean isEmpty;
|
||||
synchronized (mTaskStackListeners) {
|
||||
mTaskStackListeners.remove(listener);
|
||||
isEmpty = mTaskStackListeners.isEmpty();
|
||||
}
|
||||
if (isEmpty && mRegistered) {
|
||||
// Unregister mTaskStackListener once we have no more listeners
|
||||
try {
|
||||
ActivityTaskManager.getService().unregisterTaskStackListener(this);
|
||||
mRegistered = false;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Failed to call unregisterTaskStackListener", e);
|
||||
}
|
||||
/**
|
||||
* Unregisters a task stack listener with the system.
|
||||
* This should be called on the main thread.
|
||||
*/
|
||||
public void unregisterTaskStackListener(TaskStackChangeListener listener) {
|
||||
synchronized (mImpl) {
|
||||
mImpl.removeListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskStackChanged() throws RemoteException {
|
||||
// Call the task changed callback for the non-ui thread listeners first. Copy to a set of
|
||||
// temp listeners so that we don't lock on mTaskStackListeners while calling all the
|
||||
// callbacks. This call is always on the same binder thread, so we can just synchronize
|
||||
// on the copying of the listener list.
|
||||
synchronized (mTaskStackListeners) {
|
||||
mTmpListeners.addAll(mTaskStackListeners);
|
||||
}
|
||||
for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
|
||||
mTmpListeners.get(i).onTaskStackChangedBackground();
|
||||
}
|
||||
mTmpListeners.clear();
|
||||
private static class Impl extends TaskStackListener implements Handler.Callback {
|
||||
|
||||
mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
|
||||
mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPinned(String packageName, int userId, int taskId, int stackId)
|
||||
throws RemoteException {
|
||||
mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_PINNED,
|
||||
new PinnedActivityInfo(packageName, userId, taskId, stackId)).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityUnpinned() throws RemoteException {
|
||||
mHandler.removeMessages(H.ON_ACTIVITY_UNPINNED);
|
||||
mHandler.sendEmptyMessage(H.ON_ACTIVITY_UNPINNED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
|
||||
boolean clearedTask, boolean wasVisible) throws RemoteException {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = task;
|
||||
args.argi1 = homeTaskVisible ? 1 : 0;
|
||||
args.argi2 = clearedTask ? 1 : 0;
|
||||
args.argi3 = wasVisible ? 1 : 0;
|
||||
mHandler.removeMessages(H.ON_ACTIVITY_RESTART_ATTEMPT);
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_RESTART_ATTEMPT, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityForcedResizable(String packageName, int taskId, int reason)
|
||||
throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDismissingDockedStack() throws RemoteException {
|
||||
mHandler.sendEmptyMessage(H.ON_ACTIVITY_DISMISSING_DOCKED_STACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo,
|
||||
int requestedDisplayId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED, requestedDisplayId,
|
||||
0 /* unused */,
|
||||
taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo,
|
||||
int requestedDisplayId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED,
|
||||
requestedDisplayId, 0 /* unused */, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskProfileLocked(int taskId, int userId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskCreated(int taskId, ComponentName componentName) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_CREATED, taskId, 0, componentName).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(int taskId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_REMOVED, taskId, 0).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskMovedToFront(RunningTaskInfo taskInfo)
|
||||
throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_MOVED_TO_FRONT, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_BACK_PRESSED_ON_TASK_ROOT, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation)
|
||||
throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE, taskId,
|
||||
requestedOrientation).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken)
|
||||
throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED, displayId, 0 /* unused */,
|
||||
activityToken).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSingleTaskDisplayDrawn(int displayId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_SINGLE_TASK_DISPLAY_DRAWN, displayId,
|
||||
0 /* unused */).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSingleTaskDisplayEmpty(int displayId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_SINGLE_TASK_DISPLAY_EMPTY, displayId,
|
||||
0 /* unused */).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskDisplayChanged(int taskId, int newDisplayId) throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_DISPLAY_CHANGED, taskId, newDisplayId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentTaskListUpdated() throws RemoteException {
|
||||
mHandler.obtainMessage(H.ON_TASK_LIST_UPDATED).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentTaskListFrozenChanged(boolean frozen) {
|
||||
mHandler.obtainMessage(H.ON_TASK_LIST_FROZEN_UNFROZEN, frozen ? 1 : 0, 0 /* unused */)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) {
|
||||
mHandler.obtainMessage(H.ON_TASK_DESCRIPTION_CHANGED, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRotation(int displayId) {
|
||||
mHandler.obtainMessage(H.ON_ACTIVITY_ROTATION, displayId, 0 /* unused */)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
private final class H extends Handler {
|
||||
private static final int ON_TASK_STACK_CHANGED = 1;
|
||||
private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
|
||||
private static final int ON_ACTIVITY_PINNED = 3;
|
||||
@@ -258,23 +87,199 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
private static final int ON_TASK_MOVED_TO_FRONT = 14;
|
||||
private static final int ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE = 15;
|
||||
private static final int ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED = 16;
|
||||
private static final int ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED = 17;
|
||||
private static final int ON_BACK_PRESSED_ON_TASK_ROOT = 18;
|
||||
private static final int ON_SINGLE_TASK_DISPLAY_DRAWN = 19;
|
||||
private static final int ON_TASK_DISPLAY_CHANGED = 20;
|
||||
private static final int ON_TASK_LIST_UPDATED = 21;
|
||||
private static final int ON_SINGLE_TASK_DISPLAY_EMPTY = 22;
|
||||
private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 23;
|
||||
private static final int ON_TASK_DESCRIPTION_CHANGED = 24;
|
||||
private static final int ON_ACTIVITY_ROTATION = 25;
|
||||
private static final int ON_BACK_PRESSED_ON_TASK_ROOT = 17;
|
||||
private static final int ON_TASK_DISPLAY_CHANGED = 18;
|
||||
private static final int ON_TASK_LIST_UPDATED = 19;
|
||||
private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 20;
|
||||
private static final int ON_TASK_DESCRIPTION_CHANGED = 21;
|
||||
private static final int ON_ACTIVITY_ROTATION = 22;
|
||||
private static final int ON_LOCK_TASK_MODE_CHANGED = 23;
|
||||
|
||||
/**
|
||||
* List of {@link TaskStackChangeListener} registered from {@link #addListener}.
|
||||
*/
|
||||
private final List<TaskStackChangeListener> mTaskStackListeners = new ArrayList<>();
|
||||
private final List<TaskStackChangeListener> mTmpListeners = new ArrayList<>();
|
||||
|
||||
public H(Looper looper) {
|
||||
super(looper);
|
||||
private final Handler mHandler;
|
||||
private boolean mRegistered;
|
||||
|
||||
Impl(Looper looper) {
|
||||
mHandler = new Handler(looper, this);
|
||||
}
|
||||
|
||||
public void addListener(TaskStackChangeListener listener) {
|
||||
synchronized (mTaskStackListeners) {
|
||||
mTaskStackListeners.add(listener);
|
||||
}
|
||||
if (!mRegistered) {
|
||||
// Register mTaskStackListener to IActivityManager only once if needed.
|
||||
try {
|
||||
ActivityTaskManager.getService().registerTaskStackListener(this);
|
||||
mRegistered = true;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Failed to call registerTaskStackListener", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeListener(TaskStackChangeListener listener) {
|
||||
boolean isEmpty;
|
||||
synchronized (mTaskStackListeners) {
|
||||
mTaskStackListeners.remove(listener);
|
||||
isEmpty = mTaskStackListeners.isEmpty();
|
||||
}
|
||||
if (isEmpty && mRegistered) {
|
||||
// Unregister mTaskStackListener once we have no more listeners
|
||||
try {
|
||||
ActivityTaskManager.getService().unregisterTaskStackListener(this);
|
||||
mRegistered = false;
|
||||
} catch (Exception e) {
|
||||
Log.w(TAG, "Failed to call unregisterTaskStackListener", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
public void onTaskStackChanged() {
|
||||
// Call the task changed callback for the non-ui thread listeners first. Copy to a set
|
||||
// of temp listeners so that we don't lock on mTaskStackListeners while calling all the
|
||||
// callbacks. This call is always on the same binder thread, so we can just synchronize
|
||||
// on the copying of the listener list.
|
||||
synchronized (mTaskStackListeners) {
|
||||
mTmpListeners.addAll(mTaskStackListeners);
|
||||
}
|
||||
for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
|
||||
mTmpListeners.get(i).onTaskStackChangedBackground();
|
||||
}
|
||||
mTmpListeners.clear();
|
||||
|
||||
mHandler.removeMessages(ON_TASK_STACK_CHANGED);
|
||||
mHandler.sendEmptyMessage(ON_TASK_STACK_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPinned(String packageName, int userId, int taskId, int stackId) {
|
||||
mHandler.removeMessages(ON_ACTIVITY_PINNED);
|
||||
mHandler.obtainMessage(ON_ACTIVITY_PINNED,
|
||||
new PinnedActivityInfo(packageName, userId, taskId, stackId)).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityUnpinned() {
|
||||
mHandler.removeMessages(ON_ACTIVITY_UNPINNED);
|
||||
mHandler.sendEmptyMessage(ON_ACTIVITY_UNPINNED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRestartAttempt(RunningTaskInfo task, boolean homeTaskVisible,
|
||||
boolean clearedTask, boolean wasVisible) {
|
||||
final SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = task;
|
||||
args.argi1 = homeTaskVisible ? 1 : 0;
|
||||
args.argi2 = clearedTask ? 1 : 0;
|
||||
args.argi3 = wasVisible ? 1 : 0;
|
||||
mHandler.removeMessages(ON_ACTIVITY_RESTART_ATTEMPT);
|
||||
mHandler.obtainMessage(ON_ACTIVITY_RESTART_ATTEMPT, args).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityForcedResizable(String packageName, int taskId, int reason) {
|
||||
mHandler.obtainMessage(ON_ACTIVITY_FORCED_RESIZABLE, taskId, reason, packageName)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDismissingDockedTask() {
|
||||
mHandler.sendEmptyMessage(ON_ACTIVITY_DISMISSING_DOCKED_STACK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityLaunchOnSecondaryDisplayFailed(RunningTaskInfo taskInfo,
|
||||
int requestedDisplayId) {
|
||||
mHandler.obtainMessage(ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED,
|
||||
requestedDisplayId,
|
||||
0 /* unused */,
|
||||
taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityLaunchOnSecondaryDisplayRerouted(RunningTaskInfo taskInfo,
|
||||
int requestedDisplayId) {
|
||||
mHandler.obtainMessage(ON_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED,
|
||||
requestedDisplayId, 0 /* unused */, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskProfileLocked(int taskId, int userId) {
|
||||
mHandler.obtainMessage(ON_TASK_PROFILE_LOCKED, taskId, userId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
|
||||
mHandler.obtainMessage(ON_TASK_SNAPSHOT_CHANGED, taskId, 0, snapshot).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskCreated(int taskId, ComponentName componentName) {
|
||||
mHandler.obtainMessage(ON_TASK_CREATED, taskId, 0, componentName).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(int taskId) {
|
||||
mHandler.obtainMessage(ON_TASK_REMOVED, taskId, 0).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskMovedToFront(RunningTaskInfo taskInfo) {
|
||||
mHandler.obtainMessage(ON_TASK_MOVED_TO_FRONT, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
|
||||
mHandler.obtainMessage(ON_BACK_PRESSED_ON_TASK_ROOT, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) {
|
||||
mHandler.obtainMessage(ON_ACTIVITY_REQUESTED_ORIENTATION_CHANGE, taskId,
|
||||
requestedOrientation).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskDisplayChanged(int taskId, int newDisplayId) {
|
||||
mHandler.obtainMessage(ON_TASK_DISPLAY_CHANGED, taskId, newDisplayId).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentTaskListUpdated() {
|
||||
mHandler.obtainMessage(ON_TASK_LIST_UPDATED).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentTaskListFrozenChanged(boolean frozen) {
|
||||
mHandler.obtainMessage(ON_TASK_LIST_FROZEN_UNFROZEN, frozen ? 1 : 0, 0 /* unused */)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) {
|
||||
mHandler.obtainMessage(ON_TASK_DESCRIPTION_CHANGED, taskInfo).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityRotation(int displayId) {
|
||||
mHandler.obtainMessage(ON_ACTIVITY_ROTATION, displayId, 0 /* unused */)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLockTaskModeChanged(int mode) {
|
||||
mHandler.obtainMessage(ON_LOCK_TASK_MODE_CHANGED, mode, 0 /* unused */).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
synchronized (mTaskStackListeners) {
|
||||
switch (msg.what) {
|
||||
case ON_TASK_STACK_CHANGED: {
|
||||
@@ -287,9 +292,10 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
}
|
||||
case ON_TASK_SNAPSHOT_CHANGED: {
|
||||
Trace.beginSection("onTaskSnapshotChanged");
|
||||
final TaskSnapshot snapshot = (TaskSnapshot) msg.obj;
|
||||
final ThumbnailData thumbnail = new ThumbnailData(snapshot);
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1,
|
||||
new ThumbnailData((TaskSnapshot) msg.obj));
|
||||
mTaskStackListeners.get(i).onTaskSnapshotChanged(msg.arg1, thumbnail);
|
||||
}
|
||||
Trace.endSection();
|
||||
break;
|
||||
@@ -298,7 +304,8 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
final PinnedActivityInfo info = (PinnedActivityInfo) msg.obj;
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onActivityPinned(
|
||||
info.mPackageName, info.mUserId, info.mTaskId, info.mStackId);
|
||||
info.mPackageName, info.mUserId, info.mTaskId,
|
||||
info.mStackId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -382,13 +389,6 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_SIZE_COMPAT_MODE_ACTIVITY_CHANGED: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onSizeCompatModeActivityChanged(
|
||||
msg.arg1, (IBinder) msg.obj);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_BACK_PRESSED_ON_TASK_ROOT: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onBackPressedOnTaskRoot(
|
||||
@@ -396,19 +396,6 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_SINGLE_TASK_DISPLAY_DRAWN: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onSingleTaskDisplayDrawn(msg.arg1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_SINGLE_TASK_DISPLAY_EMPTY: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onSingleTaskDisplayEmpty(
|
||||
msg.arg1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_TASK_DISPLAY_CHANGED: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onTaskDisplayChanged(msg.arg1, msg.arg2);
|
||||
@@ -423,7 +410,8 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
}
|
||||
case ON_TASK_LIST_FROZEN_UNFROZEN: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onRecentTaskListFrozenChanged(msg.arg1 != 0);
|
||||
mTaskStackListeners.get(i).onRecentTaskListFrozenChanged(
|
||||
msg.arg1 != 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -440,11 +428,18 @@ public class TaskStackChangeListeners extends TaskStackListener {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ON_LOCK_TASK_MODE_CHANGED: {
|
||||
for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
|
||||
mTaskStackListeners.get(i).onLockTaskModeChanged(msg.arg1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (msg.obj instanceof SomeArgs) {
|
||||
((SomeArgs) msg.obj).recycle();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.view.ThreadedRenderer;
|
||||
*/
|
||||
public class ThreadedRendererCompat {
|
||||
|
||||
public static int EGL_CONTEXT_PRIORITY_REALTIME_NV = 0x3357;
|
||||
public static int EGL_CONTEXT_PRIORITY_HIGH_IMG = 0x3101;
|
||||
public static int EGL_CONTEXT_PRIORITY_MEDIUM_IMG = 0x3102;
|
||||
public static int EGL_CONTEXT_PRIORITY_LOW_IMG = 0x3103;
|
||||
|
||||
@@ -65,6 +65,11 @@ public class TransactionCompat {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionCompat setOpaque(SurfaceControlCompat surfaceControl, boolean opaque) {
|
||||
mTransaction.setOpaque(surfaceControl.mSurfaceControl, opaque);
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionCompat setMatrix(SurfaceControlCompat surfaceControl, float dsdx, float dtdx,
|
||||
float dtdy, float dsdy) {
|
||||
mTransaction.setMatrix(surfaceControl.mSurfaceControl, dsdx, dtdx, dtdy, dsdy);
|
||||
@@ -92,34 +97,13 @@ public class TransactionCompat {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionCompat deferTransactionUntil(SurfaceControlCompat surfaceControl,
|
||||
SurfaceControl barrier, long frameNumber) {
|
||||
mTransaction.deferTransactionUntil(surfaceControl.mSurfaceControl, barrier,
|
||||
frameNumber);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public TransactionCompat setEarlyWakeup() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public TransactionCompat setColor(SurfaceControlCompat surfaceControl, float[] color) {
|
||||
mTransaction.setColor(surfaceControl.mSurfaceControl, color);
|
||||
return this;
|
||||
}
|
||||
|
||||
public static void deferTransactionUntil(Transaction t, SurfaceControl surfaceControl,
|
||||
SurfaceControl barrier, long frameNumber) {
|
||||
t.deferTransactionUntil(surfaceControl, barrier, frameNumber);
|
||||
}
|
||||
|
||||
public static void setRelativeLayer(Transaction t, SurfaceControl surfaceControl,
|
||||
SurfaceControl relativeTo, int z) {
|
||||
t.setRelativeLayer(surfaceControl, relativeTo, z);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static void setEarlyWakeup(Transaction t) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,10 +34,6 @@ public class ViewRootImplCompat {
|
||||
}
|
||||
|
||||
public SurfaceControl getRenderSurfaceControl() {
|
||||
return mViewRoot == null ? null : mViewRoot.getRenderSurfaceControl();
|
||||
}
|
||||
|
||||
public SurfaceControl getSurfaceControl() {
|
||||
return mViewRoot == null ? null : mViewRoot.getSurfaceControl();
|
||||
}
|
||||
|
||||
@@ -60,4 +56,12 @@ public class ViewRootImplCompat {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void mergeWithNextTransaction(SurfaceControl.Transaction t, long frame) {
|
||||
if (mViewRoot != null) {
|
||||
mViewRoot.mergeWithNextTransaction(t, frame);
|
||||
} else {
|
||||
t.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class ViewTreeObserverWrapper {
|
||||
|
||||
private static final HashMap<OnComputeInsetsListener, ViewTreeObserver>
|
||||
sListenerObserverMap = new HashMap<>();
|
||||
private static final HashMap<OnComputeInsetsListener, OnComputeInternalInsetsListener>
|
||||
sListenerInternalListenerMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Register a callback to be invoked when the invoked when it is time to compute the window's
|
||||
* insets.
|
||||
*
|
||||
* @param observer The observer to be added
|
||||
* @param listener The callback to add
|
||||
* @throws IllegalStateException If {@link ViewTreeObserver#isAlive()} returns false
|
||||
*/
|
||||
public static void addOnComputeInsetsListener(
|
||||
@NonNull ViewTreeObserver observer, @NonNull OnComputeInsetsListener listener) {
|
||||
final OnComputeInternalInsetsListener internalListener = internalInOutInfo -> {
|
||||
final InsetsInfo inOutInfo = new InsetsInfo();
|
||||
inOutInfo.contentInsets.set(internalInOutInfo.contentInsets);
|
||||
inOutInfo.visibleInsets.set(internalInOutInfo.visibleInsets);
|
||||
inOutInfo.touchableRegion.set(internalInOutInfo.touchableRegion);
|
||||
listener.onComputeInsets(inOutInfo);
|
||||
internalInOutInfo.contentInsets.set(inOutInfo.contentInsets);
|
||||
internalInOutInfo.visibleInsets.set(inOutInfo.visibleInsets);
|
||||
internalInOutInfo.touchableRegion.set(inOutInfo.touchableRegion);
|
||||
internalInOutInfo.setTouchableInsets(inOutInfo.mTouchableInsets);
|
||||
};
|
||||
sListenerObserverMap.put(listener, observer);
|
||||
sListenerInternalListenerMap.put(listener, internalListener);
|
||||
observer.addOnComputeInternalInsetsListener(internalListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a previously installed insets computation callback.
|
||||
*
|
||||
* @param victim The callback to remove
|
||||
* @throws IllegalStateException If {@link ViewTreeObserver#isAlive()} returns false
|
||||
* @see #addOnComputeInsetsListener(ViewTreeObserver, OnComputeInsetsListener)
|
||||
*/
|
||||
public static void removeOnComputeInsetsListener(@NonNull OnComputeInsetsListener victim) {
|
||||
final ViewTreeObserver observer = sListenerObserverMap.get(victim);
|
||||
final OnComputeInternalInsetsListener listener = sListenerInternalListenerMap.get(victim);
|
||||
if (observer != null && listener != null) {
|
||||
observer.removeOnComputeInternalInsetsListener(listener);
|
||||
}
|
||||
sListenerObserverMap.remove(victim);
|
||||
sListenerInternalListenerMap.remove(victim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when layout has
|
||||
* completed and the client can compute its interior insets.
|
||||
*/
|
||||
public interface OnComputeInsetsListener {
|
||||
/**
|
||||
* Callback method to be invoked when layout has completed and the
|
||||
* client can compute its interior insets.
|
||||
*
|
||||
* @param inoutInfo Should be filled in by the implementation with
|
||||
* the information about the insets of the window. This is called
|
||||
* with whatever values the previous OnComputeInsetsListener
|
||||
* returned, if there are multiple such listeners in the window.
|
||||
*/
|
||||
void onComputeInsets(InsetsInfo inoutInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters used with OnComputeInsetsListener.
|
||||
*/
|
||||
public final static class InsetsInfo {
|
||||
|
||||
/**
|
||||
* Offsets from the frame of the window at which the content of
|
||||
* windows behind it should be placed.
|
||||
*/
|
||||
public final Rect contentInsets = new Rect();
|
||||
|
||||
/**
|
||||
* Offsets from the frame of the window at which windows behind it
|
||||
* are visible.
|
||||
*/
|
||||
public final Rect visibleInsets = new Rect();
|
||||
|
||||
/**
|
||||
* Touchable region defined relative to the origin of the frame of the window.
|
||||
* Only used when {@link #setTouchableInsets(int)} is called with
|
||||
* the option {@link #TOUCHABLE_INSETS_REGION}.
|
||||
*/
|
||||
public final Region touchableRegion = new Region();
|
||||
|
||||
/**
|
||||
* Option for {@link #setTouchableInsets(int)}: the entire window frame
|
||||
* can be touched.
|
||||
*/
|
||||
public static final int TOUCHABLE_INSETS_FRAME =
|
||||
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
|
||||
|
||||
/**
|
||||
* Option for {@link #setTouchableInsets(int)}: the area inside of
|
||||
* the content insets can be touched.
|
||||
*/
|
||||
public static final int TOUCHABLE_INSETS_CONTENT =
|
||||
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
|
||||
|
||||
/**
|
||||
* Option for {@link #setTouchableInsets(int)}: the area inside of
|
||||
* the visible insets can be touched.
|
||||
*/
|
||||
public static final int TOUCHABLE_INSETS_VISIBLE =
|
||||
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
|
||||
|
||||
/**
|
||||
* Option for {@link #setTouchableInsets(int)}: the area inside of
|
||||
* the provided touchable region in {@link #touchableRegion} can be touched.
|
||||
*/
|
||||
public static final int TOUCHABLE_INSETS_REGION =
|
||||
ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
|
||||
|
||||
/**
|
||||
* Set which parts of the window can be touched: either
|
||||
* {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
|
||||
* {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}.
|
||||
*/
|
||||
public void setTouchableInsets(int val) {
|
||||
mTouchableInsets = val;
|
||||
}
|
||||
|
||||
int mTouchableInsets;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = contentInsets.hashCode();
|
||||
result = 31 * result + visibleInsets.hashCode();
|
||||
result = 31 * result + touchableRegion.hashCode();
|
||||
result = 31 * result + mTouchableInsets;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final InsetsInfo other = (InsetsInfo) o;
|
||||
return mTouchableInsets == other.mTouchableInsets &&
|
||||
contentInsets.equals(other.contentInsets) &&
|
||||
visibleInsets.equals(other.visibleInsets) &&
|
||||
touchableRegion.equals(other.touchableRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.systemui.shared.system;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RecordingCanvas;
|
||||
import android.view.View;
|
||||
import android.view.ViewRootImpl;
|
||||
import android.view.WindowCallbacks;
|
||||
|
||||
public class WindowCallbacksCompat {
|
||||
|
||||
private final WindowCallbacks mWindowCallbacks = new WindowCallbacks() {
|
||||
@Override
|
||||
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
|
||||
Rect stableInsets) {
|
||||
WindowCallbacksCompat.this.onWindowSizeIsChanging(newBounds, fullscreen, systemInsets,
|
||||
stableInsets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen,
|
||||
Rect systemInsets, Rect stableInsets, int resizeMode) {
|
||||
WindowCallbacksCompat.this.onWindowDragResizeStart(initialBounds, fullscreen,
|
||||
systemInsets, stableInsets, resizeMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowDragResizeEnd() {
|
||||
WindowCallbacksCompat.this.onWindowDragResizeEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) {
|
||||
return WindowCallbacksCompat.this.onContentDrawn(offsetX, offsetY, sizeX, sizeY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestDraw(boolean reportNextDraw) {
|
||||
WindowCallbacksCompat.this.onRequestDraw(reportNextDraw);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostDraw(RecordingCanvas canvas) {
|
||||
WindowCallbacksCompat.this.onPostDraw(canvas);
|
||||
}
|
||||
};
|
||||
|
||||
private final View mView;
|
||||
|
||||
public WindowCallbacksCompat(View view) {
|
||||
mView = view;
|
||||
}
|
||||
|
||||
public void onWindowSizeIsChanging(Rect newBounds, boolean fullscreen, Rect systemInsets,
|
||||
Rect stableInsets) { }
|
||||
|
||||
public void onWindowDragResizeStart(Rect initialBounds, boolean fullscreen, Rect systemInsets,
|
||||
Rect stableInsets, int resizeMode) { }
|
||||
|
||||
public void onWindowDragResizeEnd() { }
|
||||
|
||||
public boolean onContentDrawn(int offsetX, int offsetY, int sizeX, int sizeY) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onRequestDraw(boolean reportNextDraw) {
|
||||
if (reportNextDraw) {
|
||||
reportDrawFinish();
|
||||
}
|
||||
}
|
||||
|
||||
public void onPostDraw(Canvas canvas) { }
|
||||
|
||||
public void reportDrawFinish() {
|
||||
mView.getViewRootImpl().reportDrawFinish();
|
||||
}
|
||||
|
||||
public boolean attach() {
|
||||
ViewRootImpl root = mView.getViewRootImpl();
|
||||
if (root != null) {
|
||||
root.addWindowCallbacks(mWindowCallbacks);
|
||||
root.requestInvalidateRootRenderNode();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void detach() {
|
||||
ViewRootImpl root = mView.getViewRootImpl();
|
||||
if (root != null) {
|
||||
root.removeWindowCallbacks(mWindowCallbacks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,41 +27,41 @@ import android.graphics.Rect;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.InsetsState;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
|
||||
import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
|
||||
import com.android.systemui.shared.recents.view.RecentsTransition;
|
||||
import com.android.systemui.shared.system.PinnedStackListenerForwarder.PinnedStackListener;
|
||||
|
||||
public class WindowManagerWrapper {
|
||||
|
||||
private static final String TAG = "WindowManagerWrapper";
|
||||
|
||||
public static final int TRANSIT_UNSET = WindowManager.TRANSIT_UNSET;
|
||||
public static final int TRANSIT_NONE = WindowManager.TRANSIT_NONE;
|
||||
public static final int TRANSIT_ACTIVITY_OPEN = WindowManager.TRANSIT_ACTIVITY_OPEN;
|
||||
public static final int TRANSIT_ACTIVITY_CLOSE = WindowManager.TRANSIT_ACTIVITY_CLOSE;
|
||||
public static final int TRANSIT_TASK_OPEN = WindowManager.TRANSIT_TASK_OPEN;
|
||||
public static final int TRANSIT_TASK_CLOSE = WindowManager.TRANSIT_TASK_CLOSE;
|
||||
public static final int TRANSIT_TASK_TO_FRONT = WindowManager.TRANSIT_TASK_TO_FRONT;
|
||||
public static final int TRANSIT_TASK_TO_BACK = WindowManager.TRANSIT_TASK_TO_BACK;
|
||||
public static final int TRANSIT_WALLPAPER_CLOSE = WindowManager.TRANSIT_WALLPAPER_CLOSE;
|
||||
public static final int TRANSIT_WALLPAPER_OPEN = WindowManager.TRANSIT_WALLPAPER_OPEN;
|
||||
public static final int TRANSIT_UNSET = WindowManager.TRANSIT_OLD_UNSET;
|
||||
public static final int TRANSIT_NONE = WindowManager.TRANSIT_OLD_NONE;
|
||||
public static final int TRANSIT_ACTIVITY_OPEN = WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
|
||||
public static final int TRANSIT_ACTIVITY_CLOSE = WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
|
||||
public static final int TRANSIT_TASK_OPEN = WindowManager.TRANSIT_OLD_TASK_OPEN;
|
||||
public static final int TRANSIT_TASK_CLOSE = WindowManager.TRANSIT_OLD_TASK_CLOSE;
|
||||
public static final int TRANSIT_TASK_TO_FRONT = WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
|
||||
public static final int TRANSIT_TASK_TO_BACK = WindowManager.TRANSIT_OLD_TASK_TO_BACK;
|
||||
public static final int TRANSIT_WALLPAPER_CLOSE = WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE;
|
||||
public static final int TRANSIT_WALLPAPER_OPEN = WindowManager.TRANSIT_OLD_WALLPAPER_OPEN;
|
||||
public static final int TRANSIT_WALLPAPER_INTRA_OPEN =
|
||||
WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
|
||||
WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
|
||||
public static final int TRANSIT_WALLPAPER_INTRA_CLOSE =
|
||||
WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
|
||||
public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_TASK_OPEN_BEHIND;
|
||||
public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
|
||||
public static final int TRANSIT_DOCK_TASK_FROM_RECENTS =
|
||||
WindowManager.TRANSIT_DOCK_TASK_FROM_RECENTS;
|
||||
public static final int TRANSIT_KEYGUARD_GOING_AWAY = WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
|
||||
WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
|
||||
public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
|
||||
public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH;
|
||||
public static final int TRANSIT_KEYGUARD_GOING_AWAY =
|
||||
WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
|
||||
public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
|
||||
WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
|
||||
public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
|
||||
public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
|
||||
WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
|
||||
public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
|
||||
public static final int TRANSIT_KEYGUARD_UNOCCLUDE =
|
||||
WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
|
||||
|
||||
public static final int NAV_BAR_POS_INVALID = NAV_BAR_INVALID;
|
||||
public static final int NAV_BAR_POS_LEFT = NAV_BAR_LEFT;
|
||||
@@ -75,26 +75,49 @@ public class WindowManagerWrapper {
|
||||
WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
public static final int WINDOWING_MODE_MULTI_WINDOW =
|
||||
WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
public static final int WINDOWING_MODE_PINNED = WindowConfiguration.WINDOWING_MODE_PINNED;
|
||||
|
||||
public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY =
|
||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
|
||||
public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY =
|
||||
WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
|
||||
public static final int WINDOWING_MODE_FREEFORM = WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||
|
||||
private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
|
||||
public static final int ITYPE_EXTRA_NAVIGATION_BAR = InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
|
||||
public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = InsetsState.ITYPE_LEFT_TAPPABLE_ELEMENT;
|
||||
public static final int ITYPE_TOP_TAPPABLE_ELEMENT = InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT;
|
||||
public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = InsetsState.ITYPE_RIGHT_TAPPABLE_ELEMENT;
|
||||
public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT =
|
||||
InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
|
||||
|
||||
/**
|
||||
* Forwarder to which we can add multiple pinned stack listeners. Each listener will receive
|
||||
* updates from the window manager service.
|
||||
*/
|
||||
private PinnedStackListenerForwarder mPinnedStackListenerForwarder =
|
||||
new PinnedStackListenerForwarder();
|
||||
private static final WindowManagerWrapper sInstance = new WindowManagerWrapper();
|
||||
|
||||
public static WindowManagerWrapper getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets {@param providesInsetsTypes} as the inset types provided by {@param params}.
|
||||
* @param params The window layout params.
|
||||
* @param providesInsetsTypes The inset types we would like this layout params to provide.
|
||||
*/
|
||||
public void setProvidesInsetsTypes(WindowManager.LayoutParams params,
|
||||
int[] providesInsetsTypes) {
|
||||
params.providesInsetsTypes = providesInsetsTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if app requested fixed orientation should be ignored for given displayId.
|
||||
*/
|
||||
public void setIgnoreOrientationRequest(int displayId, boolean ignoreOrientationRequest) {
|
||||
try {
|
||||
WindowManagerGlobal.getWindowManagerService().setIgnoreOrientationRequest(
|
||||
displayId, ignoreOrientationRequest);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to setIgnoreOrientationRequest()", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the stable insets for the primary display.
|
||||
*/
|
||||
@@ -153,12 +176,9 @@ public class WindowManagerWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setPipVisibility(final boolean visible) {
|
||||
try {
|
||||
WindowManagerGlobal.getWindowManagerService().setPipVisibility(visible);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Unable to reach window manager", e);
|
||||
}
|
||||
// To be removed
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,23 +210,6 @@ public class WindowManagerWrapper {
|
||||
return NAV_BAR_POS_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a pinned stack listener, which will receive updates from the window manager service
|
||||
* along with any other pinned stack listeners that were added via this method.
|
||||
*/
|
||||
public void addPinnedStackListener(PinnedStackListener listener) throws RemoteException {
|
||||
mPinnedStackListenerForwarder.addListener(listener);
|
||||
WindowManagerGlobal.getWindowManagerService().registerPinnedStackListener(
|
||||
DEFAULT_DISPLAY, mPinnedStackListenerForwarder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a pinned stack listener.
|
||||
*/
|
||||
public void removePinnedStackListener(PinnedStackListener listener) {
|
||||
mPinnedStackListenerForwarder.removeListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors a specified display. The SurfaceControl returned is the root of the mirrored
|
||||
* hierarchy.
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system.smartspace;
|
||||
|
||||
import com.android.systemui.shared.system.smartspace.SmartspaceState;
|
||||
|
||||
// Methods for getting and setting the state of a SmartSpace. This is used to allow a remote process
|
||||
// (such as System UI) to sync with and control a SmartSpace view hosted in another process (such as
|
||||
// Launcher).
|
||||
interface ISmartspaceCallback {
|
||||
|
||||
// Return information about the state of the SmartSpace, including location on-screen and
|
||||
// currently selected page.
|
||||
SmartspaceState getSmartspaceState();
|
||||
|
||||
// Set the currently selected page of this SmartSpace.
|
||||
oneway void setSelectedPage(int selectedPage);
|
||||
|
||||
oneway void setVisibility(int visibility);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system.smartspace;
|
||||
|
||||
import com.android.systemui.shared.system.smartspace.ISmartspaceCallback;
|
||||
|
||||
// Controller that keeps track of SmartSpace instances in remote processes (such as Launcher).
|
||||
interface ISmartspaceTransitionController {
|
||||
oneway void setSmartspace(ISmartspaceCallback callback);
|
||||
}
|
||||
+5
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -11,18 +11,11 @@
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system;
|
||||
package com.android.systemui.shared.system.smartspace;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Bundle;
|
||||
import com.android.systemui.shared.system.smartspace.SmartspaceState;
|
||||
|
||||
/**
|
||||
* Abstract class for assist data receivers.
|
||||
*/
|
||||
public abstract class AssistDataReceiver {
|
||||
public void onHandleAssistData(Bundle resultData) {}
|
||||
public void onHandleAssistScreenshot(Bitmap screenshot) {}
|
||||
}
|
||||
parcelable SmartspaceState;
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.systemui.shared.system.smartspace
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
/**
|
||||
* Represents the state of a SmartSpace, including its location on screen and the index of the
|
||||
* currently selected page. This object contains all of the information needed to synchronize two
|
||||
* SmartSpace instances so that we can perform shared-element transitions between them.
|
||||
*/
|
||||
class SmartspaceState() : Parcelable {
|
||||
var boundsOnScreen: Rect = Rect()
|
||||
var selectedPage = 0
|
||||
|
||||
constructor(parcel: Parcel) : this() {
|
||||
this.boundsOnScreen = parcel.readParcelable(Rect::javaClass.javaClass.classLoader)!!
|
||||
this.selectedPage = parcel.readInt()
|
||||
}
|
||||
|
||||
override fun writeToParcel(dest: Parcel?, flags: Int) {
|
||||
dest?.writeParcelable(boundsOnScreen, 0)
|
||||
dest?.writeInt(selectedPage)
|
||||
}
|
||||
|
||||
override fun describeContents(): Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "boundsOnScreen: $boundsOnScreen, selectedPage: $selectedPage"
|
||||
}
|
||||
|
||||
companion object CREATOR : Parcelable.Creator<SmartspaceState> {
|
||||
override fun createFromParcel(parcel: Parcel): SmartspaceState {
|
||||
return SmartspaceState(parcel)
|
||||
}
|
||||
|
||||
override fun newArray(size: Int): Array<SmartspaceState?> {
|
||||
return arrayOfNulls(size)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class FrameProtoTracer<P, S extends P, T extends P, R>
|
||||
private final TraceBuffer<P, S, T> mBuffer;
|
||||
private final File mTraceFile;
|
||||
private final ProtoTraceParams<P, S, T, R> mParams;
|
||||
private final Choreographer mChoreographer;
|
||||
private Choreographer mChoreographer;
|
||||
private final Queue<T> mPool = new LinkedList<>();
|
||||
private final ArrayList<ProtoTraceable<R>> mTraceables = new ArrayList<>();
|
||||
private final ArrayList<ProtoTraceable<R>> mTmpTraceables = new ArrayList<>();
|
||||
@@ -94,7 +94,6 @@ public class FrameProtoTracer<P, S extends P, T extends P, R>
|
||||
}
|
||||
});
|
||||
mTraceFile = params.getTraceFile();
|
||||
mChoreographer = Choreographer.getMainThreadInstance();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
@@ -140,6 +139,9 @@ public class FrameProtoTracer<P, S extends P, T extends P, R>
|
||||
}
|
||||
|
||||
// Schedule an update on the next frame
|
||||
if (mChoreographer == null) {
|
||||
mChoreographer = Choreographer.getMainThreadInstance();
|
||||
}
|
||||
mChoreographer.postFrameCallback(this);
|
||||
mFrameScheduled = true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user