summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Jetpack/Android.bp4
-rw-r--r--libs/WindowManager/Jetpack/androidx.window.sidecar.xml2
-rw-r--r--libs/WindowManager/Shell/res/raw/wm_shell_protolog.json12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java75
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java57
-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/protolog/ShellProtoLogImpl.java15
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java8
-rw-r--r--libs/androidfw/include/androidfw/ConfigDescription.h5
-rw-r--r--libs/hwui/FrameInfo.cpp3
-rw-r--r--libs/hwui/FrameInfo.h9
-rw-r--r--libs/hwui/jni/ImageDecoder.cpp13
-rw-r--r--libs/hwui/jni/android_graphics_HardwareRenderer.cpp2
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp13
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp4
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp4
-rw-r--r--libs/hwui/renderthread/RenderThread.h2
-rw-r--r--libs/hwui/renderthread/TimeLord.cpp14
-rw-r--r--libs/hwui/renderthread/TimeLord.h5
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp5
-rw-r--r--libs/hwui/tests/macrobench/TestSceneRunner.cpp6
24 files changed, 217 insertions, 67 deletions
diff --git a/libs/WindowManager/Jetpack/Android.bp b/libs/WindowManager/Jetpack/Android.bp
index 4f4364f72fef..7fbbb61e469d 100644
--- a/libs/WindowManager/Jetpack/Android.bp
+++ b/libs/WindowManager/Jetpack/Android.bp
@@ -24,14 +24,14 @@ java_library {
static_libs: ["window-sidecar"],
installable: true,
sdk_version: "core_platform",
- vendor: true,
+ system_ext_specific: true,
libs: ["framework", "androidx.annotation_annotation",],
required: ["androidx.window.sidecar.xml",],
}
prebuilt_etc {
name: "androidx.window.sidecar.xml",
- vendor: true,
+ system_ext_specific: true,
sub_dir: "permissions",
src: "androidx.window.sidecar.xml",
filename_from_src: true,
diff --git a/libs/WindowManager/Jetpack/androidx.window.sidecar.xml b/libs/WindowManager/Jetpack/androidx.window.sidecar.xml
index f88a5f4ae039..359e69fd9bc1 100644
--- a/libs/WindowManager/Jetpack/androidx.window.sidecar.xml
+++ b/libs/WindowManager/Jetpack/androidx.window.sidecar.xml
@@ -17,5 +17,5 @@
<permissions>
<library
name="androidx.window.sidecar"
- file="/vendor/framework/androidx.window.sidecar.jar"/>
+ file="/system_ext/framework/androidx.window.sidecar.jar"/>
</permissions>
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 7242793580f9..a13e98c0d1ad 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -1,6 +1,12 @@
{
"version": "1.0.0",
"messages": {
+ "-1501874464": {
+ "message": "Fullscreen Task Appeared: #%d",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
+ },
"-1340279385": {
"message": "Remove listener=%s",
"level": "VERBOSE",
@@ -31,6 +37,12 @@
"group": "WM_SHELL_TASK_ORG",
"at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
},
+ "564235578": {
+ "message": "Fullscreen Task Vanished: #%d",
+ "level": "VERBOSE",
+ "group": "WM_SHELL_TASK_ORG",
+ "at": "com\/android\/wm\/shell\/FullscreenTaskListener.java"
+ },
"980952660": {
"message": "Task root back pressed taskId=%d",
"level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
new file mode 100644
index 000000000000..9047b71253da
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import android.app.ActivityManager;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.view.SurfaceControl;
+
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
+
+class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
+ private static final String TAG = "FullscreenTaskOrg";
+
+ private final TransactionPool mTransactionPool;
+
+ private final ArraySet<Integer> mTasks = new ArraySet<>();
+
+ FullscreenTaskListener(TransactionPool transactionPool) {
+ mTransactionPool = transactionPool;
+ }
+
+ @Override
+ public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
+ synchronized (mTasks) {
+ if (mTasks.contains(taskInfo.taskId)) {
+ throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
+ }
+ mTasks.add(taskInfo.taskId);
+ final SurfaceControl.Transaction t = mTransactionPool.acquire();
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
+ taskInfo.taskId);
+ // Reset several properties back to fullscreen (PiP, for example, leaves all these
+ // properties in a bad state).
+ t.setPosition(leash, 0, 0);
+ t.setWindowCrop(leash, null);
+ t.setAlpha(leash, 1f);
+ t.setMatrix(leash, 1, 0, 0, 1);
+ t.show(leash);
+ t.apply();
+ }
+ }
+
+ @Override
+ public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
+ synchronized (mTasks) {
+ if (!mTasks.remove(taskInfo.taskId)) {
+ Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
+ return;
+ }
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
+ taskInfo.taskId);
+ }
+ }
+
+ @Override
+ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ }
+}
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 f9ba695c8503..2d82fb1d3a21 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -16,6 +16,8 @@
package com.android.wm.shell;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
import android.app.ActivityManager.RunningTaskInfo;
import android.util.Log;
import android.util.Pair;
@@ -26,6 +28,7 @@ import android.window.TaskOrganizer;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import java.util.ArrayList;
@@ -56,13 +59,16 @@ public class ShellTaskOrganizer extends TaskOrganizer {
// require us to report to both old and new listeners)
private final SparseArray<Pair<RunningTaskInfo, SurfaceControl>> mTasks = new SparseArray<>();
- public ShellTaskOrganizer() {
+ public ShellTaskOrganizer(TransactionPool transactionPool) {
super();
+ addListener(new FullscreenTaskListener(transactionPool), WINDOWING_MODE_FULLSCREEN);
}
@VisibleForTesting
- ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController) {
+ ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
+ TransactionPool transactionPool) {
super(taskOrganizerController);
+ addListener(new FullscreenTaskListener(transactionPool), WINDOWING_MODE_FULLSCREEN);
}
/**
@@ -125,6 +131,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
Pair<RunningTaskInfo, SurfaceControl> data = mTasks.get(taskInfo.taskId);
int winMode = getWindowingMode(taskInfo);
int prevWinMode = getWindowingMode(data.first);
+ mTasks.put(taskInfo.taskId, new Pair<>(taskInfo, data.second));
if (prevWinMode != -1 && prevWinMode != winMode) {
// TODO: We currently send vanished/appeared as the task moves between win modes, but
// we should consider adding a different mode-changed callback
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index c84b4781d19d..d060f6444463 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -172,8 +172,10 @@ public class OneHandedController implements OneHanded {
context, displayController);
OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
context, displayController, animationController, tutorialHandler);
+ IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
return new OneHandedController(context, displayController, organizer, touchHandler,
- tutorialHandler, gestureHandler);
+ tutorialHandler, gestureHandler, overlayManager);
}
@VisibleForTesting
@@ -182,7 +184,8 @@ public class OneHandedController implements OneHanded {
OneHandedDisplayAreaOrganizer displayAreaOrganizer,
OneHandedTouchHandler touchHandler,
OneHandedTutorialHandler tutorialHandler,
- OneHandedGestureHandler gestureHandler) {
+ OneHandedGestureHandler gestureHandler,
+ IOverlayManager overlayManager) {
mHasOneHandedFeature = SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false);
if (!mHasOneHandedFeature) {
Log.i(TAG, "Device config SUPPORT_ONE_HANDED_MODE off");
@@ -194,32 +197,32 @@ public class OneHandedController implements OneHanded {
mGestureHandler = null;
mTimeoutHandler = null;
mOverlayManager = null;
- return;
+ } else {
+ mContext = context;
+ mDisplayAreaOrganizer = displayAreaOrganizer;
+ mDisplayController = displayController;
+ mTouchHandler = touchHandler;
+ mTutorialHandler = tutorialHandler;
+ mGestureHandler = gestureHandler;
+ mOverlayManager = overlayManager;
+
+ mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50)
+ / 100.0f;
+ mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
+ context.getContentResolver());
+ mIsSwipeToNotificationEnabled =
+ OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
+ context.getContentResolver());
+ mTimeoutHandler = OneHandedTimeoutHandler.get();
+
+ mDisplayController.addDisplayChangingController(mRotationController);
+
+ setupCallback();
+ setupSettingObservers();
+ setupTimeoutListener();
+ setupGesturalOverlay();
+ updateSettings();
}
-
- mContext = context;
- mDisplayAreaOrganizer = displayAreaOrganizer;
- mDisplayController = displayController;
- mTouchHandler = touchHandler;
- mTutorialHandler = tutorialHandler;
- mGestureHandler = gestureHandler;
-
- mOverlayManager = IOverlayManager.Stub.asInterface(
- ServiceManager.getService(Context.OVERLAY_SERVICE));
- mOffSetFraction = SystemProperties.getInt(ONE_HANDED_MODE_OFFSET_PERCENTAGE, 50) / 100.0f;
- mIsOneHandedEnabled = OneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
- context.getContentResolver());
- mIsSwipeToNotificationEnabled = OneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
- context.getContentResolver());
- mTimeoutHandler = OneHandedTimeoutHandler.get();
-
- mDisplayController.addDisplayChangingController(mRotationController);
-
- setupCallback();
- setupSettingObservers();
- setupTimeoutListener();
- setupGesturalOverlay();
- updateSettings();
}
/**
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 ae0975467e3f..e3029e55a214 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
@@ -24,6 +24,8 @@ import com.android.internal.protolog.common.IProtoLogGroup;
* This file is used by the ProtoLogTool to generate optimized logging code.
*/
public enum ShellProtoLogGroup implements IProtoLogGroup {
+ // NOTE: Since we enable these from the same WM ShellCommand, these names should not conflict
+ // with those in the framework ProtoLogGroup
WM_SHELL_TASK_ORG(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
Consts.TAG_WM_SHELL),
TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
index 6a925e74e847..66ecf453c362 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
@@ -44,8 +44,6 @@ public class ShellProtoLogImpl extends BaseProtoLogImpl {
private static ShellProtoLogImpl sServiceInstance = null;
- private final PrintWriter mSystemOutWriter;
-
static {
addLogGroupEnum(ShellProtoLogGroup.values());
}
@@ -111,11 +109,11 @@ public class ShellProtoLogImpl extends BaseProtoLogImpl {
return sServiceInstance;
}
- public void startTextLogging(Context context, String... groups) {
+ public int startTextLogging(Context context, String[] groups, PrintWriter pw) {
try {
mViewerConfig.loadViewerConfig(
context.getResources().openRawResource(R.raw.wm_shell_protolog));
- setLogging(true /* setTextLogging */, true, mSystemOutWriter, groups);
+ return setLogging(true /* setTextLogging */, true, pw, groups);
} catch (IOException e) {
Log.i(TAG, "Unable to load log definitions: IOException while reading "
+ "wm_shell_protolog. " + e);
@@ -123,16 +121,15 @@ public class ShellProtoLogImpl extends BaseProtoLogImpl {
Log.i(TAG, "Unable to load log definitions: JSON parsing exception while reading "
+ "wm_shell_protolog. " + e);
}
+ return -1;
}
- public void stopTextLogging(String... groups) {
- setLogging(true /* setTextLogging */, false, mSystemOutWriter, groups);
+ public int stopTextLogging(String[] groups, PrintWriter pw) {
+ return setLogging(true /* setTextLogging */, false, pw, groups);
}
private ShellProtoLogImpl() {
- super(new File(LOG_FILENAME), null, BUFFER_CAPACITY,
- new ProtoLogViewerConfigReader());
- mSystemOutWriter = new PrintWriter(System.out, true);
+ super(new File(LOG_FILENAME), null, BUFFER_CAPACITY, new ProtoLogViewerConfigReader());
}
}
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 497b6b714281..7b499d4d6e7d 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
@@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.app.ActivityManager.RunningTaskInfo;
@@ -32,6 +33,8 @@ import android.window.ITaskOrganizerController;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.wm.shell.common.TransactionPool;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,6 +54,7 @@ public class ShellTaskOrganizerTests {
private ITaskOrganizerController mTaskOrganizerController;
ShellTaskOrganizer mOrganizer;
+ private final TransactionPool mTransactionPool = mock(TransactionPool.class);
private class TrackingTaskListener implements ShellTaskOrganizer.TaskListener {
final ArrayList<RunningTaskInfo> appeared = new ArrayList<>();
@@ -81,7 +85,7 @@ public class ShellTaskOrganizerTests {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController);
+ mOrganizer = new ShellTaskOrganizer(mTaskOrganizerController, mTransactionPool);
}
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
index 1ce8b5445b37..3645f1e56f92 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedControllerTest.java
@@ -18,13 +18,13 @@ package com.android.wm.shell.onehanded;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.om.IOverlayManager;
import android.provider.Settings;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -62,6 +62,8 @@ public class OneHandedControllerTest extends OneHandedTestCase {
OneHandedGestureHandler mMockGestureHandler;
@Mock
OneHandedTimeoutHandler mMockTimeoutHandler;
+ @Mock
+ IOverlayManager mMockOverlayManager;
@Before
public void setUp() throws Exception {
@@ -73,7 +75,8 @@ public class OneHandedControllerTest extends OneHandedTestCase {
mMockDisplayAreaOrganizer,
mMockTouchHandler,
mMockTutorialHandler,
- mMockGestureHandler);
+ mMockGestureHandler,
+ mMockOverlayManager);
mOneHandedController = Mockito.spy(oneHandedController);
mTimeoutHandler = Mockito.spy(OneHandedTimeoutHandler.get());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
index 4a133d39291a..3341c9cbacb9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/onehanded/OneHandedTutorialHandlerTest.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.onehanded;
import static org.mockito.Mockito.verify;
+import android.content.om.IOverlayManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -44,6 +45,8 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
DisplayController mMockDisplayController;
@Mock
OneHandedDisplayAreaOrganizer mMockDisplayAreaOrganizer;
+ @Mock
+ IOverlayManager mMockOverlayManager;
@Before
public void setUp() {
@@ -56,11 +59,12 @@ public class OneHandedTutorialHandlerTest extends OneHandedTestCase {
mMockDisplayAreaOrganizer,
mTouchHandler,
mTutorialHandler,
- mGestureHandler);
+ mGestureHandler,
+ mMockOverlayManager);
}
@Test
- public void testOneHandedManager_registerForDisplayAreaOrganizer() {
+ public void testRegisterForDisplayAreaOrganizer() {
verify(mMockDisplayAreaOrganizer).registerTransitionCallback(mTutorialHandler);
}
}
diff --git a/libs/androidfw/include/androidfw/ConfigDescription.h b/libs/androidfw/include/androidfw/ConfigDescription.h
index acf413aeaf91..61d10cd4e55b 100644
--- a/libs/androidfw/include/androidfw/ConfigDescription.h
+++ b/libs/androidfw/include/androidfw/ConfigDescription.h
@@ -177,9 +177,8 @@ inline ConfigDescription& ConfigDescription::operator=(ConfigDescription&& o) no
return *this;
}
-inline bool ConfigDescription::MatchWithDensity(
- const ConfigDescription& o) const {
- return match(o) && (density == 0 || density == o.density);
+inline bool ConfigDescription::MatchWithDensity(const ConfigDescription& o) const {
+ return match(o) && (density == 0 || o.density != 0);
}
inline bool ConfigDescription::operator<(const ConfigDescription& o) const {
diff --git a/libs/hwui/FrameInfo.cpp b/libs/hwui/FrameInfo.cpp
index 0698775b0021..30ce5370760d 100644
--- a/libs/hwui/FrameInfo.cpp
+++ b/libs/hwui/FrameInfo.cpp
@@ -22,6 +22,7 @@ namespace uirenderer {
const std::string FrameInfoNames[] = {
"Flags",
+ "FrameTimelineVsyncId",
"IntendedVsync",
"Vsync",
"OldestInputEvent",
@@ -44,7 +45,7 @@ static_assert((sizeof(FrameInfoNames) / sizeof(FrameInfoNames[0])) ==
static_cast<int>(FrameInfoIndex::NumIndexes),
"size mismatch: FrameInfoNames doesn't match the enum!");
-static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 17,
+static_assert(static_cast<int>(FrameInfoIndex::NumIndexes) == 18,
"Must update value in FrameMetrics.java#FRAME_STATS_COUNT (and here)");
void FrameInfo::importUiThreadInfo(int64_t* info) {
diff --git a/libs/hwui/FrameInfo.h b/libs/hwui/FrameInfo.h
index dc30617009e7..f5bfedde2f92 100644
--- a/libs/hwui/FrameInfo.h
+++ b/libs/hwui/FrameInfo.h
@@ -27,10 +27,11 @@
namespace android {
namespace uirenderer {
-#define UI_THREAD_FRAME_INFO_SIZE 9
+#define UI_THREAD_FRAME_INFO_SIZE 10
enum class FrameInfoIndex {
Flags = 0,
+ FrameTimelineVsyncId,
IntendedVsync,
Vsync,
OldestInputEvent,
@@ -71,11 +72,15 @@ enum {
class UiFrameInfoBuilder {
public:
+ static constexpr int64_t INVALID_VSYNC_ID = -1;
+
explicit UiFrameInfoBuilder(int64_t* buffer) : mBuffer(buffer) {
memset(mBuffer, 0, UI_THREAD_FRAME_INFO_SIZE * sizeof(int64_t));
+ set(FrameInfoIndex::FrameTimelineVsyncId) = INVALID_VSYNC_ID;
}
- UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync) {
+ UiFrameInfoBuilder& setVsync(nsecs_t vsyncTime, nsecs_t intendedVsync, int64_t vsyncId) {
+ set(FrameInfoIndex::FrameTimelineVsyncId) = vsyncId;
set(FrameInfoIndex::Vsync) = vsyncTime;
set(FrameInfoIndex::IntendedVsync) = intendedVsync;
// Pretend the other fields are all at vsync, too, so that naive
diff --git a/libs/hwui/jni/ImageDecoder.cpp b/libs/hwui/jni/ImageDecoder.cpp
index 1f4fd230e55e..da91d46b0738 100644
--- a/libs/hwui/jni/ImageDecoder.cpp
+++ b/libs/hwui/jni/ImageDecoder.cpp
@@ -152,7 +152,7 @@ static jobject native_create(JNIEnv* env, std::unique_ptr<SkStream> stream,
}
static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
- jobject fileDescriptor, jboolean preferAnimation, jobject source) {
+ jobject fileDescriptor, jlong length, jboolean preferAnimation, jobject source) {
#ifndef __ANDROID__ // LayoutLib for Windows does not support F_DUPFD_CLOEXEC
return throw_exception(env, kSourceException, "Only supported on Android", nullptr, source);
#else
@@ -172,7 +172,14 @@ static jobject ImageDecoder_nCreateFd(JNIEnv* env, jobject /*clazz*/,
nullptr, source);
}
- std::unique_ptr<SkFILEStream> fileStream(new SkFILEStream(file));
+ std::unique_ptr<SkFILEStream> fileStream;
+ if (length == -1) {
+ // -1 corresponds to AssetFileDescriptor.UNKNOWN_LENGTH. Pass no length
+ // so SkFILEStream will figure out the size of the file on its own.
+ fileStream.reset(new SkFILEStream(file));
+ } else {
+ fileStream.reset(new SkFILEStream(file, length));
+ }
return native_create(env, std::move(fileStream), source, preferAnimation);
#endif
}
@@ -493,7 +500,7 @@ static const JNINativeMethod gImageDecoderMethods[] = {
{ "nCreate", "(Ljava/nio/ByteBuffer;IIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteBuffer },
{ "nCreate", "([BIIZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateByteArray },
{ "nCreate", "(Ljava/io/InputStream;[BZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateInputStream },
- { "nCreate", "(Ljava/io/FileDescriptor;ZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
+ { "nCreate", "(Ljava/io/FileDescriptor;JZLandroid/graphics/ImageDecoder$Source;)Landroid/graphics/ImageDecoder;", (void*) ImageDecoder_nCreateFd },
{ "nDecodeBitmap", "(JLandroid/graphics/ImageDecoder;ZIILandroid/graphics/Rect;ZIZZZJZ)Landroid/graphics/Bitmap;",
(void*) ImageDecoder_nDecodeBitmap },
{ "nGetSampledSize","(JI)Landroid/util/Size;", (void*) ImageDecoder_nGetSampledSize },
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index e817ca744c58..c89463bf3ab4 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -514,7 +514,7 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(
proxy.setLightGeometry((Vector3){0, 0, 0}, 0);
nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
UiFrameInfoBuilder(proxy.frameInfo())
- .setVsync(vsync, vsync)
+ .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID)
.addFlag(FrameInfoFlags::SurfaceCanvas);
proxy.syncAndDrawFrame();
}
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 13d544c68e95..c7560b2496ef 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -484,6 +484,14 @@ void CanvasContext::draw() {
waitOnFences();
+ if (mNativeSurface) {
+ // TODO(b/165985262): measure performance impact
+ if (const auto vsyncId = mCurrentFrameInfo->get(FrameInfoIndex::FrameTimelineVsyncId);
+ vsyncId != UiFrameInfoBuilder::INVALID_VSYNC_ID) {
+ native_window_set_frame_timeline_vsync(mNativeSurface->getNativeWindow(), vsyncId);
+ }
+ }
+
bool requireSwap = false;
int error = OK;
bool didSwap =
@@ -617,8 +625,11 @@ void CanvasContext::prepareAndDraw(RenderNode* node) {
ATRACE_CALL();
nsecs_t vsync = mRenderThread.timeLord().computeFrameTimeNanos();
+ int64_t vsyncId = mRenderThread.timeLord().lastVsyncId();
int64_t frameInfo[UI_THREAD_FRAME_INFO_SIZE];
- UiFrameInfoBuilder(frameInfo).addFlag(FrameInfoFlags::RTAnimation).setVsync(vsync, vsync);
+ UiFrameInfoBuilder(frameInfo)
+ .addFlag(FrameInfoFlags::RTAnimation)
+ .setVsync(vsync, vsync, vsyncId);
TreeInfo info(TreeInfo::MODE_RT_ONLY, *this);
prepareTree(info, frameInfo, systemTime(SYSTEM_TIME_MONOTONIC), node);
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 1e593388d063..1ea595d6a30a 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -128,7 +128,9 @@ void DrawFrameTask::run() {
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
- mRenderThread->timeLord().vsyncReceived(vsync);
+ int64_t intendedVsync = mFrameInfo[static_cast<int>(FrameInfoIndex::IntendedVsync)];
+ int64_t vsyncId = mFrameInfo[static_cast<int>(FrameInfoIndex::FrameTimelineVsyncId)];
+ mRenderThread->timeLord().vsyncReceived(vsync, intendedVsync, vsyncId);
bool canDraw = mContext->makeCurrent();
mContext->unpinImages();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 4dcbc4458e97..9371656eda7f 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -51,8 +51,10 @@ static JVMAttachHook gOnStartHook = nullptr;
void RenderThread::frameCallback(int64_t frameTimeNanos, void* data) {
RenderThread* rt = reinterpret_cast<RenderThread*>(data);
+ int64_t vsyncId = AChoreographer_getVsyncId(rt->mChoreographer);
rt->mVsyncRequested = false;
- if (rt->timeLord().vsyncReceived(frameTimeNanos) && !rt->mFrameCallbackTaskPending) {
+ if (rt->timeLord().vsyncReceived(frameTimeNanos, frameTimeNanos, vsyncId) &&
+ !rt->mFrameCallbackTaskPending) {
ATRACE_NAME("queue mFrameCallbackTask");
rt->mFrameCallbackTaskPending = true;
nsecs_t runAt = (frameTimeNanos + rt->mDispatchFrameDelay);
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index d7dc00b8a5c1..4fbb07168ac0 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -19,8 +19,8 @@
#include <GrDirectContext.h>
#include <SkBitmap.h>
-#include <apex/choreographer.h>
#include <cutils/compiler.h>
+#include <private/android/choreographer.h>
#include <thread/ThreadBase.h>
#include <utils/Looper.h>
#include <utils/Thread.h>
diff --git a/libs/hwui/renderthread/TimeLord.cpp b/libs/hwui/renderthread/TimeLord.cpp
index 784068f1d877..7dc36c449568 100644
--- a/libs/hwui/renderthread/TimeLord.cpp
+++ b/libs/hwui/renderthread/TimeLord.cpp
@@ -19,9 +19,17 @@ namespace android {
namespace uirenderer {
namespace renderthread {
-TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)), mFrameTimeNanos(0) {}
+TimeLord::TimeLord() : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)),
+ mFrameTimeNanos(0),
+ mFrameIntendedTimeNanos(0),
+ mFrameVsyncId(-1) {}
+
+bool TimeLord::vsyncReceived(nsecs_t vsync, nsecs_t intendedVsync, int64_t vsyncId) {
+ if (intendedVsync > mFrameIntendedTimeNanos) {
+ mFrameIntendedTimeNanos = intendedVsync;
+ mFrameVsyncId = vsyncId;
+ }
-bool TimeLord::vsyncReceived(nsecs_t vsync) {
if (vsync > mFrameTimeNanos) {
mFrameTimeNanos = vsync;
return true;
@@ -36,6 +44,8 @@ nsecs_t TimeLord::computeFrameTimeNanos() {
if (jitterNanos >= mFrameIntervalNanos) {
nsecs_t lastFrameOffset = jitterNanos % mFrameIntervalNanos;
mFrameTimeNanos = now - lastFrameOffset;
+ // mFrameVsyncId is not adjusted here as we still want to send
+ // the vsync id that started this frame to the Surface Composer
}
return mFrameTimeNanos;
}
diff --git a/libs/hwui/renderthread/TimeLord.h b/libs/hwui/renderthread/TimeLord.h
index 68a0f7f971b9..23c1e51c427a 100644
--- a/libs/hwui/renderthread/TimeLord.h
+++ b/libs/hwui/renderthread/TimeLord.h
@@ -32,9 +32,10 @@ public:
nsecs_t frameIntervalNanos() const { return mFrameIntervalNanos; }
// returns true if the vsync is newer, false if it was rejected for staleness
- bool vsyncReceived(nsecs_t vsync);
+ bool vsyncReceived(nsecs_t vsync, nsecs_t indendedVsync, int64_t vsyncId);
nsecs_t latestVsync() { return mFrameTimeNanos; }
nsecs_t computeFrameTimeNanos();
+ int64_t lastVsyncId() const { return mFrameVsyncId; }
private:
friend class RenderThread;
@@ -44,6 +45,8 @@ private:
nsecs_t mFrameIntervalNanos;
nsecs_t mFrameTimeNanos;
+ nsecs_t mFrameIntendedTimeNanos;
+ int64_t mFrameVsyncId;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 4dbce92ed01c..1333b92037c3 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -516,8 +516,9 @@ void VulkanManager::swapBuffers(VulkanSurface* surface, const SkRect& dirtyRect)
flushInfo.fFinishedContext = destroyInfo;
GrSemaphoresSubmitted submitted = bufferInfo->skSurface->flush(
SkSurface::BackendSurfaceAccess::kPresent, flushInfo);
- ALOGE_IF(!bufferInfo->skSurface->getContext(), "Surface is not backed by gpu");
- bufferInfo->skSurface->getContext()->submit();
+ GrDirectContext* context = GrAsDirectContext(bufferInfo->skSurface->recordingContext());
+ ALOGE_IF(!context, "Surface is not backed by gpu");
+ context->submit();
if (submitted == GrSemaphoresSubmitted::kYes) {
VkSemaphoreGetFdInfoKHR getFdInfo;
getFdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index 801cb7d9e8c5..ed89c590be10 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -145,7 +145,8 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
for (int i = 0; i < warmupFrameCount; i++) {
testContext.waitForVsync();
nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
- UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
+ UiFrameInfoBuilder(proxy->frameInfo())
+ .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID);
proxy->syncAndDrawFrame();
}
@@ -165,7 +166,8 @@ void run(const TestScene::Info& info, const TestScene::Options& opts,
nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
{
ATRACE_NAME("UI-Draw Frame");
- UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
+ UiFrameInfoBuilder(proxy->frameInfo())
+ .setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID);
scene->doFrame(i);
proxy->syncAndDrawFrame();
}