summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java35
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java68
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java124
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java196
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt13
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt7
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt (renamed from libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt)47
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt44
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt90
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt94
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java4
-rwxr-xr-xlibs/androidfw/ApkAssets.cpp6
-rw-r--r--libs/androidfw/AssetManager2.cpp86
-rw-r--r--libs/androidfw/AssetsProvider.cpp29
-rw-r--r--libs/androidfw/include/androidfw/ApkAssets.h12
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h2
-rw-r--r--libs/androidfw/include/androidfw/AssetsProvider.h10
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp8
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp3
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp12
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp68
-rw-r--r--libs/hwui/renderthread/VulkanManager.h4
33 files changed, 728 insertions, 323 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index 7376d9898ab8..cc353dc991e3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -25,6 +25,7 @@ import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.transition.Transitions;
import java.util.Optional;
@@ -44,6 +45,7 @@ public class ShellInitImpl {
private final FullscreenTaskListener mFullscreenTaskListener;
private final ShellExecutor mMainExecutor;
private final Transitions mTransitions;
+ private final Optional<StartingSurface> mStartingSurfaceOptional;
private final InitImpl mImpl = new InitImpl();
@@ -53,6 +55,7 @@ public class ShellInitImpl {
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
+ Optional<StartingSurface> startingSurfaceOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
ShellExecutor mainExecutor) {
@@ -62,6 +65,7 @@ public class ShellInitImpl {
legacySplitScreenOptional,
splitScreenOptional,
appPairsOptional,
+ startingSurfaceOptional,
fullscreenTaskListener,
transitions,
mainExecutor).mImpl;
@@ -73,6 +77,7 @@ public class ShellInitImpl {
Optional<LegacySplitScreenController> legacySplitScreenOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<AppPairsController> appPairsOptional,
+ Optional<StartingSurface> startingSurfaceOptional,
FullscreenTaskListener fullscreenTaskListener,
Transitions transitions,
ShellExecutor mainExecutor) {
@@ -85,6 +90,7 @@ public class ShellInitImpl {
mFullscreenTaskListener = fullscreenTaskListener;
mTransitions = transitions;
mMainExecutor = mainExecutor;
+ mStartingSurfaceOptional = startingSurfaceOptional;
}
private void init() {
@@ -93,6 +99,7 @@ public class ShellInitImpl {
mShellTaskOrganizer.addListenerForType(
mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
+ mStartingSurfaceOptional.ifPresent(mShellTaskOrganizer::initStartingSurface);
// Register the shell organizer
mShellTaskOrganizer.registerOrganizer();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index efc55c4fbe31..9ddeb2fc6e1e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -44,7 +44,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
-import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
+import com.android.wm.shell.startingsurface.StartingSurface;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -110,7 +110,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
private final ArrayMap<IBinder, TaskListener> mLaunchCookieToListener = new ArrayMap<>();
private final Object mLock = new Object();
- private final StartingSurfaceDrawer mStartingSurfaceDrawer;
+ private StartingSurface mStartingSurface;
/**
* In charge of showing size compat UI. Can be {@code null} if device doesn't support size
@@ -120,23 +120,19 @@ public class ShellTaskOrganizer extends TaskOrganizer {
private final SizeCompatUIController mSizeCompatUI;
public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) {
- this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */,
- new StartingSurfaceDrawer(context, mainExecutor));
+ this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */);
}
public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context, @Nullable
SizeCompatUIController sizeCompatUI) {
- this(null /* taskOrganizerController */, mainExecutor, context, sizeCompatUI,
- new StartingSurfaceDrawer(context, mainExecutor));
+ this(null /* taskOrganizerController */, mainExecutor, context, sizeCompatUI);
}
@VisibleForTesting
ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController, ShellExecutor mainExecutor,
- Context context, @Nullable SizeCompatUIController sizeCompatUI,
- StartingSurfaceDrawer startingSurfaceDrawer) {
+ Context context, @Nullable SizeCompatUIController sizeCompatUI) {
super(taskOrganizerController, mainExecutor);
mSizeCompatUI = sizeCompatUI;
- mStartingSurfaceDrawer = startingSurfaceDrawer;
}
@Override
@@ -163,6 +159,15 @@ public class ShellTaskOrganizer extends TaskOrganizer {
}
/**
+ * @hide
+ */
+ public void initStartingSurface(StartingSurface startingSurface) {
+ synchronized (mLock) {
+ mStartingSurface = startingSurface;
+ }
+ }
+
+ /**
* Adds a listener for a specific task id.
*/
public void addListenerForTaskId(TaskListener listener, int taskId) {
@@ -254,17 +259,23 @@ public class ShellTaskOrganizer extends TaskOrganizer {
@Override
public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
- mStartingSurfaceDrawer.addStartingWindow(info, appToken);
+ if (mStartingSurface != null) {
+ mStartingSurface.addStartingWindow(info, appToken);
+ }
}
@Override
public void removeStartingWindow(int taskId) {
- mStartingSurfaceDrawer.removeStartingWindow(taskId);
+ if (mStartingSurface != null) {
+ mStartingSurface.removeStartingWindow(taskId);
+ }
}
@Override
public void copySplashScreenView(int taskId) {
- mStartingSurfaceDrawer.copySplashScreenView(taskId);
+ if (mStartingSurface != null) {
+ mStartingSurface.copySplashScreenView(taskId);
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
index 5992447bd6da..46884fefd69c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java
@@ -157,6 +157,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
});
options.setLaunchCookie(launchCookie);
options.setLaunchWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ options.setRemoveWithTaskOrganizer(true);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
index 19c3cf9c462a..57a2b6c7b9db 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleFlyoutView.java
@@ -227,24 +227,30 @@ public class BubbleFlyoutView extends FrameLayout {
/*
* Fade animation for consecutive flyouts.
*/
- void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, float stackY) {
+ void animateUpdate(Bubble.FlyoutMessage flyoutMessage, float parentWidth, PointF stackPos,
+ boolean hideDot) {
final Runnable afterFadeOut = () -> {
updateFlyoutMessage(flyoutMessage, parentWidth);
// Wait for TextViews to layout with updated height.
post(() -> {
- mFlyoutY = stackY + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
- fade(true /* in */, () -> {} /* after */);
+ fade(true /* in */, stackPos, hideDot, () -> {} /* after */);
} /* after */ );
};
- fade(false /* in */, afterFadeOut);
+ fade(false /* in */, stackPos, hideDot, afterFadeOut);
}
/*
* Fade-out above or fade-in from below.
*/
- private void fade(boolean in, Runnable afterFade) {
+ private void fade(boolean in, PointF stackPos, boolean hideDot, Runnable afterFade) {
+ mFlyoutY = stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
+
setAlpha(in ? 0f : 1f);
setTranslationY(in ? mFlyoutY + FLYOUT_FADE_Y : mFlyoutY);
+ updateFlyoutX(stackPos.x);
+ setTranslationX(mRestingTranslationX);
+ updateDot(stackPos, hideDot);
+
animate()
.alpha(in ? 1f : 0f)
.setDuration(in ? FLYOUT_FADE_IN_DURATION : FLYOUT_FADE_OUT_DURATION)
@@ -287,6 +293,33 @@ public class BubbleFlyoutView extends FrameLayout {
mMessageText.setText(flyoutMessage.message);
}
+ void updateFlyoutX(float stackX) {
+ // Calculate the translation required to position the flyout next to the bubble stack,
+ // with the desired padding.
+ mRestingTranslationX = mArrowPointingLeft
+ ? stackX + mBubbleSize + mFlyoutSpaceFromBubble
+ : stackX - getWidth() - mFlyoutSpaceFromBubble;
+ }
+
+ void updateDot(PointF stackPos, boolean hideDot) {
+ // Calculate the difference in size between the flyout and the 'dot' so that we can
+ // transform into the dot later.
+ final float newDotSize = hideDot ? 0f : mNewDotSize;
+ mFlyoutToDotWidthDelta = getWidth() - newDotSize;
+ mFlyoutToDotHeightDelta = getHeight() - newDotSize;
+
+ // Calculate the translation values needed to be in the correct 'new dot' position.
+ final float adjustmentForScaleAway = hideDot ? 0f : (mOriginalDotSize / 2f);
+ final float dotPositionX = stackPos.x + mDotCenter[0] - adjustmentForScaleAway;
+ final float dotPositionY = stackPos.y + mDotCenter[1] - adjustmentForScaleAway;
+
+ final float distanceFromFlyoutLeftToDotCenterX = mRestingTranslationX - dotPositionX;
+ final float distanceFromLayoutTopToDotCenterY = mFlyoutY - dotPositionY;
+
+ mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX;
+ mTranslationYWhenDot = -distanceFromLayoutTopToDotCenterY;
+ }
+
/** Configures the flyout, collapsed into dot form. */
void setupFlyoutStartingAsDot(
Bubble.FlyoutMessage flyoutMessage,
@@ -322,29 +355,8 @@ public class BubbleFlyoutView extends FrameLayout {
mFlyoutY =
stackPos.y + (mBubbleSize - mFlyoutTextContainer.getHeight()) / 2f;
setTranslationY(mFlyoutY);
-
- // Calculate the translation required to position the flyout next to the bubble stack,
- // with the desired padding.
- mRestingTranslationX = mArrowPointingLeft
- ? stackPos.x + mBubbleSize + mFlyoutSpaceFromBubble
- : stackPos.x - getWidth() - mFlyoutSpaceFromBubble;
-
- // Calculate the difference in size between the flyout and the 'dot' so that we can
- // transform into the dot later.
- final float newDotSize = hideDot ? 0f : mNewDotSize;
- mFlyoutToDotWidthDelta = getWidth() - newDotSize;
- mFlyoutToDotHeightDelta = getHeight() - newDotSize;
-
- // Calculate the translation values needed to be in the correct 'new dot' position.
- final float adjustmentForScaleAway = hideDot ? 0f : (mOriginalDotSize / 2f);
- final float dotPositionX = stackPos.x + mDotCenter[0] - adjustmentForScaleAway;
- final float dotPositionY = stackPos.y + mDotCenter[1] - adjustmentForScaleAway;
-
- final float distanceFromFlyoutLeftToDotCenterX = mRestingTranslationX - dotPositionX;
- final float distanceFromLayoutTopToDotCenterY = mFlyoutY - dotPositionY;
-
- mTranslationXWhenDot = -distanceFromFlyoutLeftToDotCenterX;
- mTranslationYWhenDot = -distanceFromLayoutTopToDotCenterY;
+ updateFlyoutX(stackPos.x);
+ updateDot(stackPos, hideDot);
if (onLayoutComplete != null) {
onLayoutComplete.run();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index a8ab4064455c..78820a8fa870 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -2431,7 +2431,7 @@ public class BubbleStackView extends FrameLayout
if (mFlyout.getVisibility() == View.VISIBLE) {
mFlyout.animateUpdate(bubble.getFlyoutMessage(), getWidth(),
- mStackAnimationController.getStackPosition().y);
+ mStackAnimationController.getStackPosition(), !bubble.showDot());
} else {
mFlyout.setVisibility(INVISIBLE);
mFlyout.setupFlyoutStartingAsDot(bubble.getFlyoutMessage(),
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index fb70cbe502b0..4bb8e9b6581f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -39,12 +39,12 @@ import android.view.IWindowSession;
import android.view.IWindowSessionCallback;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
+import android.view.ScrollCaptureResponse;
import android.view.SurfaceControl;
-import android.view.SurfaceSession;
import android.view.SurfaceControlViewHost;
+import android.view.SurfaceSession;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowlessWindowManager;
import android.window.ClientWindowFrames;
@@ -371,7 +371,11 @@ public class SystemWindows {
@Override
public void requestScrollCapture(IScrollCaptureCallbacks callbacks) {
try {
- callbacks.onUnavailable();
+ callbacks.onScrollCaptureResponse(
+ new ScrollCaptureResponse.Builder()
+ .setDescription("Not Implemented")
+ .build());
+
} catch (RemoteException ex) {
// ignore
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 22c97515ad76..bbfbc4098d92 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -362,8 +362,9 @@ class StageCoordinator implements SplitLayout.LayoutChangeListener,
@Override
public void onSnappedToDismiss(boolean bottomOrRight) {
- final boolean mainStageToTop = bottomOrRight
- && mSideStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
+ final boolean mainStageToTop =
+ bottomOrRight ? mSideStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT
+ : mSideStagePosition == STAGE_POSITION_TOP_OR_LEFT;
exitSplitScreen(mainStageToTop ? mMainStage : mSideStage);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
new file mode 100644
index 000000000000..2c4ceffcb8f5
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
@@ -0,0 +1,39 @@
+/*
+ * 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.wm.shell.startingsurface;
+
+import android.os.IBinder;
+import android.window.StartingWindowInfo;
+
+/**
+ * Interface to engage starting window feature.
+ */
+public interface StartingSurface {
+ /**
+ * Called when a task need a starting window.
+ */
+ void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken);
+ /**
+ * Called when the content of a task is ready to show, starting window can be removed.
+ */
+ void removeStartingWindow(int taskId);
+ /**
+ * Called when the Task wants to copy the splash screen.
+ * @param taskId
+ */
+ void copySplashScreenView(int taskId);
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 5332291fd1bd..814407164750 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -16,15 +16,9 @@
package com.android.wm.shell.startingsurface;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.res.Configuration.EMPTY;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
-import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
@@ -37,7 +31,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
-import android.os.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
@@ -46,7 +39,6 @@ import android.view.WindowManager;
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.StartingWindowInfo;
-import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
import com.android.internal.R;
@@ -56,19 +48,13 @@ import com.android.wm.shell.common.ShellExecutor;
import java.util.function.Consumer;
/**
- * Implementation to draw the starting window to an application, and remove the starting window
- * until the application displays its own window.
- *
- * When receive {@link TaskOrganizer#addStartingWindow} callback, use this class to create a
- * starting window and attached to the Task, then when the Task want to remove the starting window,
- * the TaskOrganizer will receive {@link TaskOrganizer#removeStartingWindow} callback then use this
- * class to remove the starting window of the Task.
+ * A class which able to draw splash screen or snapshot as the starting window for a task.
* @hide
*/
public class StartingSurfaceDrawer {
static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
- static final boolean DEBUG_SPLASH_SCREEN = false;
- static final boolean DEBUG_TASK_SNAPSHOT = false;
+ static final boolean DEBUG_SPLASH_SCREEN = StartingWindowController.DEBUG_SPLASH_SCREEN;
+ static final boolean DEBUG_TASK_SNAPSHOT = StartingWindowController.DEBUG_TASK_SNAPSHOT;
private final Context mContext;
private final DisplayManager mDisplayManager;
@@ -107,106 +93,10 @@ public class StartingSurfaceDrawer {
return context.createDisplayContext(targetDisplay);
}
- private static class PreferredStartingTypeHelper {
- private static final int STARTING_TYPE_NO = 0;
- private static final int STARTING_TYPE_SPLASH_SCREEN = 1;
- private static final int STARTING_TYPE_SNAPSHOT = 2;
-
- TaskSnapshot mSnapshot;
- int mPreferredType;
-
- PreferredStartingTypeHelper(StartingWindowInfo taskInfo) {
- final int parameter = taskInfo.startingWindowTypeParameter;
- final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
- final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
- final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
- final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
- final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
- mPreferredType = preferredStartingWindowType(taskInfo, newTask, taskSwitch,
- processRunning, allowTaskSnapshot, activityCreated);
- }
-
- // reference from ActivityRecord#getStartingWindowType
- private int preferredStartingWindowType(StartingWindowInfo windowInfo,
- boolean newTask, boolean taskSwitch, boolean processRunning,
- boolean allowTaskSnapshot, boolean activityCreated) {
- if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
- Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
- + " taskSwitch " + taskSwitch
- + " processRunning " + processRunning
- + " allowTaskSnapshot " + allowTaskSnapshot
- + " activityCreated " + activityCreated);
- }
-
- if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
- return STARTING_TYPE_SPLASH_SCREEN;
- } else if (taskSwitch && allowTaskSnapshot) {
- final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId);
- if (isSnapshotCompatible(windowInfo, snapshot)) {
- return STARTING_TYPE_SNAPSHOT;
- }
- if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) {
- return STARTING_TYPE_SPLASH_SCREEN;
- }
- return STARTING_TYPE_NO;
- } else {
- return STARTING_TYPE_NO;
- }
- }
-
- /**
- * Returns {@code true} if the task snapshot is compatible with this activity (at least the
- * rotation must be the same).
- */
- private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) {
- if (snapshot == null) {
- if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
- Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
- }
- return false;
- }
-
- final int taskRotation = windowInfo.taskInfo.configuration
- .windowConfiguration.getRotation();
- final int snapshotRotation = snapshot.getRotation();
- if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
- Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
- + " snapshot " + snapshotRotation);
- }
- return taskRotation == snapshotRotation;
- }
-
- private TaskSnapshot getTaskSnapshot(int taskId) {
- if (mSnapshot != null) {
- return mSnapshot;
- }
- try {
- mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId,
- false/* isLowResolution */);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e);
- return null;
- }
- return mSnapshot;
- }
- }
-
/**
- * Called when a task need a starting window.
+ * Called when a task need a splash screen starting window.
*/
- public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
- final PreferredStartingTypeHelper helper =
- new PreferredStartingTypeHelper(windowInfo);
- if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SPLASH_SCREEN) {
- addSplashScreenStartingWindow(windowInfo, appToken);
- } else if (helper.mPreferredType == PreferredStartingTypeHelper.STARTING_TYPE_SNAPSHOT) {
- final TaskSnapshot snapshot = helper.mSnapshot;
- makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
- }
- // If prefer don't show, then don't show!
- }
-
- private void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+ public void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
final RunningTaskInfo taskInfo = windowInfo.taskInfo;
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
if (activityInfo == null) {
@@ -378,8 +268,8 @@ public class StartingSurfaceDrawer {
/**
* Called when a task need a snapshot starting window.
*/
- private void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo,
- IBinder appToken, TaskSnapshot snapshot) {
+ void makeTaskSnapshotWindow(StartingWindowInfo startingWindowInfo, IBinder appToken,
+ TaskSnapshot snapshot) {
final int taskId = startingWindowInfo.taskInfo.taskId;
final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
snapshot, mMainExecutor, () -> removeWindowSynced(taskId) /* clearWindow */);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
new file mode 100644
index 000000000000..73bf8ac90c29
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -0,0 +1,196 @@
+/*
+ * 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.wm.shell.startingsurface;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
+import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
+import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
+
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.window.StartingWindowInfo;
+import android.window.TaskOrganizer;
+import android.window.TaskSnapshot;
+
+import com.android.wm.shell.common.ShellExecutor;
+
+/**
+ * Implementation to draw the starting window to an application, and remove the starting window
+ * until the application displays its own window.
+ *
+ * When receive {@link TaskOrganizer#addStartingWindow} callback, use this class to create a
+ * starting window and attached to the Task, then when the Task want to remove the starting window,
+ * the TaskOrganizer will receive {@link TaskOrganizer#removeStartingWindow} callback then use this
+ * class to remove the starting window of the Task.
+ * @hide
+ */
+public class StartingWindowController {
+ private static final String TAG = StartingWindowController.class.getSimpleName();
+ static final boolean DEBUG_SPLASH_SCREEN = false;
+ static final boolean DEBUG_TASK_SNAPSHOT = false;
+
+ private final StartingSurfaceDrawer mStartingSurfaceDrawer;
+ private final StartingTypeChecker mStartingTypeChecker = new StartingTypeChecker();
+ private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
+
+ public StartingWindowController(Context context, ShellExecutor mainExecutor) {
+ mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, mainExecutor);
+ }
+
+ /**
+ * Provide the implementation for Shell Module.
+ */
+ public StartingSurface asStartingSurface() {
+ return mImpl;
+ }
+
+ private static class StartingTypeChecker {
+ TaskSnapshot mSnapshot;
+
+ StartingTypeChecker() { }
+
+ private void reset() {
+ mSnapshot = null;
+ }
+
+ private @StartingWindowInfo.StartingWindowType int
+ estimateStartingWindowType(StartingWindowInfo windowInfo) {
+ reset();
+ final int parameter = windowInfo.startingWindowTypeParameter;
+ final boolean newTask = (parameter & TYPE_PARAMETER_NEW_TASK) != 0;
+ final boolean taskSwitch = (parameter & TYPE_PARAMETER_TASK_SWITCH) != 0;
+ final boolean processRunning = (parameter & TYPE_PARAMETER_PROCESS_RUNNING) != 0;
+ final boolean allowTaskSnapshot = (parameter & TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT) != 0;
+ final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
+ return estimateStartingWindowType(windowInfo, newTask, taskSwitch,
+ processRunning, allowTaskSnapshot, activityCreated);
+ }
+
+ // reference from ActivityRecord#getStartingWindowType
+ private int estimateStartingWindowType(StartingWindowInfo windowInfo,
+ boolean newTask, boolean taskSwitch, boolean processRunning,
+ boolean allowTaskSnapshot, boolean activityCreated) {
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
+ + " taskSwitch " + taskSwitch
+ + " processRunning " + processRunning
+ + " allowTaskSnapshot " + allowTaskSnapshot
+ + " activityCreated " + activityCreated);
+ }
+ if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
+ return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ }
+ if (taskSwitch && allowTaskSnapshot) {
+ final TaskSnapshot snapshot = getTaskSnapshot(windowInfo.taskInfo.taskId);
+ if (isSnapshotCompatible(windowInfo, snapshot)) {
+ return STARTING_WINDOW_TYPE_SNAPSHOT;
+ }
+ if (windowInfo.taskInfo.topActivityType != ACTIVITY_TYPE_HOME) {
+ return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ }
+ }
+ return STARTING_WINDOW_TYPE_NONE;
+ }
+
+ /**
+ * Returns {@code true} if the task snapshot is compatible with this activity (at least the
+ * rotation must be the same).
+ */
+ private boolean isSnapshotCompatible(StartingWindowInfo windowInfo, TaskSnapshot snapshot) {
+ if (snapshot == null) {
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
+ }
+ return false;
+ }
+
+ final int taskRotation = windowInfo.taskInfo.configuration
+ .windowConfiguration.getRotation();
+ final int snapshotRotation = snapshot.getRotation();
+ if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
+ Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
+ + " snapshot " + snapshotRotation);
+ }
+ return taskRotation == snapshotRotation;
+ }
+
+ private TaskSnapshot getTaskSnapshot(int taskId) {
+ if (mSnapshot != null) {
+ return mSnapshot;
+ }
+ try {
+ mSnapshot = ActivityTaskManager.getService().getTaskSnapshot(taskId,
+ false/* isLowResolution */);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to get snapshot for task: " + taskId + ", from: " + e);
+ return null;
+ }
+ return mSnapshot;
+ }
+ }
+
+ /**
+ * Called when a task need a starting window.
+ */
+ void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+ final int suggestionType = mStartingTypeChecker.estimateStartingWindowType(windowInfo);
+ if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken);
+ } else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
+ final TaskSnapshot snapshot = mStartingTypeChecker.mSnapshot;
+ mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken, snapshot);
+ }
+ // If prefer don't show, then don't show!
+ }
+
+ void copySplashScreenView(int taskId) {
+ mStartingSurfaceDrawer.copySplashScreenView(taskId);
+ }
+
+ /**
+ * Called when the content of a task is ready to show, starting window can be removed.
+ */
+ void removeStartingWindow(int taskId) {
+ mStartingSurfaceDrawer.removeStartingWindow(taskId);
+ }
+
+ private class StartingSurfaceImpl implements StartingSurface {
+
+ @Override
+ public void addStartingWindow(StartingWindowInfo windowInfo, IBinder appToken) {
+ StartingWindowController.this.addStartingWindow(windowInfo, appToken);
+ }
+
+ @Override
+ public void removeStartingWindow(int taskId) {
+ StartingWindowController.this.removeStartingWindow(taskId);
+ }
+
+ @Override
+ public void copySplashScreenView(int taskId) {
+ StartingWindowController.this.copySplashScreenView(taskId);
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
index eb53783f32f7..5f003ba62b2d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
@@ -71,16 +71,16 @@ class RotateTwoLaunchedAppsInAppPairsMode(
}
}
- @FlakyTest
+ @Presubmit
@Test
fun appPairsDividerIsVisible() = testSpec.appPairsDividerIsVisible()
- @FlakyTest
+ @Presubmit
@Test
fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0,
testSpec.config.endRotation)
- @FlakyTest
+ @Presubmit
@Test
fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales(Surface.ROTATION_0,
testSpec.config.endRotation)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
index 39c94842fe6e..d4792088ac31 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
@@ -76,17 +76,8 @@ class RotateTwoLaunchedAppsRotateAndEnterAppPairsMode(
@Presubmit
@Test
- fun navBarLayerRotatesAndScales() {
- Assume.assumeFalse(isRotated)
- testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0, testSpec.config.endRotation)
- }
-
- @FlakyTest
- @Test
- fun navBarLayerRotatesAndScales_Flaky() {
- Assume.assumeTrue(isRotated)
- testSpec.navBarLayerRotatesAndScales(Surface.ROTATION_0, testSpec.config.endRotation)
- }
+ fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales(
+ Surface.ROTATION_0, testSpec.config.endRotation)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 41e2864481fe..9011f1a9fb6a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -18,7 +18,6 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import android.view.Surface
-import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
@@ -125,7 +124,7 @@ class EnterPipToOtherOrientationTest(
}
}
- @FlakyTest
+ @Presubmit
@Test
fun testAppLayerCoversFullScreen() {
testSpec.assertLayersEnd {
@@ -133,11 +132,11 @@ class EnterPipToOtherOrientationTest(
}
}
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt
index 06ef79a2b243..3e331761f767 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseTransition.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 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.
@@ -16,12 +16,9 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
@@ -35,21 +32,10 @@ import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarLayerIsAlwaysVisible
import com.android.server.wm.flicker.statusBarLayerRotatesScales
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
-import org.junit.FixMethodOrder
import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
-/**
- * Test Pip launch.
- * To run this test: `atest WMShellFlickerTests:PipToHomeTest`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class PipToHomeTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+abstract class PipCloseTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
get() = buildTransition(eachRun = true) { configuration ->
setup {
@@ -62,30 +48,27 @@ class PipToHomeTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
this.setRotation(Surface.ROTATION_0)
}
}
- transitions {
- pipApp.closePipWindow(wmHelper)
- }
}
- @Postsubmit
+ @Presubmit
@Test
- fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
+ open fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
@Presubmit
@Test
- fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
+ open fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
@Presubmit
@Test
- fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+ open fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
@Presubmit
@Test
- fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+ open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
@Presubmit
@Test
- fun pipWindowBecomesInvisible() {
+ open fun pipWindowBecomesInvisible() {
testSpec.assertWm {
this.showsAppWindow(PIP_WINDOW_TITLE)
.then()
@@ -95,7 +78,7 @@ class PipToHomeTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
@Presubmit
@Test
- fun pipLayerBecomesInvisible() {
+ open fun pipLayerBecomesInvisible() {
testSpec.assertLayers {
this.isVisible(PIP_WINDOW_TITLE)
.then()
@@ -105,22 +88,22 @@ class PipToHomeTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
@Presubmit
@Test
- fun statusBarLayerRotatesScales() =
+ open fun statusBarLayerRotatesScales() =
testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
- @Postsubmit
+ @Presubmit
@Test
- fun noUncoveredRegions() =
+ open fun noUncoveredRegions() =
testSpec.noUncoveredRegions(testSpec.config.startRotation, Surface.ROTATION_0)
- @Postsubmit
+ @Presubmit
@Test
- fun navBarLayerRotatesAndScales() =
+ open fun navBarLayerRotatesAndScales() =
testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
@FlakyTest(bugId = 151179149)
@Test
- fun focusChanges() = testSpec.focusChanges(pipApp.launcherName, "NexusLauncherActivity")
+ open fun focusChanges() = testSpec.focusChanges(pipApp.launcherName, "NexusLauncherActivity")
companion object {
@Parameterized.Parameters(name = "{0}")
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt
new file mode 100644
index 000000000000..0408421c72a5
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithDismissButtonTest.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.wm.shell.flicker.pip
+
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import org.junit.FixMethodOrder
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest WMShellFlickerTests:PipCloseWithDismissButton`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipCloseWithDismissButtonTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = {
+ super.transition(this, it)
+ transitions {
+ pipApp.closePipWindow(wmHelper)
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt
new file mode 100644
index 000000000000..afaf33a7c46f
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipCloseWithSwipeTest.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.startRotation
+import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest WMShellFlickerTests:PipCloseWithSwipe`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipCloseWithSwipeTest(testSpec: FlickerTestParameter) : PipCloseTransition(testSpec) {
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = {
+ super.transition(this, it)
+ transitions {
+ val pipRegion = wmHelper.getWindowRegion(pipApp.component).bounds
+ val pipCenterX = pipRegion.centerX()
+ val pipCenterY = pipRegion.centerY()
+ val displayCenterX = device.displayWidth / 2
+ device.swipe(pipCenterX, pipCenterY, displayCenterX, device.displayHeight, 5)
+ }
+ }
+
+ @Postsubmit
+ @Test
+ override fun navBarLayerIsAlwaysVisible() = super.navBarLayerIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun statusBarLayerIsAlwaysVisible() = super.statusBarLayerIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ override fun pipWindowBecomesInvisible() = super.pipWindowBecomesInvisible()
+
+ @Postsubmit
+ @Test
+ override fun pipLayerBecomesInvisible() = super.pipLayerBecomesInvisible()
+
+ @Postsubmit
+ @Test
+ override fun statusBarLayerRotatesScales() =
+ testSpec.statusBarLayerRotatesScales(testSpec.config.startRotation, Surface.ROTATION_0)
+
+ @Postsubmit
+ @Test
+ override fun noUncoveredRegions() = super.noUncoveredRegions()
+
+ @Postsubmit
+ @Test
+ override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
new file mode 100644
index 000000000000..4c95da284d9e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipMovesInAllApps.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.wm.shell.flicker.pip
+
+import android.platform.test.annotations.Postsubmit
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.launcher3.tapl.LauncherInstrumentation
+import com.android.server.wm.flicker.FlickerParametersRunnerFactory
+import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.FlickerTestParameterFactory
+import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
+import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
+import com.google.common.truth.Truth
+import org.junit.FixMethodOrder
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip launch.
+ * To run this test: `atest WMShellFlickerTests:PipMovesInAllApps`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class PipMovesInAllApps(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+ private val taplInstrumentation = LauncherInstrumentation()
+
+ override val transition: FlickerBuilder.(Map<String, Any?>) -> Unit
+ get() = buildTransition(eachRun = false) {
+ teardown {
+ eachRun {
+ taplInstrumentation.pressHome()
+ }
+ }
+ transitions {
+ taplInstrumentation.pressHome().switchToAllApps()
+ wmHelper.waitForAppTransitionIdle()
+ }
+ }
+
+ @Postsubmit
+ @Test
+ fun navBarWindowIsAlwaysVisible() = testSpec.navBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
+
+ @Postsubmit
+ @Test
+ fun pipAlwaysVisible() = testSpec.assertWm { this.showsAppWindow(pipApp.windowName) }
+
+ @Postsubmit
+ @Test
+ fun pipWindowMovesUp() = testSpec.assertWmEnd {
+ val initialState = this.trace?.first()?.wmState
+ ?: error("Trace should not be empty")
+ val startPos = initialState.pinnedWindows.first().frame
+ val currPos = this.wmState.pinnedWindows.first().frame
+ val subject = Truth.assertWithMessage("Pip should have moved up")
+ subject.that(currPos.top).isGreaterThan(startPos.top)
+ subject.that(currPos.bottom).isGreaterThan(startPos.bottom)
+ subject.that(currPos.left).isEqualTo(startPos.left)
+ subject.that(currPos.right).isEqualTo(startPos.right)
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): List<FlickerTestParameter> {
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
+ supportedRotations = listOf(Surface.ROTATION_0), repetitions = 5)
+ }
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index 37b49c70708d..df835d21e73f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -88,11 +88,11 @@ class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec)
fun noUncoveredRegions() = testSpec.noUncoveredRegions(testSpec.config.startRotation,
testSpec.config.endRotation, allStates = false)
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
index 704fd1d61c33..1bb1d2861f3f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipToAppTest.kt
@@ -66,7 +66,7 @@ class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
}
}
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
@@ -107,12 +107,12 @@ class PipToAppTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
}
}
- @FlakyTest
+ @Presubmit
@Test
fun noUncoveredRegions() =
testSpec.noUncoveredRegions(testSpec.config.startRotation, Surface.ROTATION_0)
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun navBarLayerRotatesAndScales() =
testSpec.navBarLayerRotatesAndScales(testSpec.config.startRotation, Surface.ROTATION_0)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index 1fcc7d066aa0..7916ce59af52 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -123,11 +123,11 @@ class SetRequestedOrientationWhilePinnedTest(
}
}
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun navBarLayerIsAlwaysVisible() = testSpec.navBarLayerIsAlwaysVisible()
- @FlakyTest(bugId = 140855415)
+ @Presubmit
@Test
fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsAlwaysVisible()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index a0e9f43218f2..06b492dcb409 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -53,7 +53,6 @@ import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.sizecompatui.SizeCompatUIController;
-import com.android.wm.shell.startingsurface.StartingSurfaceDrawer;
import org.junit.Before;
import org.junit.Test;
@@ -79,8 +78,6 @@ public class ShellTaskOrganizerTests {
private Context mContext;
@Mock
private SizeCompatUIController mSizeCompatUI;
- @Mock
- private StartingSurfaceDrawer mStartingSurfaceDrawer;
ShellTaskOrganizer mOrganizer;
private final SyncTransactionQueue mSyncTransactionQueue = mock(SyncTransactionQueue.class);
@@ -116,7 +113,7 @@ public class ShellTaskOrganizerTests {
.when(mTaskOrganizerController).registerTaskOrganizer(any());
} catch (RemoteException e) {}
mOrganizer = spy(new ShellTaskOrganizer(mTaskOrganizerController, mTestExecutor, mContext,
- mSizeCompatUI, mStartingSurfaceDrawer));
+ mSizeCompatUI));
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index de7d6c74bb06..b9af9ce8895d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -125,7 +125,7 @@ public class StartingSurfaceDrawerTests {
final Handler mainLoop = new Handler(Looper.getMainLooper());
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, android.R.style.Theme);
- mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder);
waitHandlerIdle(mainLoop);
verify(mStartingSurfaceDrawer).postAddWindow(
eq(taskId), eq(mBinder), any(), any(), any(), any());
@@ -143,7 +143,7 @@ public class StartingSurfaceDrawerTests {
final Handler mainLoop = new Handler(Looper.getMainLooper());
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, 0);
- mStartingSurfaceDrawer.addStartingWindow(windowInfo, mBinder);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder);
waitHandlerIdle(mainLoop);
verify(mStartingSurfaceDrawer).postAddWindow(
eq(taskId), eq(mBinder), any(), any(), any(), any());
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 9c743cea592a..76366fce2aea 100755
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -156,7 +156,11 @@ std::unique_ptr<ApkAssets> ApkAssets::LoadImpl(std::unique_ptr<Asset> resources_
std::move(loaded_idmap)));
}
-const std::string& ApkAssets::GetPath() const {
+std::optional<std::string_view> ApkAssets::GetPath() const {
+ return assets_provider_->GetPath();
+}
+
+const std::string& ApkAssets::GetDebugName() const {
return assets_provider_->GetDebugName();
}
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 36bde5ccf267..c0ef7be8b673 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -116,8 +116,10 @@ void AssetManager2::BuildDynamicRefTable() {
package_groups_.clear();
package_ids_.fill(0xff);
- // A mapping from apk assets path to the runtime package id of its first loaded package.
- std::unordered_map<std::string, uint8_t> apk_assets_package_ids;
+ // A mapping from path of apk assets that could be target packages of overlays to the runtime
+ // package id of its first loaded package. Overlays currently can only override resources in the
+ // first package in the target resource table.
+ std::unordered_map<std::string, uint8_t> target_assets_package_ids;
// Overlay resources are not directly referenced by an application so their resource ids
// can change throughout the application's lifetime. Assign overlay package ids last.
@@ -140,8 +142,8 @@ void AssetManager2::BuildDynamicRefTable() {
if (auto loaded_idmap = apk_assets->GetLoadedIdmap(); loaded_idmap != nullptr) {
// The target package must precede the overlay package in the apk assets paths in order
// to take effect.
- auto iter = apk_assets_package_ids.find(std::string(loaded_idmap->TargetApkPath()));
- if (iter == apk_assets_package_ids.end()) {
+ auto iter = target_assets_package_ids.find(std::string(loaded_idmap->TargetApkPath()));
+ if (iter == target_assets_package_ids.end()) {
LOG(INFO) << "failed to find target package for overlay "
<< loaded_idmap->OverlayApkPath();
} else {
@@ -205,7 +207,10 @@ void AssetManager2::BuildDynamicRefTable() {
package_name, static_cast<uint8_t>(entry.package_id));
}
- apk_assets_package_ids.insert(std::make_pair(apk_assets->GetPath(), package_id));
+ if (auto apk_assets_path = apk_assets->GetPath()) {
+ // Overlay target ApkAssets must have been created using path based load apis.
+ target_assets_package_ids.insert(std::make_pair(std::string(*apk_assets_path), package_id));
+ }
}
}
@@ -227,7 +232,7 @@ void AssetManager2::DumpToLog() const {
std::string list;
for (const auto& apk_assets : apk_assets_) {
- base::StringAppendF(&list, "%s,", apk_assets->GetPath().c_str());
+ base::StringAppendF(&list, "%s,", apk_assets->GetDebugName().c_str());
}
LOG(INFO) << "ApkAssets: " << list;
@@ -383,8 +388,8 @@ void AssetManager2::SetConfiguration(const ResTable_config& configuration) {
}
}
-std::set<std::string> AssetManager2::GetNonSystemOverlayPaths() const {
- std::set<std::string> non_system_overlays;
+std::set<const ApkAssets*> AssetManager2::GetNonSystemOverlays() const {
+ std::set<const ApkAssets*> non_system_overlays;
for (const PackageGroup& package_group : package_groups_) {
bool found_system_package = false;
for (const ConfiguredPackage& package : package_group.packages_) {
@@ -396,7 +401,7 @@ std::set<std::string> AssetManager2::GetNonSystemOverlayPaths() const {
if (!found_system_package) {
for (const ConfiguredOverlay& overlay : package_group.overlays_) {
- non_system_overlays.insert(apk_assets_[overlay.cookie]->GetPath());
+ non_system_overlays.insert(apk_assets_[overlay.cookie]);
}
}
}
@@ -408,7 +413,7 @@ base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceCon
bool exclude_system, bool exclude_mipmap) const {
ATRACE_NAME("AssetManager::GetResourceConfigurations");
const auto non_system_overlays =
- (exclude_system) ? GetNonSystemOverlayPaths() : std::set<std::string>();
+ (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>();
std::set<ResTable_config> configurations;
for (const PackageGroup& package_group : package_groups_) {
@@ -419,8 +424,8 @@ base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceCon
}
auto apk_assets = apk_assets_[package_group.cookies_[i]];
- if (exclude_system && apk_assets->IsOverlay()
- && non_system_overlays.find(apk_assets->GetPath()) == non_system_overlays.end()) {
+ if (exclude_system && apk_assets->IsOverlay() &&
+ non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
// Exclude overlays that target system resources.
continue;
}
@@ -439,7 +444,7 @@ std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
ATRACE_NAME("AssetManager::GetResourceLocales");
std::set<std::string> locales;
const auto non_system_overlays =
- (exclude_system) ? GetNonSystemOverlayPaths() : std::set<std::string>();
+ (exclude_system) ? GetNonSystemOverlays() : std::set<const ApkAssets*>();
for (const PackageGroup& package_group : package_groups_) {
for (size_t i = 0; i < package_group.packages_.size(); i++) {
@@ -449,8 +454,8 @@ std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
}
auto apk_assets = apk_assets_[package_group.cookies_[i]];
- if (exclude_system && apk_assets->IsOverlay()
- && non_system_overlays.find(apk_assets->GetPath()) == non_system_overlays.end()) {
+ if (exclude_system && apk_assets->IsOverlay() &&
+ non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
// Exclude overlays that target system resources.
continue;
}
@@ -491,7 +496,7 @@ std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) con
AssetDir::FileInfo info;
info.setFileName(String8(name.data(), name.size()));
info.setFileType(type);
- info.setSourceName(String8(apk_assets->GetPath().c_str()));
+ info.setSourceName(String8(apk_assets->GetDebugName().c_str()));
files->add(info);
};
@@ -846,7 +851,7 @@ std::string AssetManager2::GetLastResourceResolution() const {
}
log_stream << "\n\t" << prefix->second << ": " << *step.package_name << " ("
- << apk_assets_[step.cookie]->GetPath() << ")";
+ << apk_assets_[step.cookie]->GetDebugName() << ")";
if (!step.config_name.isEmpty()) {
log_stream << " -" << step.config_name;
}
@@ -1556,41 +1561,32 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& o) {
std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map;
// Determine which ApkAssets are loaded in both theme AssetManagers.
- std::vector<const ApkAssets*> src_assets = o.asset_manager_->GetApkAssets();
+ const auto src_assets = o.asset_manager_->GetApkAssets();
for (size_t i = 0; i < src_assets.size(); i++) {
const ApkAssets* src_asset = src_assets[i];
- std::vector<const ApkAssets*> dest_assets = asset_manager_->GetApkAssets();
+ const auto dest_assets = asset_manager_->GetApkAssets();
for (size_t j = 0; j < dest_assets.size(); j++) {
const ApkAssets* dest_asset = dest_assets[j];
+ if (src_asset != dest_asset) {
+ // ResourcesManager caches and reuses ApkAssets when the same apk must be present in
+ // multiple AssetManagers. Two ApkAssets point to the same version of the same resources
+ // if they are the same instance.
+ continue;
+ }
- // Map the runtime package of the source apk asset to the destination apk asset.
- if (src_asset->GetPath() == dest_asset->GetPath()) {
- const auto& src_packages = src_asset->GetLoadedArsc()->GetPackages();
- const auto& dest_packages = dest_asset->GetLoadedArsc()->GetPackages();
-
- SourceToDestinationRuntimePackageMap package_map;
-
- // The source and destination package should have the same number of packages loaded in
- // the same order.
- const size_t N = src_packages.size();
- CHECK(N == dest_packages.size())
- << " LoadedArsc " << src_asset->GetPath() << " differs number of packages.";
- for (size_t p = 0; p < N; p++) {
- auto& src_package = src_packages[p];
- auto& dest_package = dest_packages[p];
- CHECK(src_package->GetPackageName() == dest_package->GetPackageName())
- << " Package " << src_package->GetPackageName() << " differs in load order.";
-
- int src_package_id = o.asset_manager_->GetAssignedPackageId(src_package.get());
- int dest_package_id = asset_manager_->GetAssignedPackageId(dest_package.get());
- package_map[src_package_id] = dest_package_id;
- }
-
- src_to_dest_asset_cookies.insert(std::make_pair(i, j));
- src_asset_cookie_id_map.insert(std::make_pair(i, package_map));
- break;
+ // Map the package ids of the asset in the source AssetManager to the package ids of the
+ // asset in th destination AssetManager.
+ SourceToDestinationRuntimePackageMap package_map;
+ for (const auto& loaded_package : src_asset->GetLoadedArsc()->GetPackages()) {
+ const int src_package_id = o.asset_manager_->GetAssignedPackageId(loaded_package.get());
+ const int dest_package_id = asset_manager_->GetAssignedPackageId(loaded_package.get());
+ package_map[src_package_id] = dest_package_id;
}
+
+ src_to_dest_asset_cookies.insert(std::make_pair(i, j));
+ src_asset_cookie_id_map.insert(std::make_pair(i, package_map));
+ break;
}
}
diff --git a/libs/androidfw/AssetsProvider.cpp b/libs/androidfw/AssetsProvider.cpp
index f3c48f7f9fc8..0aaf0b359b60 100644
--- a/libs/androidfw/AssetsProvider.cpp
+++ b/libs/androidfw/AssetsProvider.cpp
@@ -261,6 +261,13 @@ std::optional<uint32_t> ZipAssetsProvider::GetCrc(std::string_view path) const {
return entry.crc32;
}
+std::optional<std::string_view> ZipAssetsProvider::GetPath() const {
+ if (name_.GetPath() != nullptr) {
+ return *name_.GetPath();
+ }
+ return {};
+}
+
const std::string& ZipAssetsProvider::GetDebugName() const {
return name_.GetDebugName();
}
@@ -318,6 +325,10 @@ bool DirectoryAssetsProvider::ForEachFile(
return true;
}
+std::optional<std::string_view> DirectoryAssetsProvider::GetPath() const {
+ return dir_;
+}
+
const std::string& DirectoryAssetsProvider::GetDebugName() const {
return dir_;
}
@@ -336,13 +347,9 @@ MultiAssetsProvider::MultiAssetsProvider(std::unique_ptr<AssetsProvider>&& prima
std::unique_ptr<AssetsProvider>&& secondary)
: primary_(std::forward<std::unique_ptr<AssetsProvider>>(primary)),
secondary_(std::forward<std::unique_ptr<AssetsProvider>>(secondary)) {
- if (primary_->GetDebugName() == kEmptyDebugString) {
- debug_name_ = secondary_->GetDebugName();
- } else if (secondary_->GetDebugName() == kEmptyDebugString) {
- debug_name_ = primary_->GetDebugName();
- } else {
- debug_name_ = primary_->GetDebugName() + " and " + secondary_->GetDebugName();
- }
+ debug_name_ = primary_->GetDebugName() + " and " + secondary_->GetDebugName();
+ path_ = (primary_->GetDebugName() != kEmptyDebugString) ? primary_->GetPath()
+ : secondary_->GetPath();
}
std::unique_ptr<AssetsProvider> MultiAssetsProvider::Create(
@@ -367,6 +374,10 @@ bool MultiAssetsProvider::ForEachFile(const std::string& root_path,
return primary_->ForEachFile(root_path, f) && secondary_->ForEachFile(root_path, f);
}
+std::optional<std::string_view> MultiAssetsProvider::GetPath() const {
+ return path_;
+}
+
const std::string& MultiAssetsProvider::GetDebugName() const {
return debug_name_;
}
@@ -394,6 +405,10 @@ bool EmptyAssetsProvider::ForEachFile(
return true;
}
+std::optional<std::string_view> EmptyAssetsProvider::GetPath() const {
+ return {};
+}
+
const std::string& EmptyAssetsProvider::GetDebugName() const {
const static std::string kEmpty = kEmptyDebugString;
return kEmpty;
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index d0019ed6be30..6f88f41976cd 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -34,7 +34,6 @@ namespace android {
// Holds an APK.
class ApkAssets {
public:
-
// Creates an ApkAssets from a path on device.
static std::unique_ptr<ApkAssets> Load(const std::string& path,
package_property_t flags = 0U);
@@ -61,12 +60,11 @@ class ApkAssets {
static std::unique_ptr<ApkAssets> LoadOverlay(const std::string& idmap_path,
package_property_t flags = 0U);
- // TODO(177101983): Remove all uses of GetPath for checking whether two ApkAssets are the same.
- // With the introduction of ResourcesProviders, not all ApkAssets have paths. This could cause
- // bugs when path is used for comparison because multiple ApkAssets could have the same "firendly
- // name". Use pointer equality instead. ResourceManager caches and reuses ApkAssets so the
- // same asset should have the same pointer.
- const std::string& GetPath() const;
+ // Path to the contents of the ApkAssets on disk. The path could represent an APk, a directory,
+ // or some other file type.
+ std::optional<std::string_view> GetPath() const;
+
+ const std::string& GetDebugName() const;
const AssetsProvider* GetAssetsProvider() const {
return assets_provider_.get();
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 2255973f1039..119f531b8634 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -412,7 +412,7 @@ class AssetManager2 {
void RebuildFilterList();
// Retrieves the APK paths of overlays that overlay non-system packages.
- std::set<std::string> GetNonSystemOverlayPaths() const;
+ std::set<const ApkAssets*> GetNonSystemOverlays() const;
// AssetManager2::GetBag(resid) wraps this function to track which resource ids have already
// been seen while traversing bag parents.
diff --git a/libs/androidfw/include/androidfw/AssetsProvider.h b/libs/androidfw/include/androidfw/AssetsProvider.h
index 6f16ff453905..63bbdcc9698d 100644
--- a/libs/androidfw/include/androidfw/AssetsProvider.h
+++ b/libs/androidfw/include/androidfw/AssetsProvider.h
@@ -48,6 +48,10 @@ struct AssetsProvider {
virtual bool ForEachFile(const std::string& path,
const std::function<void(const StringPiece&, FileType)>& f) const = 0;
+ // Retrieves the path to the contents of the AssetsProvider on disk. The path could represent an
+ // APk, a directory, or some other file type.
+ WARN_UNUSED virtual std::optional<std::string_view> GetPath() const = 0;
+
// Retrieves a name that represents the interface. This may or may not be the path of the
// interface source.
WARN_UNUSED virtual const std::string& GetDebugName() const = 0;
@@ -85,9 +89,9 @@ struct ZipAssetsProvider : public AssetsProvider {
bool ForEachFile(const std::string& root_path,
const std::function<void(const StringPiece&, FileType)>& f) const override;
+ WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
WARN_UNUSED bool IsUpToDate() const override;
-
WARN_UNUSED std::optional<uint32_t> GetCrc(std::string_view path) const;
~ZipAssetsProvider() override = default;
@@ -125,6 +129,7 @@ struct DirectoryAssetsProvider : public AssetsProvider {
bool ForEachFile(const std::string& path,
const std::function<void(const StringPiece&, FileType)>& f) const override;
+ WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
WARN_UNUSED bool IsUpToDate() const override;
@@ -149,6 +154,7 @@ struct MultiAssetsProvider : public AssetsProvider {
bool ForEachFile(const std::string& root_path,
const std::function<void(const StringPiece&, FileType)>& f) const override;
+ WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
WARN_UNUSED bool IsUpToDate() const override;
@@ -163,6 +169,7 @@ struct MultiAssetsProvider : public AssetsProvider {
std::unique_ptr<AssetsProvider> primary_;
std::unique_ptr<AssetsProvider> secondary_;
+ std::optional<std::string_view> path_;
std::string debug_name_;
};
@@ -173,6 +180,7 @@ struct EmptyAssetsProvider : public AssetsProvider {
bool ForEachFile(const std::string& path,
const std::function<void(const StringPiece&, FileType)>& f) const override;
+ WARN_UNUSED std::optional<std::string_view> GetPath() const override;
WARN_UNUSED const std::string& GetDebugName() const override;
WARN_UNUSED bool IsUpToDate() const override;
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 389fe7eed7c7..50eea31f984f 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -105,7 +105,6 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
LightingInfo::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, surface,
SkMatrix::I());
- layerUpdateQueue->clear();
// Draw visual debugging features
if (CC_UNLIKELY(Properties::showDirtyRegions ||
@@ -113,9 +112,14 @@ bool SkiaOpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
SkCanvas* profileCanvas = surface->getCanvas();
SkiaProfileRenderer profileRenderer(profileCanvas);
profiler->draw(profileRenderer);
- profileCanvas->flush();
}
+ {
+ ATRACE_NAME("flush commands");
+ surface->flushAndSubmit();
+ }
+ layerUpdateQueue->clear();
+
// Log memory statistics
if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
dumpResourceCacheUsage();
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 6456e36a847a..1f73ac919a47 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -454,9 +454,6 @@ void SkiaPipeline::renderFrame(const LayerUpdateQueue& layers, const SkRect& cli
renderOverdraw(clip, nodes, contentDrawBounds, surface, preTransform);
}
- ATRACE_NAME("flush commands");
- surface->flushAndSubmit();
-
Properties::skpCaptureEnabled = previousSkpEnabled;
}
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index ad6363b4452d..1bd943f4c21d 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -17,14 +17,15 @@
#include "SkiaVulkanPipeline.h"
#include "DeferredLayerUpdater.h"
+#include "LightingInfo.h"
#include "Readback.h"
#include "ShaderCache.h"
-#include "LightingInfo.h"
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
#include "VkInteropFunctorDrawable.h"
#include "renderstate/RenderState.h"
#include "renderthread/Frame.h"
+#include "utils/TraceUtils.h"
#include <SkSurface.h>
#include <SkTypes.h>
@@ -73,8 +74,6 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
LightingInfo::updateLighting(lightGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
mVkSurface->getCurrentPreTransform());
- ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
- layerUpdateQueue->clear();
// Draw visual debugging features
if (CC_UNLIKELY(Properties::showDirtyRegions ||
@@ -82,9 +81,14 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
SkCanvas* profileCanvas = backBuffer->getCanvas();
SkiaProfileRenderer profileRenderer(profileCanvas);
profiler->draw(profileRenderer);
- profileCanvas->flush();
}
+ {
+ ATRACE_NAME("flush commands");
+ mVkManager.finishFrame(backBuffer.get());
+ }
+ layerUpdateQueue->clear();
+
// Log memory statistics
if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
dumpResourceCacheUsage();
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 3e7ce368f55d..e93824dfbd30 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -31,6 +31,7 @@
#include "Properties.h"
#include "RenderThread.h"
+#include "pipeline/skia/ShaderCache.h"
#include "renderstate/RenderState.h"
#include "utils/TraceUtils.h"
@@ -476,17 +477,10 @@ static void destroy_semaphore(void* context) {
}
}
-void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
- if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
- ATRACE_NAME("Finishing GPU work");
- mDeviceWaitIdle(mDevice);
- }
-
- VulkanSurface::NativeBufferInfo* bufferInfo = surface->getCurrentBufferInfo();
- if (!bufferInfo) {
- // If VulkanSurface::dequeueNativeBuffer failed earlier, then swapBuffers is a no-op.
- return;
- }
+void VulkanManager::finishFrame(SkSurface* surface) {
+ ATRACE_NAME("Vulkan finish frame");
+ ALOGE_IF(mSwapSemaphore != VK_NULL_HANDLE || mDestroySemaphoreContext != nullptr,
+ "finishFrame already has an outstanding semaphore");
VkExportSemaphoreCreateInfo exportInfo;
exportInfo.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO;
@@ -499,32 +493,52 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect)
semaphoreInfo.flags = 0;
VkSemaphore semaphore;
VkResult err = mCreateSemaphore(mDevice, &semaphoreInfo, nullptr, &semaphore);
- ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to create semaphore");
+ ALOGE_IF(VK_SUCCESS != err, "VulkanManager::makeSwapSemaphore(): Failed to create semaphore");
GrBackendSemaphore backendSemaphore;
backendSemaphore.initVulkan(semaphore);
- int fenceFd = -1;
- DestroySemaphoreInfo* destroyInfo =
- new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
GrFlushInfo flushInfo;
- flushInfo.fNumSemaphores = 1;
- flushInfo.fSignalSemaphores = &backendSemaphore;
- flushInfo.fFinishedProc = destroy_semaphore;
- flushInfo.fFinishedContext = destroyInfo;
- GrSemaphoresSubmitted submitted = bufferInfo->skSurface->flush(
- SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
- GrDirectContext* context = GrAsDirectContext(bufferInfo->skSurface->recordingContext());
+ if (err == VK_SUCCESS) {
+ mDestroySemaphoreContext = new DestroySemaphoreInfo(mDestroySemaphore, mDevice, semaphore);
+ flushInfo.fNumSemaphores = 1;
+ flushInfo.fSignalSemaphores = &backendSemaphore;
+ flushInfo.fFinishedProc = destroy_semaphore;
+ flushInfo.fFinishedContext = mDestroySemaphoreContext;
+ } else {
+ semaphore = VK_NULL_HANDLE;
+ }
+ GrSemaphoresSubmitted submitted =
+ surface->flush(SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
+ GrDirectContext* context = GrAsDirectContext(surface->recordingContext());
ALOGE_IF(!context, "Surface is not backed by gpu");
context->submit();
- if (submitted == GrSemaphoresSubmitted::kYes) {
+ if (semaphore != VK_NULL_HANDLE) {
+ if (submitted == GrSemaphoresSubmitted::kYes) {
+ mSwapSemaphore = semaphore;
+ } else {
+ destroy_semaphore(mDestroySemaphoreContext);
+ mDestroySemaphoreContext = nullptr;
+ }
+ }
+ skiapipeline::ShaderCache::get().onVkFrameFlushed(context);
+}
+
+void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect) {
+ if (CC_UNLIKELY(Properties::waitForGpuCompletion)) {
+ ATRACE_NAME("Finishing GPU work");
+ mDeviceWaitIdle(mDevice);
+ }
+
+ int fenceFd = -1;
+ if (mSwapSemaphore != VK_NULL_HANDLE) {
VkSemaphoreGetFdInfoKHR getFdInfo;
getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
getFdInfo.pNext = nullptr;
- getFdInfo.semaphore = semaphore;
+ getFdInfo.semaphore = mSwapSemaphore;
getFdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
- err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
+ VkResult err = mGetSemaphoreFdKHR(mDevice, &getFdInfo, &fenceFd);
ALOGE_IF(VK_SUCCESS != err, "VulkanManager::swapBuffers(): Failed to get semaphore Fd");
} else {
ALOGE("VulkanManager::swapBuffers(): Semaphore submission failed");
@@ -532,9 +546,11 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect)
std::lock_guard<std::mutex> lock(mGraphicsQueueMutex);
mQueueWaitIdle(mGraphicsQueue);
}
- destroy_semaphore(destroyInfo);
+ destroy_semaphore(mDestroySemaphoreContext);
surface->presentCurrentBuffer(dirtyRect, fenceFd);
+ mSwapSemaphore = VK_NULL_HANDLE;
+ mDestroySemaphoreContext = nullptr;
}
void VulkanManager::destroySurface(VulkanSurface* surface) {
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 121afc90cfe5..0912369b611d 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -69,6 +69,7 @@ public:
void destroySurface(VulkanSurface* surface);
Frame dequeueNextBuffer(VulkanSurface* surface);
+ void finishFrame(SkSurface* surface);
void swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect);
// Inserts a wait on fence command into the Vulkan command buffer.
@@ -200,6 +201,9 @@ private:
SwapBehavior mSwapBehavior = SwapBehavior::Discard;
GrVkExtensions mExtensions;
uint32_t mDriverVersion = 0;
+
+ VkSemaphore mSwapSemaphore = VK_NULL_HANDLE;
+ void* mDestroySemaphoreContext = nullptr;
};
} /* namespace renderthread */