diff options
Diffstat (limited to 'libs')
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(); } |