diff options
18 files changed, 231 insertions, 146 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index fde139b60ca5..339671f5b17c 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -17621,7 +17621,6 @@ package android.graphics { method public void setIntUniform(@NonNull String, int, int, int); method public void setIntUniform(@NonNull String, int, int, int, int); method public void setIntUniform(@NonNull String, @NonNull int[]); - method @FlaggedApi("com.android.graphics.hwui.flags.shader_color_space") public void setWorkingColorSpace(@Nullable android.graphics.ColorSpace); } @FlaggedApi("com.android.graphics.hwui.flags.runtime_color_filters_blenders") public class RuntimeXfermode extends android.graphics.Xfermode { diff --git a/core/java/android/app/ApplicationStartInfo.java b/core/java/android/app/ApplicationStartInfo.java index 3214bd8f01fc..2e8031dd22fe 100644 --- a/core/java/android/app/ApplicationStartInfo.java +++ b/core/java/android/app/ApplicationStartInfo.java @@ -840,7 +840,9 @@ public final class ApplicationStartInfo implements Parcelable { * @hide */ // LINT.IfChange(write_proto) - public void writeToProto(ProtoOutputStream proto, long fieldId) throws IOException { + public void writeToProto(ProtoOutputStream proto, long fieldId, + ByteArrayOutputStream byteArrayOutputStream, ObjectOutputStream objectOutputStream, + TypedXmlSerializer typedXmlSerializer) throws IOException { final long token = proto.start(fieldId); proto.write(ApplicationStartInfoProto.PID, mPid); proto.write(ApplicationStartInfoProto.REAL_UID, mRealUid); @@ -850,38 +852,38 @@ public final class ApplicationStartInfo implements Parcelable { proto.write(ApplicationStartInfoProto.STARTUP_STATE, mStartupState); proto.write(ApplicationStartInfoProto.REASON, mReason); if (mStartupTimestampsNs != null && mStartupTimestampsNs.size() > 0) { - ByteArrayOutputStream timestampsBytes = new ByteArrayOutputStream(); - ObjectOutputStream timestampsOut = new ObjectOutputStream(timestampsBytes); - TypedXmlSerializer serializer = Xml.resolveSerializer(timestampsOut); - serializer.startDocument(null, true); - serializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); + byteArrayOutputStream = new ByteArrayOutputStream(); + objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + typedXmlSerializer = Xml.resolveSerializer(objectOutputStream); + typedXmlSerializer.startDocument(null, true); + typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); for (int i = 0; i < mStartupTimestampsNs.size(); i++) { - serializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP); - serializer.attributeInt(null, PROTO_SERIALIZER_ATTRIBUTE_KEY, + typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP); + typedXmlSerializer.attributeInt(null, PROTO_SERIALIZER_ATTRIBUTE_KEY, mStartupTimestampsNs.keyAt(i)); - serializer.attributeLong(null, PROTO_SERIALIZER_ATTRIBUTE_TS, + typedXmlSerializer.attributeLong(null, PROTO_SERIALIZER_ATTRIBUTE_TS, mStartupTimestampsNs.valueAt(i)); - serializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP); + typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP); } - serializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); - serializer.endDocument(); + typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); + typedXmlSerializer.endDocument(); proto.write(ApplicationStartInfoProto.STARTUP_TIMESTAMPS, - timestampsBytes.toByteArray()); - timestampsOut.close(); + byteArrayOutputStream.toByteArray()); + objectOutputStream.close(); } proto.write(ApplicationStartInfoProto.START_TYPE, mStartType); if (mStartIntent != null) { - ByteArrayOutputStream intentBytes = new ByteArrayOutputStream(); - ObjectOutputStream intentOut = new ObjectOutputStream(intentBytes); - TypedXmlSerializer serializer = Xml.resolveSerializer(intentOut); - serializer.startDocument(null, true); - serializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); - mStartIntent.saveToXml(serializer); - serializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); - serializer.endDocument(); + byteArrayOutputStream = new ByteArrayOutputStream(); + objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + typedXmlSerializer = Xml.resolveSerializer(objectOutputStream); + typedXmlSerializer.startDocument(null, true); + typedXmlSerializer.startTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); + mStartIntent.saveToXml(typedXmlSerializer); + typedXmlSerializer.endTag(null, PROTO_SERIALIZER_ATTRIBUTE_INTENT); + typedXmlSerializer.endDocument(); proto.write(ApplicationStartInfoProto.START_INTENT, - intentBytes.toByteArray()); - intentOut.close(); + byteArrayOutputStream.toByteArray()); + objectOutputStream.close(); } proto.write(ApplicationStartInfoProto.LAUNCH_MODE, mLaunchMode); proto.write(ApplicationStartInfoProto.WAS_FORCE_STOPPED, mWasForceStopped); @@ -900,7 +902,9 @@ public final class ApplicationStartInfo implements Parcelable { * @hide */ // LINT.IfChange(read_proto) - public void readFromProto(ProtoInputStream proto, long fieldId) + public void readFromProto(ProtoInputStream proto, long fieldId, + ByteArrayInputStream byteArrayInputStream, ObjectInputStream objectInputStream, + TypedXmlPullParser typedXmlPullParser) throws IOException, WireTypeMismatchException, ClassNotFoundException { final long token = proto.start(fieldId); while (proto.nextField() != ProtoInputStream.NO_MORE_FIELDS) { @@ -927,19 +931,21 @@ public final class ApplicationStartInfo implements Parcelable { mReason = proto.readInt(ApplicationStartInfoProto.REASON); break; case (int) ApplicationStartInfoProto.STARTUP_TIMESTAMPS: - ByteArrayInputStream timestampsBytes = new ByteArrayInputStream(proto.readBytes( + byteArrayInputStream = new ByteArrayInputStream(proto.readBytes( ApplicationStartInfoProto.STARTUP_TIMESTAMPS)); - ObjectInputStream timestampsIn = new ObjectInputStream(timestampsBytes); + objectInputStream = new ObjectInputStream(byteArrayInputStream); mStartupTimestampsNs = new ArrayMap<Integer, Long>(); try { - TypedXmlPullParser parser = Xml.resolvePullParser(timestampsIn); - XmlUtils.beginDocument(parser, PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); - int depth = parser.getDepth(); - while (XmlUtils.nextElementWithin(parser, depth)) { - if (PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP.equals(parser.getName())) { - int key = parser.getAttributeInt(null, + typedXmlPullParser = Xml.resolvePullParser(objectInputStream); + XmlUtils.beginDocument(typedXmlPullParser, + PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMPS); + int depth = typedXmlPullParser.getDepth(); + while (XmlUtils.nextElementWithin(typedXmlPullParser, depth)) { + if (PROTO_SERIALIZER_ATTRIBUTE_TIMESTAMP.equals( + typedXmlPullParser.getName())) { + int key = typedXmlPullParser.getAttributeInt(null, PROTO_SERIALIZER_ATTRIBUTE_KEY); - long ts = parser.getAttributeLong(null, + long ts = typedXmlPullParser.getAttributeLong(null, PROTO_SERIALIZER_ATTRIBUTE_TS); mStartupTimestampsNs.put(key, ts); } @@ -947,23 +953,24 @@ public final class ApplicationStartInfo implements Parcelable { } catch (XmlPullParserException e) { // Timestamps lost } - timestampsIn.close(); + objectInputStream.close(); break; case (int) ApplicationStartInfoProto.START_TYPE: mStartType = proto.readInt(ApplicationStartInfoProto.START_TYPE); break; case (int) ApplicationStartInfoProto.START_INTENT: - ByteArrayInputStream intentBytes = new ByteArrayInputStream(proto.readBytes( + byteArrayInputStream = new ByteArrayInputStream(proto.readBytes( ApplicationStartInfoProto.START_INTENT)); - ObjectInputStream intentIn = new ObjectInputStream(intentBytes); + objectInputStream = new ObjectInputStream(byteArrayInputStream); try { - TypedXmlPullParser parser = Xml.resolvePullParser(intentIn); - XmlUtils.beginDocument(parser, PROTO_SERIALIZER_ATTRIBUTE_INTENT); - mStartIntent = Intent.restoreFromXml(parser); + typedXmlPullParser = Xml.resolvePullParser(objectInputStream); + XmlUtils.beginDocument(typedXmlPullParser, + PROTO_SERIALIZER_ATTRIBUTE_INTENT); + mStartIntent = Intent.restoreFromXml(typedXmlPullParser); } catch (XmlPullParserException e) { // Intent lost } - intentIn.close(); + objectInputStream.close(); break; case (int) ApplicationStartInfoProto.LAUNCH_MODE: mLaunchMode = proto.readInt(ApplicationStartInfoProto.LAUNCH_MODE); diff --git a/core/java/android/hardware/input/InputSettings.java b/core/java/android/hardware/input/InputSettings.java index 3d4b8854b01f..7c82abe083c2 100644 --- a/core/java/android/hardware/input/InputSettings.java +++ b/core/java/android/hardware/input/InputSettings.java @@ -386,7 +386,7 @@ public class InputSettings { */ public static boolean isTouchpadAccelerationEnabled(@NonNull Context context) { if (!isPointerAccelerationFeatureFlagEnabled()) { - return false; + return true; } return Settings.System.getIntForUser(context.getContentResolver(), @@ -833,7 +833,7 @@ public class InputSettings { */ public static boolean isMousePointerAccelerationEnabled(@NonNull Context context) { if (!isPointerAccelerationFeatureFlagEnabled()) { - return false; + return true; } return Settings.System.getIntForUser(context.getContentResolver(), diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index de3e45b8ebde..6b6147a3749d 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -118,6 +118,7 @@ import static android.view.flags.Flags.addSchandleToVriSurface; import static android.view.flags.Flags.disableDrawWakeLock; import static android.view.flags.Flags.sensitiveContentAppProtection; import static android.view.flags.Flags.sensitiveContentPrematureProtectionRemovedFix; +import static android.view.flags.Flags.toolkitFrameRateDebug; import static android.view.flags.Flags.toolkitFrameRateFunctionEnablingReadOnly; import static android.view.flags.Flags.toolkitFrameRateTouchBoost25q1; import static android.view.flags.Flags.toolkitFrameRateTypingReadOnly; @@ -1227,6 +1228,7 @@ public final class ViewRootImpl implements ViewParent, com.android.graphics.surfaceflinger.flags.Flags.vrrBugfix24q4(); private static final boolean sEnableVrr = ViewProperties.vrr_enabled().orElse(true); private static final boolean sToolkitInitialTouchBoostFlagValue = toolkitInitialTouchBoost(); + private static boolean sToolkitFrameRateDebugFlagValue = toolkitFrameRateDebug(); static { sToolkitSetFrameRateReadOnlyFlagValue = toolkitSetFrameRateReadOnly(); @@ -13139,6 +13141,11 @@ public final class ViewRootImpl implements ViewParent, if (sToolkitFrameRateFunctionEnablingReadOnlyFlagValue) { mFrameRateTransaction.setFrameRateCategory(mSurfaceControl, frameRateCategory, false).applyAsyncUnsafe(); + + if (sToolkitFrameRateDebugFlagValue) { + Log.v(mTag, "### ViewRootImpl setFrameRateCategory '" + + categoryToString(frameRateCategory) + "'"); + } } mLastPreferredFrameRateCategory = frameRateCategory; } @@ -13201,8 +13208,15 @@ public final class ViewRootImpl implements ViewParent, if (preferredFrameRate > 0) { mFrameRateTransaction.setFrameRate(mSurfaceControl, preferredFrameRate, mFrameRateCompatibility); + if (sToolkitFrameRateDebugFlagValue) { + Log.v(mTag, "### ViewRootImpl setFrameRate '" + + preferredFrameRate + "'"); + } } else { mFrameRateTransaction.clearFrameRate(mSurfaceControl); + if (sToolkitFrameRateDebugFlagValue) { + Log.v(mTag, "### ViewRootImpl setFrameRate 0 Hz"); + } } mFrameRateTransaction.applyAsyncUnsafe(); } @@ -13256,6 +13270,12 @@ public final class ViewRootImpl implements ViewParent, // mFrameRateCategoryView = view == null ? "-" : view.getClass().getSimpleName(); } mDrawnThisFrame = true; + + if (sToolkitFrameRateDebugFlagValue) { + String viewName = view == null ? "-" : view.getClass().getSimpleName(); + Log.v(mTag, "### View: " + viewName + " votes '" + + categoryToString(frameRateCategory) + "'"); + } } /** diff --git a/core/java/android/view/flags/refresh_rate_flags.aconfig b/core/java/android/view/flags/refresh_rate_flags.aconfig index 3bc2205f8e1c..18fa0f353f36 100644 --- a/core/java/android/view/flags/refresh_rate_flags.aconfig +++ b/core/java/android/view/flags/refresh_rate_flags.aconfig @@ -143,4 +143,11 @@ flag { namespace: "toolkit" description: "Feature flag to update initial touch boost logic" bug: "393004744" +} + +flag { + name: "toolkit_frame_rate_debug" + namespace: "toolkit" + description: "Feature flag to ennable ARR debug message" + bug: "394614443" }
\ No newline at end of file diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java index 9016724b765e..3543e991924e 100644 --- a/graphics/java/android/graphics/RuntimeShader.java +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -20,7 +20,6 @@ import android.annotation.ColorInt; import android.annotation.ColorLong; import android.annotation.FlaggedApi; import android.annotation.NonNull; -import android.annotation.Nullable; import android.util.ArrayMap; import android.view.Window; @@ -77,7 +76,6 @@ import libcore.util.NativeAllocationRegistry; * Additionally, if the shader is invoked by another using {@link #setInputShader(String, Shader)}, * then that parent shader may modify the input coordinates arbitrarily.</p> * - * <a id="agsl-and-color-spaces"/> * <h3>AGSL and Color Spaces</h3> * <p>Android Graphics and by extension {@link RuntimeShader} are color managed. The working * {@link ColorSpace} for an AGSL shader is defined to be the color space of the destination, which @@ -269,8 +267,6 @@ public class RuntimeShader extends Shader { private ArrayMap<String, ColorFilter> mColorFilterUniforms = new ArrayMap<>(); private ArrayMap<String, RuntimeXfermode> mXfermodeUniforms = new ArrayMap<>(); - private ColorSpace mWorkingColorSpace = null; - /** * Creates a new RuntimeShader. @@ -290,35 +286,6 @@ public class RuntimeShader extends Shader { } /** - * Sets the working color space for this shader. That is, the shader will be evaluated - * in the given colorspace before being converted to the output destination's colorspace. - * - * <p>By default the RuntimeShader is evaluated in the context of the - * <a href="#agsl-and-color-spaces">destination colorspace</a>. By calling this method - * that can be overridden to force the shader to be evaluated in the given colorspace first - * before then being color converted to the destination colorspace.</p> - * - * @param colorSpace The ColorSpace to evaluate in. Must be an {@link ColorSpace#getModel() RGB} - * ColorSpace. Passing null restores default behavior of working in the - * destination colorspace. - * @throws IllegalArgumentException If the colorspace is not RGB - */ - @FlaggedApi(Flags.FLAG_SHADER_COLOR_SPACE) - public void setWorkingColorSpace(@Nullable ColorSpace colorSpace) { - if (colorSpace != null && colorSpace.getModel() != ColorSpace.Model.RGB) { - throw new IllegalArgumentException("ColorSpace must be RGB, given " + colorSpace); - } - if (mWorkingColorSpace != colorSpace) { - mWorkingColorSpace = colorSpace; - if (mWorkingColorSpace != null) { - // Just to enforce this can be resolved instead of erroring out later - mWorkingColorSpace.getNativeInstance(); - } - discardNativeInstance(); - } - } - - /** * Sets the uniform color value corresponding to this shader. If the shader does not have a * uniform with that name or if the uniform is declared with a type other than vec3 or vec4 and * corresponding layout(color) annotation then an IllegalArgumentException is thrown. @@ -611,8 +578,7 @@ public class RuntimeShader extends Shader { /** @hide */ @Override protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) { - return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix, - mWorkingColorSpace != null ? mWorkingColorSpace.getNativeInstance() : 0); + return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix); } /** @hide */ @@ -622,8 +588,7 @@ public class RuntimeShader extends Shader { private static native long nativeGetFinalizer(); private static native long nativeCreateBuilder(String agsl); - private static native long nativeCreateShader(long shaderBuilder, long matrix, - long colorSpacePtr); + private static native long nativeCreateShader(long shaderBuilder, long matrix); private static native void nativeUpdateUniforms( long shaderBuilder, String uniformName, float[] uniforms, boolean isColor); private static native void nativeUpdateUniforms( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithmTest.java index e3798e92c092..a6c35f1bd93c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithmTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PhonePipKeepClearAlgorithmTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip.phone; +package com.android.wm.shell.common.pip; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -29,9 +29,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.pip.PhonePipKeepClearAlgorithm; -import com.android.wm.shell.common.pip.PipBoundsAlgorithm; -import com.android.wm.shell.common.pip.PipBoundsState; import org.junit.Before; import org.junit.Test; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PhoneSizeSpecSourceTest.java index 85f1da5322ea..737735c9efcd 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PhoneSizeSpecSourceTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PhoneSizeSpecSourceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2023 The Android Open Source Project + * Copyright (C) 2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip.phone; +package com.android.wm.shell.common.pip; import static org.mockito.Mockito.when; @@ -27,9 +27,6 @@ import android.view.DisplayInfo; import com.android.wm.shell.R; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.DisplayLayout; -import com.android.wm.shell.common.pip.PhoneSizeSpecSource; -import com.android.wm.shell.common.pip.PipDisplayLayoutState; -import com.android.wm.shell.common.pip.SizeSpecSource; import org.junit.Assert; import org.junit.Before; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsAlgorithmTest.java index 080b0ae006ea..6bda2259b44c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsAlgorithmTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsAlgorithmTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip; +package com.android.wm.shell.common.pip; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -32,13 +32,6 @@ import androidx.test.filters.SmallTest; import com.android.wm.shell.R; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.DisplayLayout; -import com.android.wm.shell.common.pip.PhoneSizeSpecSource; -import com.android.wm.shell.common.pip.PipBoundsAlgorithm; -import com.android.wm.shell.common.pip.PipBoundsState; -import com.android.wm.shell.common.pip.PipDisplayLayoutState; -import com.android.wm.shell.common.pip.PipKeepClearAlgorithmInterface; -import com.android.wm.shell.common.pip.PipSnapAlgorithm; -import com.android.wm.shell.common.pip.SizeSpecSource; import org.junit.Before; import org.junit.Test; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java index 304da75f870c..ad664acfdc37 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsStateTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipBoundsStateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip; +package com.android.wm.shell.common.pip; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -36,10 +36,6 @@ import androidx.test.filters.SmallTest; import com.android.internal.util.function.TriConsumer; import com.android.wm.shell.R; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.pip.PhoneSizeSpecSource; -import com.android.wm.shell.common.pip.PipBoundsState; -import com.android.wm.shell.common.pip.PipDisplayLayoutState; -import com.android.wm.shell.common.pip.SizeSpecSource; import org.junit.Before; import org.junit.Test; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipDoubleTapHelperTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipDoubleTapHelperTest.java index b583acda1c9a..1756aad8fc9b 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipDoubleTapHelperTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipDoubleTapHelperTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 The Android Open Source Project + * Copyright (C) 2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip.phone; +package com.android.wm.shell.common.pip; import static com.android.wm.shell.common.pip.PipDoubleTapHelper.SIZE_SPEC_CUSTOM; import static com.android.wm.shell.common.pip.PipDoubleTapHelper.SIZE_SPEC_DEFAULT; @@ -29,8 +29,6 @@ import android.graphics.Rect; import android.testing.AndroidTestingRunner; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.pip.PipBoundsState; -import com.android.wm.shell.common.pip.PipDoubleTapHelper; import org.junit.Assert; import org.junit.Before; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipSnapAlgorithmTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipSnapAlgorithmTest.java index ac13d7ffcd61..3e71ab3e1ad4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipSnapAlgorithmTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/pip/PipSnapAlgorithmTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2025 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. @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wm.shell.pip; +package com.android.wm.shell.common.pip; import static org.junit.Assert.assertEquals; @@ -25,8 +25,6 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.pip.PipBoundsState; -import com.android.wm.shell.common.pip.PipSnapAlgorithm; import org.junit.Before; import org.junit.Test; diff --git a/libs/hwui/aconfig/hwui_flags.aconfig b/libs/hwui/aconfig/hwui_flags.aconfig index d3fc91b65829..7e1f2e2a3490 100644 --- a/libs/hwui/aconfig/hwui_flags.aconfig +++ b/libs/hwui/aconfig/hwui_flags.aconfig @@ -137,14 +137,6 @@ flag { } flag { - name: "shader_color_space" - is_exported: true - namespace: "core_graphics" - description: "API to set the working colorspace of a Shader or ColorFilter" - bug: "299670828" -} - -flag { name: "query_global_priority" namespace: "core_graphics" description: "Attempt to query whether the vulkan driver supports the requested global priority before queue creation." diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp index c02508977eba..eadb9dea566f 100644 --- a/libs/hwui/jni/Shader.cpp +++ b/libs/hwui/jni/Shader.cpp @@ -266,17 +266,11 @@ static jlong RuntimeShader_getNativeFinalizer(JNIEnv*, jobject) { return static_cast<jlong>(reinterpret_cast<uintptr_t>(&SkRuntimeShaderBuilder_delete)); } -static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderBuilder, jlong matrixPtr, - jlong colorSpacePtr) { +static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderBuilder, jlong matrixPtr) { SkRuntimeShaderBuilder* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(shaderBuilder); const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr); - auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpacePtr); sk_sp<SkShader> shader = builder->makeShader(matrix); ThrowIAE_IfNull(env, shader); - if (colorSpace) { - shader = shader->makeWithWorkingColorSpace(colorSpace); - ThrowIAE_IfNull(env, shader); - } return reinterpret_cast<jlong>(shader.release()); } @@ -385,7 +379,7 @@ static const JNINativeMethod gComposeShaderMethods[] = { static const JNINativeMethod gRuntimeShaderMethods[] = { {"nativeGetFinalizer", "()J", (void*)RuntimeShader_getNativeFinalizer}, - {"nativeCreateShader", "(JJJ)J", (void*)RuntimeShader_create}, + {"nativeCreateShader", "(JJ)J", (void*)RuntimeShader_create}, {"nativeCreateBuilder", "(Ljava/lang/String;)J", (void*)RuntimeShader_createShaderBuilder}, {"nativeUpdateUniforms", "(JLjava/lang/String;[FZ)V", (void*)RuntimeShader_updateFloatArrayUniforms}, diff --git a/ravenwood/runtime-jni/ravenwood_initializer.cpp b/ravenwood/runtime-jni/ravenwood_initializer.cpp index 391c5d56b212..8a35ade649b2 100644 --- a/ravenwood/runtime-jni/ravenwood_initializer.cpp +++ b/ravenwood/runtime-jni/ravenwood_initializer.cpp @@ -26,6 +26,10 @@ #include <fcntl.h> #include <set> +#include <fstream> +#include <iostream> +#include <string> +#include <cstdlib> #include "jni_helper.h" @@ -182,17 +186,82 @@ static jboolean removeSystemProperty(JNIEnv* env, jclass, jstring javaKey) { } } +// Find the PPID of child_pid using /proc/N/stat. The 4th field is the PPID. +// Also returns child_pid's process name (2nd field). +static pid_t getppid_of(pid_t child_pid, std::string& out_process_name) { + if (child_pid < 0) { + return -1; + } + std::string stat_file = "/proc/" + std::to_string(child_pid) + "/stat"; + std::ifstream stat_stream(stat_file); + if (!stat_stream.is_open()) { + ALOGW("Unable to open '%s': %s", stat_file.c_str(), strerror(errno)); + return -1; + } + + std::string field; + int field_count = 0; + while (std::getline(stat_stream, field, ' ')) { + if (++field_count == 4) { + return atoi(field.c_str()); + } + if (field_count == 2) { + out_process_name = field; + } + } + ALOGW("Unexpected format in '%s'", stat_file.c_str()); + return -1; +} + +// Find atest's PID. Climb up the process tree, and find "atest-py3". +static pid_t find_atest_pid() { + auto ret = getpid(); // self (isolation runner process) + + while (ret != -1) { + std::string proc; + ret = getppid_of(ret, proc); + if (proc == "(atest-py3)") { + return ret; + } + } + + return ret; +} + +// If $RAVENWOOD_LOG_OUT is set, redirect stdout/err to this file. +// Originally it was added to allow to monitor log in realtime, with +// RAVENWOOD_LOG_OUT=$(tty) atest... +// +// As a special case, if $RAVENWOOD_LOG_OUT is set to "-", we try to find +// atest's process and send the output to its stdout. It's sort of hacky, but +// this allows shell redirection to work on Ravenwood output too, +// so e.g. `atest ... |tee atest.log` would work on Ravenwood's output. +// (which wouldn't work with `RAVENWOOD_LOG_OUT=$(tty)`). +// +// Otherwise -- if $RAVENWOOD_LOG_OUT isn't set -- atest/tradefed just writes +// the test's output to its own log file. static void maybeRedirectLog() { auto ravenwoodLogOut = getenv("RAVENWOOD_LOG_OUT"); - if (ravenwoodLogOut == NULL) { + if (ravenwoodLogOut == NULL || *ravenwoodLogOut == '\0') { return; } - ALOGI("RAVENWOOD_LOG_OUT set. Redirecting output to %s", ravenwoodLogOut); + std::string path; + if (strcmp("-", ravenwoodLogOut) == 0) { + pid_t ppid = find_atest_pid(); + if (ppid < 0) { + ALOGI("RAVENWOOD_LOG_OUT set to '-', but unable to find atest's PID"); + return; + } + path = std::format("/proc/{}/fd/1", ppid); + } else { + path = ravenwoodLogOut; + } + ALOGI("RAVENWOOD_LOG_OUT set. Redirecting output to '%s'", path.c_str()); // Redirect stdin / stdout to /dev/tty. - int ttyFd = open(ravenwoodLogOut, O_WRONLY | O_APPEND); + int ttyFd = open(path.c_str(), O_WRONLY | O_APPEND); if (ttyFd == -1) { - ALOGW("$RAVENWOOD_LOG_OUT is set to %s, but failed to open: %s ", ravenwoodLogOut, + ALOGW("$RAVENWOOD_LOG_OUT is set, but failed to open '%s': %s ", path.c_str(), strerror(errno)); return; } diff --git a/services/core/java/com/android/server/am/AppStartInfoTracker.java b/services/core/java/com/android/server/am/AppStartInfoTracker.java index 961022b7231b..517279bd7527 100644 --- a/services/core/java/com/android/server/am/AppStartInfoTracker.java +++ b/services/core/java/com/android/server/am/AppStartInfoTracker.java @@ -54,15 +54,21 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ProcessMap; import com.android.internal.os.Clock; import com.android.internal.os.MonotonicClock; +import com.android.modules.utils.TypedXmlPullParser; +import com.android.modules.utils.TypedXmlSerializer; import com.android.server.IoThread; import com.android.server.ServiceThread; import com.android.server.SystemServiceManager; import com.android.server.wm.WindowProcessController; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; @@ -1006,6 +1012,12 @@ public final class AppStartInfoTracker { throws IOException, WireTypeMismatchException, ClassNotFoundException { long token = proto.start(fieldId); String pkgName = ""; + + // Create objects for reuse. + ByteArrayInputStream byteArrayInputStream = null; + ObjectInputStream objectInputStream = null; + TypedXmlPullParser typedXmlPullParser = null; + for (int next = proto.nextField(); next != ProtoInputStream.NO_MORE_FIELDS; next = proto.nextField()) { @@ -1017,7 +1029,7 @@ public final class AppStartInfoTracker { AppStartInfoContainer container = new AppStartInfoContainer(mAppStartInfoHistoryListSize); int uid = container.readFromProto(proto, AppsStartInfoProto.Package.USERS, - pkgName); + pkgName, byteArrayInputStream, objectInputStream, typedXmlPullParser); // If the isolated process flag is enabled and the uid is that of an isolated // process, then break early so that the container will not be added to mData. @@ -1052,6 +1064,12 @@ public final class AppStartInfoTracker { out = af.startWrite(); ProtoOutputStream proto = new ProtoOutputStream(out); proto.write(AppsStartInfoProto.LAST_UPDATE_TIMESTAMP, now); + + // Create objects for reuse. + ByteArrayOutputStream byteArrayOutputStream = null; + ObjectOutputStream objectOutputStream = null; + TypedXmlSerializer typedXmlSerializer = null; + synchronized (mLock) { succeeded = forEachPackageLocked( (packageName, records) -> { @@ -1060,8 +1078,9 @@ public final class AppStartInfoTracker { int uidArraySize = records.size(); for (int j = 0; j < uidArraySize; j++) { try { - records.valueAt(j) - .writeToProto(proto, AppsStartInfoProto.Package.USERS); + records.valueAt(j).writeToProto(proto, + AppsStartInfoProto.Package.USERS, byteArrayOutputStream, + objectOutputStream, typedXmlSerializer); } catch (IOException e) { Slog.w(TAG, "Unable to write app start info into persistent" + "storage: " + e); @@ -1414,19 +1433,23 @@ public final class AppStartInfoTracker { } @GuardedBy("mLock") - void writeToProto(ProtoOutputStream proto, long fieldId) throws IOException { + void writeToProto(ProtoOutputStream proto, long fieldId, + ByteArrayOutputStream byteArrayOutputStream, ObjectOutputStream objectOutputStream, + TypedXmlSerializer typedXmlSerializer) throws IOException { long token = proto.start(fieldId); proto.write(AppsStartInfoProto.Package.User.UID, mUid); int size = mInfos.size(); for (int i = 0; i < size; i++) { - mInfos.get(i) - .writeToProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO); + mInfos.get(i).writeToProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO, + byteArrayOutputStream, objectOutputStream, typedXmlSerializer); } proto.write(AppsStartInfoProto.Package.User.MONITORING_ENABLED, mMonitoringModeEnabled); proto.end(token); } - int readFromProto(ProtoInputStream proto, long fieldId, String packageName) + int readFromProto(ProtoInputStream proto, long fieldId, String packageName, + ByteArrayInputStream byteArrayInputStream, ObjectInputStream objectInputStream, + TypedXmlPullParser typedXmlPullParser) throws IOException, WireTypeMismatchException, ClassNotFoundException { long token = proto.start(fieldId); for (int next = proto.nextField(); @@ -1440,7 +1463,8 @@ public final class AppStartInfoTracker { // Create record with monotonic time 0 in case the persisted record does not // have a create time. ApplicationStartInfo info = new ApplicationStartInfo(0); - info.readFromProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO); + info.readFromProto(proto, AppsStartInfoProto.Package.User.APP_START_INFO, + byteArrayInputStream, objectInputStream, typedXmlPullParser); info.setPackageName(packageName); mInfos.add(info); break; diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index a4f983c33eb9..b607b0fce9ab 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -2952,13 +2952,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } private boolean isOpaqueInner(@NonNull WindowContainer<?> container) { - // If it's a leaf task fragment, then opacity is calculated based on its activities. - if (container.asTaskFragment() != null - && ((TaskFragment) container).isLeafTaskFragment()) { + final boolean isActivity = container.asActivityRecord() != null; + final boolean isLeafTaskFragment = container.asTaskFragment() != null + && ((TaskFragment) container).isLeafTaskFragment(); + if (isActivity || isLeafTaskFragment) { + // When it is an activity or leaf task fragment, then opacity is calculated based + // on itself or its activities. return container.getActivity(this, true /* traverseTopToBottom */, null /* boundary */) != null; } - // When not a leaf, it's considered opaque if any of its opaque children fill this + // Otherwise, it's considered opaque if any of its opaque children fill this // container, unless the children are adjacent fragments, in which case as long as they // are all opaque then |container| is also considered opaque, even if the adjacent // task fragment aren't filling. diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java index 3c74ad06a21f..a9be47d71213 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskSupervisorTests.java @@ -509,6 +509,32 @@ public class ActivityTaskSupervisorTests extends WindowTestsBase { assertThat(mSupervisor.mOpaqueContainerHelper.isOpaque(rootTask)).isTrue(); } + @Test + public void testOpaque_nonLeafTaskFragmentWithDirectActivity_opaque() { + final ActivityRecord directChildActivity = new ActivityBuilder(mAtm).setCreateTask(true) + .build(); + directChildActivity.setOccludesParent(true); + final Task nonLeafTask = directChildActivity.getTask(); + final TaskFragment directChildFragment = new TaskFragment(mAtm, new Binder(), + true /* createdByOrganizer */, false /* isEmbedded */); + nonLeafTask.addChild(directChildFragment, 0); + + assertThat(mSupervisor.mOpaqueContainerHelper.isOpaque(nonLeafTask)).isTrue(); + } + + @Test + public void testOpaque_nonLeafTaskFragmentWithDirectActivity_transparent() { + final ActivityRecord directChildActivity = new ActivityBuilder(mAtm).setCreateTask(true) + .build(); + directChildActivity.setOccludesParent(false); + final Task nonLeafTask = directChildActivity.getTask(); + final TaskFragment directChildFragment = new TaskFragment(mAtm, new Binder(), + true /* createdByOrganizer */, false /* isEmbedded */); + nonLeafTask.addChild(directChildFragment, 0); + + assertThat(mSupervisor.mOpaqueContainerHelper.isOpaque(nonLeafTask)).isFalse(); + } + @NonNull private TaskFragment createChildTaskFragment(@NonNull Task parent, @WindowConfiguration.WindowingMode int windowingMode, |