summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/res/layout/tv_pip_menu.xml2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java99
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java47
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java45
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java31
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java26
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java49
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java43
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java105
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java58
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt9
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java65
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java16
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java49
-rw-r--r--libs/hwui/Android.bp2
-rw-r--r--libs/hwui/jni/YuvToJpegEncoder.cpp32
-rw-r--r--libs/hwui/jni/YuvToJpegEncoder.h6
31 files changed, 594 insertions, 186 deletions
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
index dcce4698c252..ab64f9e359b0 100644
--- a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
@@ -67,7 +67,7 @@
<!-- Temporarily extending the background to show an edu text hint for opening the menu -->
<FrameLayout
- android:id="@+id/tv_pip_menu_edu_text_drawer_placeholder"
+ android:id="@+id/tv_pip_menu_edu_text_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/tv_pip"
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 47d3a5c52074..dc27ceb7f51c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -20,6 +20,9 @@ import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTas
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_BACK_PREVIEW;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityTaskManager;
@@ -37,7 +40,9 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings.Global;
+import android.util.DisplayMetrics;
import android.util.Log;
+import android.util.MathUtils;
import android.util.SparseArray;
import android.view.IRemoteAnimationRunner;
import android.view.InputDevice;
@@ -56,6 +61,7 @@ import android.window.IOnBackInvokedCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.internal.view.AppearanceRegion;
+import com.android.wm.shell.animation.FlingAnimationUtils;
import com.android.wm.shell.common.ExternalInterfaceBinder;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
@@ -80,6 +86,17 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
public static boolean IS_U_ANIMATION_ENABLED =
SystemProperties.getInt("persist.wm.debug.predictive_back_anim",
SETTING_VALUE_ON) == SETTING_VALUE_ON;
+
+ public static final float FLING_MAX_LENGTH_SECONDS = 0.1f; // 100ms
+ public static final float FLING_SPEED_UP_FACTOR = 0.6f;
+
+ /**
+ * The maximum additional progress in case of fling gesture.
+ * The end animation starts after the user lifts the finger from the screen, we continue to
+ * fire {@link BackEvent}s until the velocity reaches 0.
+ */
+ private static final float MAX_FLING_PROGRESS = 0.3f; /* 30% of the screen */
+
/** Predictive back animation developer option */
private final AtomicBoolean mEnableAnimations = new AtomicBoolean(false);
/**
@@ -96,6 +113,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private boolean mShouldStartOnNextMoveEvent = false;
/** @see #setTriggerBack(boolean) */
private boolean mTriggerBack;
+ private FlingAnimationUtils mFlingAnimationUtils;
@Nullable
private BackNavigationInfo mBackNavigationInfo;
@@ -174,6 +192,11 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mBgHandler = bgHandler;
shellInit.addInitCallback(this::onInit, this);
mAnimationBackground = backAnimationBackground;
+ DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
+ mFlingAnimationUtils = new FlingAnimationUtils.Builder(displayMetrics)
+ .setMaxLengthSeconds(FLING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(FLING_SPEED_UP_FACTOR)
+ .build();
}
@VisibleForTesting
@@ -465,6 +488,78 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
}
+
+ /**
+ * Allows us to manage the fling gesture, it smoothly animates the current progress value to
+ * the final position, calculated based on the current velocity.
+ *
+ * @param callback the callback to be invoked when the animation ends.
+ */
+ private void dispatchOrAnimateOnBackInvoked(IOnBackInvokedCallback callback) {
+ if (callback == null) {
+ return;
+ }
+
+ boolean animationStarted = false;
+
+ if (mBackNavigationInfo != null && mBackNavigationInfo.isAnimationCallback()) {
+
+ final BackMotionEvent backMotionEvent = mTouchTracker.createProgressEvent();
+ if (backMotionEvent != null) {
+ // Constraints - absolute values
+ float minVelocity = mFlingAnimationUtils.getMinVelocityPxPerSecond();
+ float maxVelocity = mFlingAnimationUtils.getHighVelocityPxPerSecond();
+ float maxX = mTouchTracker.getMaxX(); // px
+ float maxFlingDistance = maxX * MAX_FLING_PROGRESS; // px
+
+ // Current state
+ float currentX = backMotionEvent.getTouchX();
+ float velocity = MathUtils.constrain(backMotionEvent.getVelocityX(),
+ -maxVelocity, maxVelocity);
+
+ // Target state
+ float animationFaction = velocity / maxVelocity; // value between -1 and 1
+ float flingDistance = animationFaction * maxFlingDistance; // px
+ float endX = MathUtils.constrain(currentX + flingDistance, 0f, maxX);
+
+ if (!Float.isNaN(endX)
+ && currentX != endX
+ && Math.abs(velocity) >= minVelocity) {
+ ValueAnimator animator = ValueAnimator.ofFloat(currentX, endX);
+
+ mFlingAnimationUtils.apply(
+ /* animator = */ animator,
+ /* currValue = */ currentX,
+ /* endValue = */ endX,
+ /* velocity = */ velocity,
+ /* maxDistance = */ maxFlingDistance
+ );
+
+ animator.addUpdateListener(animation -> {
+ Float animatedValue = (Float) animation.getAnimatedValue();
+ float progress = mTouchTracker.getProgress(animatedValue);
+ final BackMotionEvent backEvent = mTouchTracker
+ .createProgressEvent(progress);
+ dispatchOnBackProgressed(mActiveCallback, backEvent);
+ });
+
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ dispatchOnBackInvoked(callback);
+ }
+ });
+ animator.start();
+ animationStarted = true;
+ }
+ }
+ }
+
+ if (!animationStarted) {
+ dispatchOnBackInvoked(callback);
+ }
+ }
+
private void dispatchOnBackInvoked(IOnBackInvokedCallback callback) {
if (callback == null) {
return;
@@ -530,7 +625,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
if (mBackNavigationInfo != null) {
final IOnBackInvokedCallback callback = mBackNavigationInfo.getOnBackInvokedCallback();
if (mTriggerBack) {
- dispatchOnBackInvoked(callback);
+ dispatchOrAnimateOnBackInvoked(callback);
} else {
dispatchOnBackCancelled(callback);
}
@@ -605,7 +700,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
// The next callback should be {@link #onBackAnimationFinished}.
if (mTriggerBack) {
- dispatchOnBackInvoked(mActiveCallback);
+ dispatchOrAnimateOnBackInvoked(mActiveCallback);
} else {
dispatchOnBackCancelled(mActiveCallback);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
index 904574b08562..7a00f5b9bab4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/TouchTracker.java
@@ -16,7 +16,10 @@
package com.android.wm.shell.back;
+import android.annotation.FloatRange;
import android.os.SystemProperties;
+import android.util.MathUtils;
+import android.view.MotionEvent;
import android.view.RemoteAnimationTarget;
import android.window.BackEvent;
import android.window.BackMotionEvent;
@@ -99,28 +102,42 @@ class TouchTracker {
}
BackMotionEvent createProgressEvent() {
- float progressThreshold = PROGRESS_THRESHOLD >= 0
- ? PROGRESS_THRESHOLD : mProgressThreshold;
- progressThreshold = progressThreshold == 0 ? 1 : progressThreshold;
float progress = 0;
// Progress is always 0 when back is cancelled and not restarted.
if (!mCancelled) {
- // If back is committed, progress is the distance between the last and first touch
- // point, divided by the max drag distance. Otherwise, it's the distance between
- // the last touch point and the starting threshold, divided by max drag distance.
- // The starting threshold is initially the first touch location, and updated to
- // the location everytime back is restarted after being cancelled.
- float startX = mTriggerBack ? mInitTouchX : mStartThresholdX;
- float deltaX = Math.max(
- mSwipeEdge == BackEvent.EDGE_LEFT
- ? mLatestTouchX - startX
- : startX - mLatestTouchX,
- 0);
- progress = Math.min(Math.max(deltaX / progressThreshold, 0), 1);
+ progress = getProgress(mLatestTouchX);
}
return createProgressEvent(progress);
}
+ /**
+ * Progress value computed from the touch position.
+ *
+ * @param touchX the X touch position of the {@link MotionEvent}.
+ * @return progress value
+ */
+ @FloatRange(from = 0.0, to = 1.0)
+ float getProgress(float touchX) {
+ // If back is committed, progress is the distance between the last and first touch
+ // point, divided by the max drag distance. Otherwise, it's the distance between
+ // the last touch point and the starting threshold, divided by max drag distance.
+ // The starting threshold is initially the first touch location, and updated to
+ // the location everytime back is restarted after being cancelled.
+ float startX = mTriggerBack ? mInitTouchX : mStartThresholdX;
+ float deltaX = Math.abs(startX - touchX);
+ float maxX = getMaxX();
+ maxX = maxX == 0 ? 1 : maxX;
+ return MathUtils.constrain(deltaX / maxX, 0, 1);
+ }
+
+ /**
+ * Maximum X value (in pixels).
+ * Progress is considered to be completed (1f) when this limit is exceeded.
+ */
+ float getMaxX() {
+ return PROGRESS_THRESHOLD >= 0 ? PROGRESS_THRESHOLD : mProgressThreshold;
+ }
+
BackMotionEvent createProgressEvent(float progress) {
return new BackMotionEvent(
/* touchX = */ mLatestTouchX,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
index 79e0a4868cae..d3f395846894 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java
@@ -64,7 +64,11 @@ import java.util.concurrent.Executor;
public class Bubble implements BubbleViewProvider {
private static final String TAG = "Bubble";
- public static final String KEY_APP_BUBBLE = "key_app_bubble";
+ /** A string suffix used in app bubbles' {@link #mKey}. */
+ private static final String KEY_APP_BUBBLE = "key_app_bubble";
+
+ /** Whether the bubble is an app bubble. */
+ private final boolean mIsAppBubble;
private final String mKey;
@Nullable
@@ -181,7 +185,7 @@ public class Bubble implements BubbleViewProvider {
private PendingIntent mDeleteIntent;
/**
- * Used only for a special bubble in the stack that has the key {@link #KEY_APP_BUBBLE}.
+ * Used only for a special bubble in the stack that has {@link #mIsAppBubble} set to true.
* There can only be one of these bubbles in the stack and this intent will be populated for
* that bubble.
*/
@@ -216,24 +220,54 @@ public class Bubble implements BubbleViewProvider {
mMainExecutor = mainExecutor;
mTaskId = taskId;
mBubbleMetadataFlagListener = listener;
+ mIsAppBubble = false;
}
- public Bubble(Intent intent,
+ private Bubble(
+ Intent intent,
UserHandle user,
@Nullable Icon icon,
+ boolean isAppBubble,
+ String key,
Executor mainExecutor) {
- mKey = KEY_APP_BUBBLE;
mGroupKey = null;
mLocusId = null;
mFlags = 0;
mUser = user;
mIcon = icon;
+ mIsAppBubble = isAppBubble;
+ mKey = key;
mShowBubbleUpdateDot = false;
mMainExecutor = mainExecutor;
mTaskId = INVALID_TASK_ID;
mAppIntent = intent;
mDesiredHeight = Integer.MAX_VALUE;
mPackageName = intent.getPackage();
+
+ }
+
+ /** Creates an app bubble. */
+ public static Bubble createAppBubble(
+ Intent intent,
+ UserHandle user,
+ @Nullable Icon icon,
+ Executor mainExecutor) {
+ return new Bubble(intent,
+ user,
+ icon,
+ /* isAppBubble= */ true,
+ /* key= */ getAppBubbleKeyForApp(intent.getPackage(), user),
+ mainExecutor);
+ }
+
+ /**
+ * Returns the key for an app bubble from an app with package name, {@code packageName} on an
+ * Android user, {@code user}.
+ */
+ public static String getAppBubbleKeyForApp(String packageName, UserHandle user) {
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(user);
+ return KEY_APP_BUBBLE + ":" + user.getIdentifier() + ":" + packageName;
}
@VisibleForTesting(visibility = PRIVATE)
@@ -241,6 +275,7 @@ public class Bubble implements BubbleViewProvider {
final Bubbles.BubbleMetadataFlagListener listener,
final Bubbles.PendingIntentCanceledListener intentCancelListener,
Executor mainExecutor) {
+ mIsAppBubble = false;
mKey = entry.getKey();
mGroupKey = entry.getGroupKey();
mLocusId = entry.getLocusId();
@@ -815,7 +850,7 @@ public class Bubble implements BubbleViewProvider {
}
boolean isAppBubble() {
- return KEY_APP_BUBBLE.equals(mKey);
+ return mIsAppBubble;
}
Intent getSettingsIntent(final Context context) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index c407b0624985..21f02b10035b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -24,7 +24,6 @@ import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_CONTROLLER;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_GESTURE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
@@ -1193,14 +1192,15 @@ public class BubbleController implements ConfigurationChangeListener,
return;
}
+ String appBubbleKey = Bubble.getAppBubbleKeyForApp(intent.getPackage(), user);
PackageManager packageManager = getPackageManagerForUser(mContext, user.getIdentifier());
- if (!isResizableActivity(intent, packageManager, KEY_APP_BUBBLE)) return;
+ if (!isResizableActivity(intent, packageManager, appBubbleKey)) return;
- Bubble existingAppBubble = mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE);
+ Bubble existingAppBubble = mBubbleData.getBubbleInStackWithKey(appBubbleKey);
if (existingAppBubble != null) {
BubbleViewProvider selectedBubble = mBubbleData.getSelectedBubble();
if (isStackExpanded()) {
- if (selectedBubble != null && KEY_APP_BUBBLE.equals(selectedBubble.getKey())) {
+ if (selectedBubble != null && appBubbleKey.equals(selectedBubble.getKey())) {
// App bubble is expanded, lets collapse
collapseStack();
} else {
@@ -1214,7 +1214,7 @@ public class BubbleController implements ConfigurationChangeListener,
}
} else {
// App bubble does not exist, lets add and expand it
- Bubble b = new Bubble(intent, user, icon, mMainExecutor);
+ Bubble b = Bubble.createAppBubble(intent, user, icon, mMainExecutor);
b.setShouldAutoExpand(true);
inflateAndAdd(b, /* suppressFlyout= */ true, /* showInShade= */ false);
}
@@ -1247,8 +1247,8 @@ public class BubbleController implements ConfigurationChangeListener,
}
/** Sets the app bubble's taskId which is cached for SysUI. */
- public void setAppBubbleTaskId(int taskId) {
- mImpl.mCachedState.setAppBubbleTaskId(taskId);
+ public void setAppBubbleTaskId(String key, int taskId) {
+ mImpl.mCachedState.setAppBubbleTaskId(key, taskId);
}
/**
@@ -2045,7 +2045,8 @@ public class BubbleController implements ConfigurationChangeListener,
private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();
- private int mAppBubbleTaskId = INVALID_TASK_ID;
+
+ private HashMap<String, Integer> mAppBubbleTaskIds = new HashMap();
private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();
@@ -2077,20 +2078,20 @@ public class BubbleController implements ConfigurationChangeListener,
mSuppressedBubbleKeys.clear();
mShortcutIdToBubble.clear();
- mAppBubbleTaskId = INVALID_TASK_ID;
+ mAppBubbleTaskIds.clear();
for (Bubble b : mTmpBubbles) {
mShortcutIdToBubble.put(b.getShortcutId(), b);
updateBubbleSuppressedState(b);
- if (KEY_APP_BUBBLE.equals(b.getKey())) {
- mAppBubbleTaskId = b.getTaskId();
+ if (b.isAppBubble()) {
+ mAppBubbleTaskIds.put(b.getKey(), b.getTaskId());
}
}
}
/** Sets the app bubble's taskId which is cached for SysUI. */
- synchronized void setAppBubbleTaskId(int taskId) {
- mAppBubbleTaskId = taskId;
+ synchronized void setAppBubbleTaskId(String key, int taskId) {
+ mAppBubbleTaskIds.put(key, taskId);
}
/**
@@ -2143,7 +2144,7 @@ public class BubbleController implements ConfigurationChangeListener,
pw.println(" suppressing: " + key);
}
- pw.print("mAppBubbleTaskId: " + mAppBubbleTaskId);
+ pw.print("mAppBubbleTaskIds: " + mAppBubbleTaskIds.values());
}
}
@@ -2205,7 +2206,7 @@ public class BubbleController implements ConfigurationChangeListener,
@Override
public boolean isAppBubbleTaskId(int taskId) {
- return mCachedState.mAppBubbleTaskId == taskId;
+ return mCachedState.mAppBubbleTaskIds.values().contains(taskId);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
index 92b969bb6f97..cc8f50e09fcb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java
@@ -17,7 +17,6 @@ package com.android.wm.shell.bubbles;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_DATA;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
@@ -780,7 +779,7 @@ public class BubbleData {
|| !(reason == Bubbles.DISMISS_AGED
|| reason == Bubbles.DISMISS_USER_GESTURE
|| reason == Bubbles.DISMISS_RELOAD_FROM_DISK)
- || KEY_APP_BUBBLE.equals(bubble.getKey())) {
+ || bubble.isAppBubble()) {
return;
}
if (DEBUG_BUBBLE_DATA) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
index 684a23a198c2..6c482c831152 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedView.java
@@ -287,9 +287,9 @@ public class BubbleExpandedView extends LinearLayout {
// The taskId is saved to use for removeTask, preventing appearance in recent tasks.
mTaskId = taskId;
- if (Bubble.KEY_APP_BUBBLE.equals(getBubbleKey())) {
+ if (mBubble != null && mBubble.isAppBubble()) {
// Let the controller know sooner what the taskId is.
- mController.setAppBubbleTaskId(mTaskId);
+ mController.setAppBubbleTaskId(mBubble.getKey(), mTaskId);
}
// With the task org, the taskAppeared callback will only happen once the task has
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index 4970fa0cb087..56616cb6bd88 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -165,6 +165,10 @@ public class SplitDecorManager extends WindowlessWindowManager {
t.remove(mGapBackgroundLeash);
mGapBackgroundLeash = null;
}
+ if (mScreenshot != null) {
+ t.remove(mScreenshot);
+ mScreenshot = null;
+ }
mHostLeash = null;
mIcon = null;
mResizingIconView = null;
@@ -324,6 +328,8 @@ public class SplitDecorManager extends WindowlessWindowManager {
if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
mScreenshotAnimator.cancel();
+ } else if (mScreenshot != null) {
+ t.remove(mScreenshot);
}
mTempRect.set(mOldBounds);
@@ -340,6 +346,8 @@ public class SplitDecorManager extends WindowlessWindowManager {
if (!mShown && mIsResizing && !mOldBounds.equals(mResizingBounds)) {
if (mScreenshotAnimator != null && mScreenshotAnimator.isRunning()) {
mScreenshotAnimator.cancel();
+ } else if (mScreenshot != null) {
+ t.remove(mScreenshot);
}
mScreenshot = screenshot;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index d04ce1540980..b6216b340b38 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -146,13 +146,17 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
t.apply();
// execute the runnable if non-null after WCT is applied to finish resizing pip
- if (mPipFinishResizeWCTRunnable != null) {
- mPipFinishResizeWCTRunnable.run();
- mPipFinishResizeWCTRunnable = null;
- }
+ maybePerformFinishResizeCallback();
}
};
+ private void maybePerformFinishResizeCallback() {
+ if (mPipFinishResizeWCTRunnable != null) {
+ mPipFinishResizeWCTRunnable.run();
+ mPipFinishResizeWCTRunnable = null;
+ }
+ }
+
// These callbacks are called on the update thread
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
new PipAnimationController.PipAnimationCallback() {
@@ -619,11 +623,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
* Removes PiP immediately.
*/
public void removePip() {
- if (!mPipTransitionState.isInPip() || mToken == null) {
+ if (!mPipTransitionState.isInPip() || mToken == null || mLeash == null) {
ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: Not allowed to removePip in current state"
- + " mState=%d mToken=%s", TAG, mPipTransitionState.getTransitionState(),
- mToken);
+ + " mState=%d mToken=%s mLeash=%s", TAG,
+ mPipTransitionState.getTransitionState(), mToken, mLeash);
return;
}
@@ -1007,6 +1011,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
return;
}
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mPipTransitionController.onFixedRotationFinished();
clearWaitForFixedRotation();
return;
}
@@ -1527,6 +1532,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
if (snapshotSurface != null) {
mSyncTransactionQueue.queue(wct);
mSyncTransactionQueue.runInSync(t -> {
+ // reset the pinch gesture
+ maybePerformFinishResizeCallback();
+
// Scale the snapshot from its pre-resize bounds to the post-resize bounds.
mSurfaceTransactionHelper.scale(t, snapshotSurface, preResizeBounds,
snapshotDest);
@@ -1606,6 +1614,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
mSplitScreenOptional.ifPresent(splitScreenController ->
splitScreenController.enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct));
+ } else if (direction == TRANSITION_DIRECTION_LEAVE_PIP) {
+ // when leaving PiP we can call the callback without sync
+ maybePerformFinishResizeCallback();
+ mTaskOrganizer.applyTransaction(wct);
} else {
mTaskOrganizer.applySyncTransaction(wct, mPipFinishResizeWCTCallback);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 5755a10897af..99cb6f782d01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -409,9 +409,31 @@ public class PipTransition extends PipTransitionController {
@Override
public void onFixedRotationStarted() {
+ fadeEnteredPipIfNeed(false /* show */);
+ }
+
+ @Override
+ public void onFixedRotationFinished() {
+ fadeEnteredPipIfNeed(true /* show */);
+ }
+
+ private void fadeEnteredPipIfNeed(boolean show) {
// The transition with this fixed rotation may be handled by other handler before reaching
// PipTransition, so we cannot do this in #startAnimation.
- if (mPipTransitionState.getTransitionState() == ENTERED_PIP && !mHasFadeOut) {
+ if (!mPipTransitionState.hasEnteredPip()) {
+ return;
+ }
+ if (show && mHasFadeOut) {
+ // If there is a pending transition, then let startAnimation handle it. And if it is
+ // handled, mHasFadeOut will be set to false and this runnable will be no-op. Otherwise
+ // make sure the PiP will reshow, e.g. swipe-up with fixed rotation (fade-out) but
+ // return to the current app (only finish the recent transition).
+ mTransitions.runOnIdle(() -> {
+ if (mHasFadeOut && mPipTransitionState.hasEnteredPip()) {
+ fadeExistingPip(true /* show */);
+ }
+ });
+ } else if (!show && !mHasFadeOut) {
// Fade out the existing PiP to avoid jump cut during seamless rotation.
fadeExistingPip(false /* show */);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index ff7ab8ba1d97..949d6f558c32 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -123,6 +123,10 @@ public abstract class PipTransitionController implements Transitions.TransitionH
public void onFixedRotationStarted() {
}
+ /** Called when the fixed rotation finished. */
+ public void onFixedRotationFinished() {
+ }
+
public PipTransitionController(
@NonNull ShellInit shellInit,
@NonNull ShellTaskOrganizer shellTaskOrganizer,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java
index 222307fba8c2..5f6b3fe1e250 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipAction.java
@@ -31,6 +31,12 @@ import java.util.Objects;
abstract class TvPipAction {
+ /**
+ * Extras key for adding a boolean to the {@link Notification.Action} to differentiate custom
+ * from system actions, most importantly to identify custom close actions.
+ **/
+ public static final String EXTRA_IS_PIP_CUSTOM_ACTION = "EXTRA_IS_PIP_CUSTOM_ACTION";
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"ACTION_"}, value = {
ACTION_FULLSCREEN,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
index bca27a5c6636..977aad4a898a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipCustomAction.java
@@ -86,7 +86,7 @@ public class TvPipCustomAction extends TvPipAction {
Bundle extras = new Bundle();
extras.putCharSequence(Notification.EXTRA_PICTURE_CONTENT_DESCRIPTION,
mRemoteAction.getContentDescription());
- extras.putBoolean(Notification.EXTRA_CONTAINS_CUSTOM_VIEW, true);
+ extras.putBoolean(TvPipAction.EXTRA_IS_PIP_CUSTOM_ACTION, true);
builder.addExtras(extras);
builder.setSemanticAction(isCloseAction()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java
index 6eef22562caa..f86f987039ba 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuEduTextDrawer.java
@@ -23,6 +23,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE;
+import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.drawable.Drawable;
@@ -115,6 +116,10 @@ class TvPipMenuEduTextDrawer extends FrameLayout {
scheduleLifecycleEvents();
}
+ int getEduTextDrawerHeight() {
+ return getVisibility() == GONE ? 0 : getHeight();
+ }
+
private void scheduleLifecycleEvents() {
final int startScrollDelay = mContext.getResources().getInteger(
R.integer.pip_edu_text_start_scroll_delay);
@@ -226,20 +231,41 @@ class TvPipMenuEduTextDrawer extends FrameLayout {
.start();
// Start animation to close the drawer by animating its height to 0
- final ValueAnimator heightAnimation = ValueAnimator.ofInt(getHeight(), 0);
- heightAnimation.setDuration(eduTextSlideExitAnimationDuration);
- heightAnimation.setInterpolator(TvPipInterpolators.BROWSE);
- heightAnimation.addUpdateListener(animator -> {
+ final ValueAnimator heightAnimator = ValueAnimator.ofInt(getHeight(), 0);
+ heightAnimator.setDuration(eduTextSlideExitAnimationDuration);
+ heightAnimator.setInterpolator(TvPipInterpolators.BROWSE);
+ heightAnimator.addUpdateListener(animator -> {
final ViewGroup.LayoutParams params = getLayoutParams();
params.height = (int) animator.getAnimatedValue();
setLayoutParams(params);
- if (params.height == 0) {
- setVisibility(GONE);
+ });
+ heightAnimator.addListener(new Animator.AnimatorListener() {
+ @Override
+ public void onAnimationStart(@NonNull Animator animator) {
+ }
+
+ @Override
+ public void onAnimationEnd(@NonNull Animator animator) {
+ onCloseEduTextAnimationEnd();
+ }
+
+ @Override
+ public void onAnimationCancel(@NonNull Animator animator) {
+ onCloseEduTextAnimationEnd();
+ }
+
+ @Override
+ public void onAnimationRepeat(@NonNull Animator animator) {
}
});
- heightAnimation.start();
+ heightAnimator.start();
+
+ mListener.onCloseEduTextAnimationStart();
+ }
- mListener.onCloseEduText();
+ public void onCloseEduTextAnimationEnd() {
+ setVisibility(GONE);
+ mListener.onCloseEduTextAnimationEnd();
}
/**
@@ -270,11 +296,8 @@ class TvPipMenuEduTextDrawer extends FrameLayout {
* A listener for edu text drawer event states.
*/
interface Listener {
- /**
- * The edu text closing impacts the size of the Picture-in-Picture window and influences
- * how it is positioned on the screen.
- */
- void onCloseEduText();
+ void onCloseEduTextAnimationStart();
+ void onCloseEduTextAnimationEnd();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
index 6eb719ba60a3..d07641892552 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipMenuView.java
@@ -57,7 +57,8 @@ import java.util.List;
* A View that represents Pip Menu on TV. It's responsible for displaying the Pip menu actions from
* the TvPipActionsProvider as well as the buttons for manually moving the PiP.
*/
-public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.Listener {
+public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.Listener,
+ TvPipMenuEduTextDrawer.Listener {
private static final String TAG = "TvPipMenuView";
private final TvPipMenuView.Listener mListener;
@@ -76,6 +77,7 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
private final View mDimLayer;
private final TvPipMenuEduTextDrawer mEduTextDrawer;
+ private final ViewGroup mEduTextContainer;
private final int mPipMenuOuterSpace;
private final int mPipMenuBorderWidth;
@@ -139,9 +141,9 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
mPipMenuBorderWidth = context.getResources()
.getDimensionPixelSize(R.dimen.pip_menu_border_width);
- mEduTextDrawer = new TvPipMenuEduTextDrawer(mContext, mainHandler, mListener);
- ((FrameLayout) findViewById(R.id.tv_pip_menu_edu_text_drawer_placeholder))
- .addView(mEduTextDrawer);
+ mEduTextDrawer = new TvPipMenuEduTextDrawer(mContext, mainHandler, this);
+ mEduTextContainer = (ViewGroup) findViewById(R.id.tv_pip_menu_edu_text_container);
+ mEduTextContainer.addView(mEduTextDrawer);
}
void onPipTransitionToTargetBoundsStarted(Rect targetBounds) {
@@ -235,11 +237,13 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
* pip menu when it gains focus.
*/
private void updatePipFrameBounds() {
- final ViewGroup.LayoutParams pipFrameParams = mPipFrameView.getLayoutParams();
- if (pipFrameParams != null) {
- pipFrameParams.width = mCurrentPipBounds.width() + 2 * mPipMenuBorderWidth;
- pipFrameParams.height = mCurrentPipBounds.height() + 2 * mPipMenuBorderWidth;
- mPipFrameView.setLayoutParams(pipFrameParams);
+ if (mPipFrameView.getVisibility() == VISIBLE) {
+ final ViewGroup.LayoutParams pipFrameParams = mPipFrameView.getLayoutParams();
+ if (pipFrameParams != null) {
+ pipFrameParams.width = mCurrentPipBounds.width() + 2 * mPipMenuBorderWidth;
+ pipFrameParams.height = mCurrentPipBounds.height() + 2 * mPipMenuBorderWidth;
+ mPipFrameView.setLayoutParams(pipFrameParams);
+ }
}
final ViewGroup.LayoutParams pipViewParams = mPipView.getLayoutParams();
@@ -262,7 +266,7 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
Rect getPipMenuContainerBounds(Rect pipBounds) {
final Rect menuUiBounds = new Rect(pipBounds);
menuUiBounds.inset(-mPipMenuOuterSpace, -mPipMenuOuterSpace);
- menuUiBounds.bottom += mEduTextDrawer.getHeight();
+ menuUiBounds.bottom += mEduTextDrawer.getEduTextDrawerHeight();
return menuUiBounds;
}
@@ -406,6 +410,17 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
}
@Override
+ public void onCloseEduTextAnimationStart() {
+ mListener.onCloseEduText();
+ }
+
+ @Override
+ public void onCloseEduTextAnimationEnd() {
+ mPipFrameView.setVisibility(GONE);
+ mEduTextContainer.setVisibility(GONE);
+ }
+
+ @Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == ACTION_UP) {
@@ -551,7 +566,7 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
}
}
- interface Listener extends TvPipMenuEduTextDrawer.Listener {
+ interface Listener {
void onBackPress();
@@ -573,5 +588,11 @@ public class TvPipMenuView extends FrameLayout implements TvPipActionsProvider.L
* has lost focus.
*/
void onPipWindowFocusChanged(boolean focused);
+
+ /**
+ * The edu text closing impacts the size of the Picture-in-Picture window and influences
+ * how it is positioned on the screen.
+ */
+ void onCloseEduText();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index c9b3a1af6507..c4a0e9cf5a74 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -32,6 +32,8 @@ public enum ShellProtoLogGroup implements IProtoLogGroup {
Consts.TAG_WM_SHELL),
WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
Consts.TAG_WM_SHELL),
+ WM_SHELL_RECENTS_TRANSITION(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
+ Consts.TAG_WM_SHELL),
WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
Consts.TAG_WM_SHELL),
WM_SHELL_STARTING_WINDOW(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
index 44d7e6de8ec4..b55487258220 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java
@@ -47,7 +47,9 @@ import android.window.TransitionRequestInfo;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
+import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.TransitionUtil;
@@ -96,6 +98,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
void startRecentsTransition(PendingIntent intent, Intent fillIn, Bundle options,
IApplicationThread appThread, IRecentsAnimationRunner listener) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsTransitionHandler.startRecentsTransition");
// only care about latest one.
mAnimApp = appThread;
WindowContainerTransaction wct = new WindowContainerTransaction();
@@ -116,7 +120,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
mixer.setRecentsTransition(transition);
}
if (transition == null) {
- controller.cancel();
+ controller.cancel("startRecentsTransition");
return;
}
controller.setTransition(transition);
@@ -127,6 +131,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
public WindowContainerTransaction handleRequest(IBinder transition,
TransitionRequestInfo request) {
// do not directly handle requests. Only entry point should be via startRecentsTransition
+ Slog.e(TAG, "RecentsTransitionHandler.handleRequest: Unexpected transition request");
return null;
}
@@ -143,11 +148,17 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
SurfaceControl.Transaction finishTransaction,
Transitions.TransitionFinishCallback finishCallback) {
final int controllerIdx = findController(transition);
- if (controllerIdx < 0) return false;
+ if (controllerIdx < 0) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsTransitionHandler.startAnimation: no controller found");
+ return false;
+ }
final RecentsController controller = mControllers.get(controllerIdx);
Transitions.setRunningRemoteTransitionDelegate(mAnimApp);
mAnimApp = null;
if (!controller.start(info, startTransaction, finishTransaction, finishCallback)) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsTransitionHandler.startAnimation: failed to start animation");
return false;
}
return true;
@@ -168,7 +179,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
SurfaceControl.Transaction finishTransaction) {
final int idx = findController(transition);
if (idx < 0) return;
- mControllers.get(idx).cancel();
+ mControllers.get(idx).cancel("onTransitionConsumed");
}
/** There is only one of these and it gets reset on finish. */
@@ -213,39 +224,45 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
RecentsController(IRecentsAnimationRunner listener) {
mListener = listener;
- mDeathHandler = () -> mExecutor.execute(() -> {
- if (mListener == null) return;
- if (mFinishCB != null) {
- finish(mWillFinishToHome, false /* leaveHint */);
- }
- });
+ mDeathHandler = () -> {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.DeathRecipient: binder died");
+ finish(mWillFinishToHome, false /* leaveHint */);
+ };
try {
mListener.asBinder().linkToDeath(mDeathHandler, 0 /* flags */);
} catch (RemoteException e) {
+ Slog.e(TAG, "RecentsController: failed to link to death", e);
mListener = null;
}
}
void setTransition(IBinder transition) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setTransition: id=%s", transition);
mTransition = transition;
}
- void cancel() {
+ void cancel(String reason) {
// restoring (to-home = false) involves submitting more WM changes, so by default, use
// toHome = true when canceling.
- cancel(true /* toHome */);
+ cancel(true /* toHome */, reason);
}
- void cancel(boolean toHome) {
+ void cancel(boolean toHome, String reason) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.cancel: toHome=%b reason=%s", toHome, reason);
if (mListener != null) {
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.cancel: calling onAnimationCanceled");
mListener.onAnimationCanceled(null, null);
} catch (RemoteException e) {
Slog.e(TAG, "Error canceling recents animation", e);
}
}
if (mFinishCB != null) {
- finish(toHome, false /* userLeave */);
+ finishInner(toHome, false /* userLeave */);
} else {
cleanUp();
}
@@ -272,6 +289,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
}
}
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.cancel: calling onAnimationCanceled with snapshots");
mListener.onAnimationCanceled(taskIds, snapshots);
} catch (RemoteException e) {
Slog.e(TAG, "Error canceling recents animation", e);
@@ -281,6 +300,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
}
void cleanUp() {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsController.cleanup");
if (mListener != null && mDeathHandler != null) {
mListener.asBinder().unlinkToDeath(mDeathHandler, 0 /* flags */);
mDeathHandler = null;
@@ -304,6 +324,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
boolean start(TransitionInfo info, SurfaceControl.Transaction t,
SurfaceControl.Transaction finishT, Transitions.TransitionFinishCallback finishCB) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsController.start");
if (mListener == null || mTransition == null) {
cleanUp();
return false;
@@ -363,6 +384,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
info.getChanges().size() - i, info, t, mLeashMap);
apps.add(target);
if (TransitionUtil.isClosingType(change.getMode())) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " adding pausing taskId=%d", taskInfo.taskId);
// raise closing (pausing) task to "above" layer so it isn't covered
t.setLayer(target.leash, info.getChanges().size() * 3 - i);
mPausingTasks.add(new TaskState(change, target.leash));
@@ -377,19 +400,23 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
} else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
// do nothing
} else if (TransitionUtil.isOpeningType(change.getMode())) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " adding opening taskId=%d", taskInfo.taskId);
mOpeningTasks.add(new TaskState(change, target.leash));
}
}
}
t.apply();
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.start: calling onAnimationStart");
mListener.onAnimationStart(this,
apps.toArray(new RemoteAnimationTarget[apps.size()]),
wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
new Rect(0, 0, 0, 0), new Rect());
} catch (RemoteException e) {
Slog.e(TAG, "Error starting recents animation", e);
- cancel();
+ cancel("onAnimationStart() failed");
}
return true;
}
@@ -398,14 +425,19 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
void merge(TransitionInfo info, SurfaceControl.Transaction t,
Transitions.TransitionFinishCallback finishCallback) {
if (mFinishCB == null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.merge: skip, no finish callback");
// This was no-op'd (likely a repeated start) and we've already sent finish.
return;
}
if (info.getType() == TRANSIT_SLEEP) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.merge: transit_sleep");
// A sleep event means we need to stop animations immediately, so cancel here.
- cancel();
+ cancel("transit_sleep");
return;
}
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, "RecentsController.merge");
ArrayList<TransitionInfo.Change> openingTasks = null;
ArrayList<TransitionInfo.Change> closingTasks = null;
mOpeningSeparateHome = false;
@@ -422,7 +454,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
&& taskInfo.configuration.windowConfiguration.isAlwaysOnTop()) {
// Tasks that are always on top (e.g. bubbles), will handle their own transition
// as they are on top of everything else. So cancel the merge here.
- cancel();
+ cancel("task #" + taskInfo.taskId + " is always_on_top");
return;
}
hasTaskChange = hasTaskChange || taskInfo != null;
@@ -453,7 +485,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
// Finish recents animation if the display is changed, so the default
// transition handler can play the animation such as rotation effect.
if (change.hasFlags(TransitionInfo.FLAG_IS_DISPLAY)) {
- cancel(mWillFinishToHome);
+ cancel(mWillFinishToHome, "display change");
return;
}
// Don't consider order-only changes as changing apps.
@@ -497,7 +529,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
+ " something unexpected: " + change.getTaskInfo().taskId);
continue;
}
- mPausingTasks.add(mOpeningTasks.remove(openingIdx));
+ final TaskState openingTask = mOpeningTasks.remove(openingIdx);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " pausing opening taskId=%d", openingTask.mTaskInfo.taskId);
+ mPausingTasks.add(openingTask);
didMergeThings = true;
}
}
@@ -514,7 +549,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
// Something is showing/opening a previously-pausing app.
appearedTargets[i] = TransitionUtil.newTarget(
change, layer, mPausingTasks.get(pausingIdx).mLeash);
- mOpeningTasks.add(mPausingTasks.remove(pausingIdx));
+ final TaskState pausingTask = mPausingTasks.remove(pausingIdx);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " opening pausing taskId=%d", pausingTask.mTaskInfo.taskId);
+ mOpeningTasks.add(pausingTask);
// Setup hides opening tasks initially, so make it visible again (since we
// are already showing it).
t.show(change.getLeash());
@@ -527,6 +565,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo);
t.reparent(appearedTargets[i].leash, mInfo.getRoot(rootIdx).getLeash());
t.setLayer(appearedTargets[i].leash, layer);
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ " opening new taskId=%d", appearedTargets[i].taskId);
mOpeningTasks.add(new TaskState(change, appearedTargets[i].leash));
}
}
@@ -544,7 +584,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
+ foundRecentsClosing);
if (foundRecentsClosing) {
mWillFinishToHome = false;
- cancel(false /* toHome */);
+ cancel(false /* toHome */, "didn't merge");
}
return;
}
@@ -552,13 +592,15 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
t.apply();
// not using the incoming anim-only surfaces
info.releaseAnimSurfaces();
- finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
if (appearedTargets == null) return;
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.merge: calling onTasksAppeared");
mListener.onTasksAppeared(appearedTargets);
} catch (RemoteException e) {
Slog.e(TAG, "Error sending appeared tasks to recents animation", e);
}
+ finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
}
/** For now, just set-up a jump-cut to the new activity. */
@@ -577,6 +619,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
@Override
public TaskSnapshot screenshotTask(int taskId) {
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.screenshotTask: taskId=%d", taskId);
return ActivityTaskManager.getService().takeTaskSnapshot(taskId);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to screenshot task", e);
@@ -587,12 +631,19 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
@Override
public void setInputConsumerEnabled(boolean enabled) {
mExecutor.execute(() -> {
- if (mFinishCB == null || !enabled) return;
+ if (mFinishCB == null || !enabled) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setInputConsumerEnabled: skip, cb?=%b enabled?=%b",
+ mFinishCB != null, enabled);
+ return;
+ }
// transient launches don't receive focus automatically. Since we are taking over
// the gesture now, take focus explicitly.
// This also moves recents back to top if the user gestured before a switch
// animation finished.
try {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setInputConsumerEnabled: set focus to recents");
ActivityTaskManager.getService().setFocusedTask(mRecentsTaskId);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to set focused task", e);
@@ -607,6 +658,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
@Override
public void setFinishTaskTransaction(int taskId,
PictureInPictureSurfaceTransaction finishTransaction, SurfaceControl overlay) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.setFinishTaskTransaction: taskId=%d", taskId);
mExecutor.execute(() -> {
if (mFinishCB == null) return;
mPipTransaction = finishTransaction;
@@ -624,6 +677,9 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
Slog.e(TAG, "Duplicate call to finish");
return;
}
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.finishInner: toHome=%b userLeaveHint=%b willFinishToHome=%b",
+ toHome, sendUserLeaveHint, mWillFinishToHome);
final Transitions.TransitionFinishCallback finishCB = mFinishCB;
mFinishCB = null;
@@ -635,6 +691,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
else wct.restoreTransientOrder(mRecentsTask);
}
if (!toHome && !mWillFinishToHome && mPausingTasks != null && mState == STATE_NORMAL) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " returning to app");
// The gesture is returning to the pausing-task(s) rather than continuing with
// recents, so end the transition by moving the app back to the top (and also
// re-showing it's task).
@@ -647,6 +704,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
wct.restoreTransientOrder(mRecentsTask);
}
} else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " 3p launching home");
// Special situation where 3p launcher was changed during recents (this happens
// during tapltests...). Here we get both "return to home" AND "home opening".
// This is basically going home, but we have to restore the recents and home order.
@@ -665,6 +723,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
wct.restoreTransientOrder(mRecentsTask);
}
} else {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION, " normal finish");
// The general case: committing to recents, going home, or switching tasks.
for (int i = 0; i < mOpeningTasks.size(); ++i) {
t.show(mOpeningTasks.get(i).mTaskSurface);
@@ -721,6 +780,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
*/
@Override
public void detachNavigationBarFromApp(boolean moveHomeToTop) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
+ "RecentsController.detachNavigationBarFromApp");
mExecutor.execute(() -> {
if (mTransition == null) return;
try {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index bdb7d44bad32..08b0bf74f413 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -429,6 +429,7 @@ public class Transitions implements RemoteCallable<Transitions> {
&& (change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) == 0) {
t.setAlpha(leash, 0.f);
}
+ finishT.show(leash);
} else if (mode == TRANSIT_CLOSE || mode == TRANSIT_TO_BACK) {
finishT.hide(leash);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index 8e8facadfd5d..e8a6a159cb19 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -127,7 +127,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
if (decoration == null) {
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
} else {
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
}
@@ -139,7 +139,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) return;
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
@Override
@@ -192,7 +192,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragPositioningCallback(taskPositioner);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
- windowDecoration.relayout(taskInfo, startT, finishT);
+ windowDecoration.relayout(taskInfo, startT, finishT,
+ false /* applyStartTransactionOnDraw */);
setupCaptionColor(taskInfo, windowDecoration);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index dfde7e6feff5..116af7094e13 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -90,15 +90,15 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
@Override
void relayout(RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- relayout(taskInfo, t, t);
- mSyncQueue.runInSync(transaction -> {
- transaction.merge(t);
- t.close();
- });
+ // Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
+ // synced with the buffer transaction (that draws the View). Both will be shown on screen
+ // at the same, whereas applying them independently causes flickering. See b/270202228.
+ relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
}
void relayout(RunningTaskInfo taskInfo,
- SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
+ boolean applyStartTransactionOnDraw) {
final int shadowRadiusID = taskInfo.isFocused
? R.dimen.freeform_decor_shadow_focused_thickness
: R.dimen.freeform_decor_shadow_unfocused_thickness;
@@ -115,6 +115,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
mRelayoutParams.mLayoutResId = R.layout.caption_window_decor;
mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
+ mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index e137bc462607..49a5eac5fd07 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -247,7 +247,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
if (decoration == null) {
createWindowDecoration(taskInfo, taskSurface, startT, finishT);
} else {
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
}
@@ -259,7 +259,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
if (decoration == null) return;
- decoration.relayout(taskInfo, startT, finishT);
+ decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */);
}
@Override
@@ -781,7 +781,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
windowDecoration.setDragPositioningCallback(taskPositioner);
windowDecoration.setDragDetector(touchEventListener.mDragDetector);
- windowDecoration.relayout(taskInfo, startT, finishT);
+ windowDecoration.relayout(taskInfo, startT, finishT,
+ false /* applyStartTransactionOnDraw */);
incrementEventReceiverTasks(taskInfo.displayId);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 67e99d73b811..af3fb0ead55c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -173,15 +173,15 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- relayout(taskInfo, t, t);
- mSyncQueue.runInSync(transaction -> {
- transaction.merge(t);
- t.close();
- });
+ // Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
+ // synced with the buffer transaction (that draws the View). Both will be shown on screen
+ // at the same, whereas applying them independently causes flickering. See b/270202228.
+ relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */);
}
void relayout(ActivityManager.RunningTaskInfo taskInfo,
- SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+ SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
+ boolean applyStartTransactionOnDraw) {
final int shadowRadiusID = taskInfo.isFocused
? R.dimen.freeform_decor_shadow_focused_thickness
: R.dimen.freeform_decor_shadow_unfocused_thickness;
@@ -216,6 +216,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mRelayoutParams.mLayoutResId = windowDecorLayoutId;
mRelayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
+ mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 8b35694ff8fd..9a1b4ffbd50c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -238,30 +238,6 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
startT.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
.show(mCaptionContainerSurface);
- if (mCaptionWindowManager == null) {
- // Put caption under a container surface because ViewRootImpl sets the destination frame
- // of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
- mCaptionWindowManager = new WindowlessWindowManager(
- mTaskInfo.getConfiguration(), mCaptionContainerSurface,
- null /* hostInputToken */);
- }
-
- // Caption view
- mCaptionWindowManager.setConfiguration(taskConfig);
- final WindowManager.LayoutParams lp =
- new WindowManager.LayoutParams(captionWidth, captionHeight,
- WindowManager.LayoutParams.TYPE_APPLICATION,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
- lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
- lp.setTrustedOverlay();
- if (mViewHost == null) {
- mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
- mCaptionWindowManager);
- mViewHost.setView(outResult.mRootView, lp);
- } else {
- mViewHost.relayout(lp);
- }
-
if (ViewRootImpl.CAPTION_ON_SHELL) {
outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
@@ -287,6 +263,36 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
.show(mTaskSurface);
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
+
+ if (mCaptionWindowManager == null) {
+ // Put caption under a container surface because ViewRootImpl sets the destination frame
+ // of windowless window layers and BLASTBufferQueue#update() doesn't support offset.
+ mCaptionWindowManager = new WindowlessWindowManager(
+ mTaskInfo.getConfiguration(), mCaptionContainerSurface,
+ null /* hostInputToken */);
+ }
+
+ // Caption view
+ mCaptionWindowManager.setConfiguration(taskConfig);
+ final WindowManager.LayoutParams lp =
+ new WindowManager.LayoutParams(captionWidth, captionHeight,
+ WindowManager.LayoutParams.TYPE_APPLICATION,
+ WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, PixelFormat.TRANSPARENT);
+ lp.setTitle("Caption of Task=" + mTaskInfo.taskId);
+ lp.setTrustedOverlay();
+ if (mViewHost == null) {
+ mViewHost = mSurfaceControlViewHostFactory.create(mDecorWindowContext, mDisplay,
+ mCaptionWindowManager);
+ if (params.mApplyStartTransactionOnDraw) {
+ mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
+ }
+ mViewHost.setView(outResult.mRootView, lp);
+ } else {
+ if (params.mApplyStartTransactionOnDraw) {
+ mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
+ }
+ mViewHost.relayout(lp);
+ }
}
/**
@@ -411,6 +417,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
int mCaptionX;
int mCaptionY;
+ boolean mApplyStartTransactionOnDraw;
+
void reset() {
mLayoutResId = Resources.ID_NULL;
mCaptionHeightId = Resources.ID_NULL;
@@ -419,6 +427,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionX = 0;
mCaptionY = 0;
+
+ mApplyStartTransactionOnDraw = false;
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index c416ad011c4e..45024f387c25 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -223,15 +223,6 @@ fun FlickerTest.splitAppLayerBoundsChanges(
portraitPosTop,
scenario.endRotation
)
- .then()
- .isInvisible(component)
- .then()
- .splitAppLayerBoundsSnapToDivider(
- component,
- landscapePosLeft,
- portraitPosTop,
- scenario.endRotation
- )
} else {
splitAppLayerBoundsSnapToDivider(
component,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
index 62936e0f5ca8..625987a2e7ef 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
@@ -293,7 +293,7 @@ internal object SplitScreenUtils {
wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
- dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3), 2000)
+ dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3), 200)
wmHelper
.StateSyncBuilder()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index d95c7a488ea1..3d8bd3854a45 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -135,12 +135,15 @@ public class BackAnimationControllerTest extends ShellTestCase {
mShellExecutor.flushAll();
}
- private void createNavigationInfo(int backType, boolean enableAnimation) {
+ private void createNavigationInfo(int backType,
+ boolean enableAnimation,
+ boolean isAnimationCallback) {
BackNavigationInfo.Builder builder = new BackNavigationInfo.Builder()
.setType(backType)
.setOnBackNavigationDone(new RemoteCallback((bundle) -> {}))
.setOnBackInvokedCallback(mAppCallback)
- .setPrepareRemoteAnimation(enableAnimation);
+ .setPrepareRemoteAnimation(enableAnimation)
+ .setAnimationCallback(isAnimationCallback);
createNavigationInfo(builder);
}
@@ -218,7 +221,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
@Test
public void backToHome_dispatchesEvents() throws RemoteException {
registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
- createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, true);
+ createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ /* enableAnimation = */ true,
+ /* isAnimationCallback = */ false);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
@@ -240,6 +245,32 @@ public class BackAnimationControllerTest extends ShellTestCase {
}
@Test
+ public void backToHomeWithAnimationCallback_dispatchesEvents() throws RemoteException {
+ registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
+ createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ /* enableAnimation = */ true,
+ /* isAnimationCallback = */ true);
+
+ doMotionEvent(MotionEvent.ACTION_DOWN, 0);
+
+ // Check that back start and progress is dispatched when first move.
+ doMotionEvent(MotionEvent.ACTION_MOVE, 100, 3000);
+
+ simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME);
+
+ verify(mAnimatorCallback).onBackStarted(any(BackMotionEvent.class));
+ verify(mBackAnimationRunner).onAnimationStart(anyInt(), any(), any(), any(), any());
+ ArgumentCaptor<BackMotionEvent> backEventCaptor =
+ ArgumentCaptor.forClass(BackMotionEvent.class);
+ verify(mAnimatorCallback, atLeastOnce()).onBackProgressed(backEventCaptor.capture());
+
+ // Check that back invocation is dispatched.
+ mController.setTriggerBack(true); // Fake trigger back
+ doMotionEvent(MotionEvent.ACTION_UP, 0);
+ verify(mAnimatorCallback).onBackInvoked();
+ }
+
+ @Test
public void animationDisabledFromSettings() throws RemoteException {
// Toggle the setting off
Settings.Global.putString(mContentResolver, Settings.Global.ENABLE_BACK_ANIMATION, "0");
@@ -254,7 +285,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
ArgumentCaptor<BackMotionEvent> backEventCaptor =
ArgumentCaptor.forClass(BackMotionEvent.class);
- createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, false);
+ createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ /* enableAnimation = */ false,
+ /* isAnimationCallback = */ false);
triggerBackGesture();
releaseBackGesture();
@@ -271,7 +304,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
@Test
public void ignoresGesture_transitionInProgress() throws RemoteException {
registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
- createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, true);
+ createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ /* enableAnimation = */ true,
+ /* isAnimationCallback = */ false);
triggerBackGesture();
simulateRemoteAnimationStart(BackNavigationInfo.TYPE_RETURN_TO_HOME);
@@ -309,7 +344,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
@Test
public void acceptsGesture_transitionTimeout() throws RemoteException {
registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
- createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, true);
+ createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ /* enableAnimation = */ true,
+ /* isAnimationCallback = */ false);
// In case it is still running in animation.
doNothing().when(mAnimatorCallback).onBackInvoked();
@@ -334,7 +371,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
public void cancelBackInvokeWhenLostFocus() throws RemoteException {
registerAnimation(BackNavigationInfo.TYPE_RETURN_TO_HOME);
- createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME, true);
+ createNavigationInfo(BackNavigationInfo.TYPE_RETURN_TO_HOME,
+ /* enableAnimation = */ true,
+ /* isAnimationCallback = */ false);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
// Check that back start and progress is dispatched when first move.
@@ -454,7 +493,9 @@ public class BackAnimationControllerTest extends ShellTestCase {
mController.registerAnimation(type, animationRunner);
- createNavigationInfo(type, true);
+ createNavigationInfo(type,
+ /* enableAnimation = */ true,
+ /* isAnimationCallback = */ false);
doMotionEvent(MotionEvent.ACTION_DOWN, 0);
@@ -473,11 +514,15 @@ public class BackAnimationControllerTest extends ShellTestCase {
}
private void doMotionEvent(int actionDown, int coordinate) {
+ doMotionEvent(actionDown, coordinate, 0);
+ }
+
+ private void doMotionEvent(int actionDown, int coordinate, float velocity) {
mController.onMotionEvent(
/* touchX */ coordinate,
/* touchY */ coordinate,
- /* velocityX = */ 0,
- /* velocityY = */ 0,
+ /* velocityX = */ velocity,
+ /* velocityY = */ velocity,
/* keyAction */ actionDown,
/* swipeEdge */ BackEvent.EDGE_LEFT);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
index 919bf0665b5e..4a55429eacb6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/bubbles/BubbleDataTest.java
@@ -16,8 +16,6 @@
package com.android.wm.shell.bubbles;
-import static com.android.wm.shell.bubbles.Bubble.KEY_APP_BUBBLE;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -185,7 +183,10 @@ public class BubbleDataTest extends ShellTestCase {
Intent appBubbleIntent = new Intent(mContext, BubblesTestActivity.class);
appBubbleIntent.setPackage(mContext.getPackageName());
- mAppBubble = new Bubble(appBubbleIntent, new UserHandle(1), mock(Icon.class),
+ mAppBubble = Bubble.createAppBubble(
+ appBubbleIntent,
+ new UserHandle(1),
+ mock(Icon.class),
mMainExecutor);
mPositioner = new TestableBubblePositioner(mContext,
@@ -1101,14 +1102,15 @@ public class BubbleDataTest extends ShellTestCase {
@Test
public void test_removeAppBubble_skipsOverflow() {
+ String appBubbleKey = mAppBubble.getKey();
mBubbleData.notificationEntryUpdated(mAppBubble, true /* suppressFlyout*/,
false /* showInShade */);
- assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isEqualTo(mAppBubble);
+ assertThat(mBubbleData.getBubbleInStackWithKey(appBubbleKey)).isEqualTo(mAppBubble);
- mBubbleData.dismissBubbleWithKey(KEY_APP_BUBBLE, Bubbles.DISMISS_USER_GESTURE);
+ mBubbleData.dismissBubbleWithKey(appBubbleKey, Bubbles.DISMISS_USER_GESTURE);
- assertThat(mBubbleData.getOverflowBubbleWithKey(KEY_APP_BUBBLE)).isNull();
- assertThat(mBubbleData.getBubbleInStackWithKey(KEY_APP_BUBBLE)).isNull();
+ assertThat(mBubbleData.getOverflowBubbleWithKey(appBubbleKey)).isNull();
+ assertThat(mBubbleData.getBubbleInStackWithKey(appBubbleKey)).isNull();
}
private void verifyUpdateReceived() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index c1e53a90b7e0..fc4bfd9754a0 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -33,6 +33,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.content.Context;
@@ -42,6 +43,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
+import android.view.AttachedSurfaceControl;
import android.view.Display;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
@@ -97,6 +99,8 @@ public class WindowDecorationTests extends ShellTestCase {
@Mock
private SurfaceControlViewHost mMockSurfaceControlViewHost;
@Mock
+ private AttachedSurfaceControl mMockRootSurfaceControl;
+ @Mock
private TestView mMockView;
@Mock
private WindowContainerTransaction mMockWindowContainerTransaction;
@@ -129,6 +133,8 @@ public class WindowDecorationTests extends ShellTestCase {
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any());
+ when(mMockSurfaceControlViewHost.getRootSurfaceControl())
+ .thenReturn(mMockRootSurfaceControl);
}
@Test
@@ -461,6 +467,43 @@ public class WindowDecorationTests extends ShellTestCase {
verify(mMockSurfaceControlStartT).show(captionContainerSurface);
}
+ @Test
+ public void testRelayout_applyTransactionInSyncWithDraw() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+
+ final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder decorContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(decorContainerSurface);
+ mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+ final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+ final SurfaceControl.Builder captionContainerSurfaceBuilder =
+ createMockSurfaceControlBuilder(captionContainerSurface);
+ mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+ final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+ mMockSurfaceControlTransactions.add(t);
+ final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+ new ActivityManager.TaskDescription.Builder()
+ .setBackgroundColor(Color.YELLOW);
+ final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setTaskDescriptionBuilder(taskDescriptionBuilder)
+ .setBounds(TASK_BOUNDS)
+ .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
+ .setVisible(true)
+ .build();
+ taskInfo.isFocused = true;
+ taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2;
+ final SurfaceControl taskSurface = mock(SurfaceControl.class);
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+ windowDecor.relayout(taskInfo, true /* applyStartTransactionOnDraw */);
+
+ verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
+ }
+
private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(),
@@ -516,6 +559,12 @@ public class WindowDecorationTests extends ShellTestCase {
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
+ relayout(taskInfo, false /* applyStartTransactionOnDraw */);
+ }
+
+ void relayout(ActivityManager.RunningTaskInfo taskInfo,
+ boolean applyStartTransactionOnDraw) {
+ mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT,
mMockWindowContainerTransaction, mMockView, mRelayoutResult);
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 70c36a5803ee..34af1f9ea039 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -399,7 +399,7 @@ cc_defaults {
"libharfbuzz_ng",
"libimage_io",
"libjpeg",
- "libjpegrecoverymap",
+ "libultrahdr",
"liblog",
"libminikin",
"libz",
diff --git a/libs/hwui/jni/YuvToJpegEncoder.cpp b/libs/hwui/jni/YuvToJpegEncoder.cpp
index 8874ef1d2fe0..69418b09fee6 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.cpp
+++ b/libs/hwui/jni/YuvToJpegEncoder.cpp
@@ -298,39 +298,39 @@ void Yuv422IToJpegEncoder::configSamplingFactors(jpeg_compress_struct* cinfo) {
}
///////////////////////////////////////////////////////////////////////////////
-using namespace android::jpegrecoverymap;
+using namespace android::ultrahdr;
-jpegr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) {
+ultrahdr_color_gamut P010Yuv420ToJpegREncoder::findColorGamut(JNIEnv* env, int aDataSpace) {
switch (aDataSpace & ADataSpace::STANDARD_MASK) {
case ADataSpace::STANDARD_BT709:
- return jpegr_color_gamut::JPEGR_COLORGAMUT_BT709;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709;
case ADataSpace::STANDARD_DCI_P3:
- return jpegr_color_gamut::JPEGR_COLORGAMUT_P3;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_P3;
case ADataSpace::STANDARD_BT2020:
- return jpegr_color_gamut::JPEGR_COLORGAMUT_BT2100;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100;
default:
jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(IllegalArgumentException,
"The requested color gamut is not supported by JPEG/R.");
}
- return jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED;
+ return ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED;
}
-jpegr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNIEnv* env,
+ultrahdr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNIEnv* env,
int aDataSpace) {
switch (aDataSpace & ADataSpace::TRANSFER_MASK) {
case ADataSpace::TRANSFER_ST2084:
- return jpegr_transfer_function::JPEGR_TF_PQ;
+ return ultrahdr_transfer_function::ULTRAHDR_TF_PQ;
case ADataSpace::TRANSFER_HLG:
- return jpegr_transfer_function::JPEGR_TF_HLG;
+ return ultrahdr_transfer_function::ULTRAHDR_TF_HLG;
default:
jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException");
env->ThrowNew(IllegalArgumentException,
"The requested HDR transfer function is not supported by JPEG/R.");
}
- return jpegr_transfer_function::JPEGR_TF_UNSPECIFIED;
+ return ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED;
}
bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env,
@@ -344,13 +344,13 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env,
return false;
}
- jpegr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace);
- jpegr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace);
- jpegr_transfer_function hdrTransferFunction = findHdrTransferFunction(env, hdrColorSpace);
+ ultrahdr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace);
+ ultrahdr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace);
+ ultrahdr_transfer_function hdrTransferFunction = findHdrTransferFunction(env, hdrColorSpace);
- if (hdrColorGamut == jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED
- || sdrColorGamut == jpegr_color_gamut::JPEGR_COLORGAMUT_UNSPECIFIED
- || hdrTransferFunction == jpegr_transfer_function::JPEGR_TF_UNSPECIFIED) {
+ if (hdrColorGamut == ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED
+ || sdrColorGamut == ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_UNSPECIFIED
+ || hdrTransferFunction == ultrahdr_transfer_function::ULTRAHDR_TF_UNSPECIFIED) {
return false;
}
diff --git a/libs/hwui/jni/YuvToJpegEncoder.h b/libs/hwui/jni/YuvToJpegEncoder.h
index d22a26c83567..8ef780547184 100644
--- a/libs/hwui/jni/YuvToJpegEncoder.h
+++ b/libs/hwui/jni/YuvToJpegEncoder.h
@@ -2,7 +2,7 @@
#define _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_
#include <android/data_space.h>
-#include <jpegrecoverymap/jpegr.h>
+#include <ultrahdr/jpegr.h>
extern "C" {
#include "jpeglib.h"
@@ -103,7 +103,7 @@ public:
* @param aDataSpace data space defined in data_space.h.
* @return color gamut for JPEG/R.
*/
- static android::jpegrecoverymap::jpegr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
+ static android::ultrahdr::ultrahdr_color_gamut findColorGamut(JNIEnv* env, int aDataSpace);
/** Map data space (defined in DataSpace.java and data_space.h) to the transfer function
* used in JPEG/R
@@ -112,7 +112,7 @@ public:
* @param aDataSpace data space defined in data_space.h.
* @return color gamut for JPEG/R.
*/
- static android::jpegrecoverymap::jpegr_transfer_function findHdrTransferFunction(
+ static android::ultrahdr::ultrahdr_transfer_function findHdrTransferFunction(
JNIEnv* env, int aDataSpace);
};