diff options
25 files changed, 277 insertions, 73 deletions
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java index 73bff08c626d..af0237491639 100644 --- a/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java +++ b/apct-tests/perftests/utils/src/android/perftests/utils/BenchmarkState.java @@ -20,6 +20,7 @@ import android.app.Activity; import android.app.Instrumentation; import android.os.Bundle; import android.os.Debug; +import android.os.Trace; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -129,17 +130,23 @@ public final class BenchmarkState { } private void beginWarmup() { + Trace.beginSection("Warmup"); mStartTimeNs = System.nanoTime(); mIteration = 0; mState = WARMUP; } + private void endWarmup() { + Trace.endSection(); + } + private void beginBenchmark(long warmupDuration, int iterations) { if (ENABLE_PROFILING) { File f = new File(InstrumentationRegistry.getContext().getDataDir(), "benchprof"); Log.d(TAG, "Tracing to: " + f.getAbsolutePath()); Debug.startMethodTracingSampling(f.getAbsolutePath(), 16 * 1024 * 1024, 100); } + Trace.beginSection("Benchmark"); mMaxIterations = (int) (TARGET_TEST_DURATION_NS / (warmupDuration / iterations)); mMaxIterations = Math.min(MAX_TEST_ITERATIONS, Math.max(mMaxIterations, MIN_TEST_ITERATIONS)); @@ -150,6 +157,10 @@ public final class BenchmarkState { mStartTimeNs = System.nanoTime(); } + private void endBenchmark() { + Trace.endSection(); + } + private boolean startNextTestRun() { final long currentTime = System.nanoTime(); mResults.add((currentTime - mStartTimeNs - mPausedDurationNs) / mMaxIterations); @@ -165,6 +176,7 @@ public final class BenchmarkState { return true; } mState = FINISHED; + endBenchmark(); return false; } mPausedDurationNs = 0; @@ -189,6 +201,7 @@ public final class BenchmarkState { // don't yet have a target iteration count. final long duration = System.nanoTime() - mStartTimeNs; if (mIteration >= WARMUP_MIN_ITERATIONS && duration >= WARMUP_DURATION_NS) { + endWarmup(); beginBenchmark(duration, mIteration); } return true; @@ -208,6 +221,7 @@ public final class BenchmarkState { mCustomizedIterations++; if (mCustomizedIterations >= mMaxCustomizedIterations) { mState = FINISHED; + endBenchmark(); return false; } mCustomizedIterationListener.onStart(mCustomizedIterations); diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index 12de82a46263..d563ad3fd3db 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -416,7 +416,6 @@ int main(int argc, char** argv) format = ANDROID_BITMAP_COMPRESS_FORMAT_PNG; } else if (jpeg) { format = ANDROID_BITMAP_COMPRESS_FORMAT_JPEG; - captureArgs.attachGainmap = true; } // setThreadPoolMaxThreadCount(0) actually tells the kernel it's diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 8594caee32c5..5171e68cdb85 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2431,6 +2431,12 @@ package android.os { method @NonNull public static byte[] digest(@NonNull java.io.InputStream, @NonNull String) throws java.io.IOException, java.security.NoSuchAlgorithmException; } + public class Handler { + method @FlaggedApi("android.os.mainline_vcn_platform_api") public final boolean hasMessagesOrCallbacks(); + method @FlaggedApi("android.os.mainline_vcn_platform_api") public final void removeCallbacksAndEqualMessages(@Nullable Object); + method @FlaggedApi("android.os.mainline_vcn_platform_api") public final void removeEqualMessages(int, @Nullable Object); + } + public class IpcDataCache<Query, Result> extends android.app.PropertyInvalidatedCache<Query,Result> { ctor public IpcDataCache(int, @NonNull String, @NonNull String, @NonNull String, @NonNull android.os.IpcDataCache.QueryHandler<Query,Result>); method public static void disableForCurrentProcess(@NonNull String); diff --git a/core/java/android/os/Handler.java b/core/java/android/os/Handler.java index d0828c384664..eaecd34b9d75 100644 --- a/core/java/android/os/Handler.java +++ b/core/java/android/os/Handler.java @@ -20,6 +20,7 @@ import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.util.Log; import android.util.Printer; @@ -839,6 +840,7 @@ public class Handler { *@hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi @FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API) public final void removeEqualMessages(int what, @Nullable Object object) { mQueue.removeEqualMessages(this, what, disallowNullArgumentIfShared(object)); @@ -872,6 +874,7 @@ public class Handler { *@hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi @FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API) public final void removeCallbacksAndEqualMessages(@Nullable Object token) { mQueue.removeCallbacksAndEqualMessages(this, disallowNullArgumentIfShared(token)); @@ -889,6 +892,7 @@ public class Handler { * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) + @TestApi @FlaggedApi(android.os.Flags.FLAG_MAINLINE_VCN_PLATFORM_API) public final boolean hasMessagesOrCallbacks() { return mQueue.hasMessages(this); diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 34bae46b484c..ebb6fb451699 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -137,4 +137,12 @@ flag { description: "Feature flag for Secure Lockdown feature" bug: "373422357" is_exported: true +} + +flag { + name: "subscribe_to_keyguard_locked_state_perm_priv_flag" + namespace: "psap_ai" + description: "Feature flag to add the privileged flag to the SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE permission" + bug: "380120712" + is_fixed_read_only: true }
\ No newline at end of file diff --git a/core/java/android/window/ScreenCapture.java b/core/java/android/window/ScreenCapture.java index 544642811a39..fc41307c4d1f 100644 --- a/core/java/android/window/ScreenCapture.java +++ b/core/java/android/window/ScreenCapture.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.graphics.Bitmap; import android.graphics.ColorSpace; +import android.graphics.Gainmap; import android.graphics.PixelFormat; import android.graphics.Rect; import android.hardware.HardwareBuffer; @@ -184,17 +185,29 @@ public class ScreenCapture { * @hide */ public static class ScreenshotHardwareBuffer { + private static final float EPSILON = 1.0f / 64.0f; + private final HardwareBuffer mHardwareBuffer; private final ColorSpace mColorSpace; private final boolean mContainsSecureLayers; private final boolean mContainsHdrLayers; + private final HardwareBuffer mGainmap; + private final float mHdrSdrRatio; public ScreenshotHardwareBuffer(HardwareBuffer hardwareBuffer, ColorSpace colorSpace, boolean containsSecureLayers, boolean containsHdrLayers) { + this(hardwareBuffer, colorSpace, containsSecureLayers, containsHdrLayers, null, 1.0f); + } + + public ScreenshotHardwareBuffer(HardwareBuffer hardwareBuffer, ColorSpace colorSpace, + boolean containsSecureLayers, boolean containsHdrLayers, HardwareBuffer gainmap, + float hdrSdrRatio) { mHardwareBuffer = hardwareBuffer; mColorSpace = colorSpace; mContainsSecureLayers = containsSecureLayers; mContainsHdrLayers = containsHdrLayers; + mGainmap = gainmap; + mHdrSdrRatio = hdrSdrRatio; } /** @@ -209,13 +222,12 @@ public class ScreenCapture { * @param containsHdrLayers Indicates whether this graphic buffer contains HDR content. */ private static ScreenshotHardwareBuffer createFromNative(HardwareBuffer hardwareBuffer, - int dataspace, boolean containsSecureLayers, boolean containsHdrLayers) { + int dataspace, boolean containsSecureLayers, boolean containsHdrLayers, + HardwareBuffer gainmap, float hdrSdrRatio) { ColorSpace colorSpace = ColorSpace.getFromDataSpace(dataspace); - return new ScreenshotHardwareBuffer( - hardwareBuffer, + return new ScreenshotHardwareBuffer(hardwareBuffer, colorSpace != null ? colorSpace : ColorSpace.get(ColorSpace.Named.SRGB), - containsSecureLayers, - containsHdrLayers); + containsSecureLayers, containsHdrLayers, gainmap, hdrSdrRatio); } public ColorSpace getColorSpace() { @@ -259,7 +271,22 @@ public class ScreenCapture { Log.w(TAG, "Failed to take screenshot. Null screenshot object"); return null; } - return Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace); + + Bitmap bitmap = Bitmap.wrapHardwareBuffer(mHardwareBuffer, mColorSpace); + if (mGainmap != null) { + Bitmap gainmapBitmap = Bitmap.wrapHardwareBuffer(mGainmap, null); + Gainmap gainmap = new Gainmap(gainmapBitmap); + gainmap.setRatioMin(1.0f, 1.0f, 1.0f); + gainmap.setRatioMax(mHdrSdrRatio, mHdrSdrRatio, mHdrSdrRatio); + gainmap.setGamma(1.0f, 1.0f, 1.0f); + gainmap.setEpsilonSdr(EPSILON, EPSILON, EPSILON); + gainmap.setEpsilonHdr(EPSILON, EPSILON, EPSILON); + gainmap.setMinDisplayRatioForHdrTransition(1.0f); + gainmap.setDisplayRatioForFullHdr(mHdrSdrRatio); + bitmap.setGainmap(gainmap); + } + + return bitmap; } } diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig index 1bd6743b40bd..30668a6c6b1d 100644 --- a/core/java/android/window/flags/windowing_frontend.aconfig +++ b/core/java/android/window/flags/windowing_frontend.aconfig @@ -9,16 +9,6 @@ flag { } flag { - name: "reset_draw_state_on_client_invisible" - namespace: "windowing_frontend" - description: "Reset draw state if the client is notified to be invisible" - bug: "373023636" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "wait_for_transition_on_display_switch" namespace: "windowing_frontend" description: "Waits for Shell transition to start before unblocking the screen after display switch" diff --git a/core/jni/android_window_ScreenCapture.cpp b/core/jni/android_window_ScreenCapture.cpp index 1a52fb74a1e9..5657fa146b5b 100644 --- a/core/jni/android_window_ScreenCapture.cpp +++ b/core/jni/android_window_ScreenCapture.cpp @@ -110,13 +110,19 @@ public: captureResults.fenceResult.value()->waitForever(LOG_TAG); jobject jhardwareBuffer = android_hardware_HardwareBuffer_createFromAHardwareBuffer( env, captureResults.buffer->toAHardwareBuffer()); + jobject jGainmap = nullptr; + if (captureResults.optionalGainMap) { + jGainmap = android_hardware_HardwareBuffer_createFromAHardwareBuffer( + env, captureResults.optionalGainMap->toAHardwareBuffer()); + } jobject screenshotHardwareBuffer = env->CallStaticObjectMethod(gScreenshotHardwareBufferClassInfo.clazz, gScreenshotHardwareBufferClassInfo.builder, jhardwareBuffer, static_cast<jint>(captureResults.capturedDataspace), captureResults.capturedSecureLayers, - captureResults.capturedHdrLayers); + captureResults.capturedHdrLayers, jGainmap, + captureResults.hdrSdrRatio); checkAndClearException(env, "builder"); env->CallVoidMethod(consumer.get(), gConsumerClassInfo.accept, screenshotHardwareBuffer, fenceStatus(captureResults.fenceResult)); @@ -340,7 +346,8 @@ int register_android_window_ScreenCapture(JNIEnv* env) { MakeGlobalRefOrDie(env, screenshotGraphicsBufferClazz); gScreenshotHardwareBufferClassInfo.builder = GetStaticMethodIDOrDie(env, screenshotGraphicsBufferClazz, "createFromNative", - "(Landroid/hardware/HardwareBuffer;IZZ)Landroid/window/" + "(Landroid/hardware/HardwareBuffer;IZZLandroid/hardware/" + "HardwareBuffer;F)Landroid/window/" "ScreenCapture$ScreenshotHardwareBuffer;"); return err; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index b0cc9959a3fa..82cad8b3a477 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -5648,11 +5648,21 @@ <!-- Allows an application to subscribe to device locked and keyguard locked (i.e., showing) state. - <p>Protection level: signature|role - <p>Intended for use by ROLE_ASSISTANT and signature apps only. + <p>Protection level: signature|module|role + <p>Intended for use by ROLE_ASSISTANT, VDM, and signature apps only. + --> + <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" + android:protectionLevel="signature|module|role" + android:featureFlag="!android.security.subscribe_to_keyguard_locked_state_perm_priv_flag"/> + + <!-- Allows an application to subscribe to device locked and keyguard locked (i.e., showing) + state. + <p>Protection level: signature|privileged|module|role + <p>Intended for use by ROLE_ASSISTANT, VDM, and signature / privileged apps only. --> <permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" - android:protectionLevel="signature|module|role"/> + android:protectionLevel="signature|privileged|module|role" + android:featureFlag="android.security.subscribe_to_keyguard_locked_state_perm_priv_flag"/> <!-- Must be required by a {@link android.service.autofill.AutofillService}, to ensure that only the system can bind to it. diff --git a/data/etc/com.android.systemui.xml b/data/etc/com.android.systemui.xml index 38ea4ac8d109..45952ea75b6f 100644 --- a/data/etc/com.android.systemui.xml +++ b/data/etc/com.android.systemui.xml @@ -94,5 +94,6 @@ <permission name="android.permission.CONTROL_UI_TRACING" /> <permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND" /> <permission name="android.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW"/> + <permission name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" /> </privapp-permissions> </permissions> diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 5c706b27de8b..2c542ec31a20 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -607,6 +607,8 @@ applications that come with the platform <!-- Permission required for CTS test - IntrusionDetectionManagerTest --> <permission name="android.permission.READ_INTRUSION_DETECTION_STATE" /> <permission name="android.permission.MANAGE_INTRUSION_DETECTION_STATE" /> + <!-- Permission required for CTS test - KeyguardLockedStateApiTest --> + <permission name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" /> </privapp-permissions> <privapp-permissions package="com.android.statementservice"> diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index e2db2c9e3827..677fd86aca9c 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -154,7 +154,10 @@ cc_defaults { "libstatssocket_lazy", "libtonemap", ], - whole_static_libs: ["hwui_flags_cc_lib"], + whole_static_libs: [ + "hwui_flags_cc_lib", + "libsurfaceflingerflags", + ], }, host: { static_libs: [ diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp index cc292d9de7b2..b1550b0b6888 100644 --- a/libs/hwui/hwui/Bitmap.cpp +++ b/libs/hwui/hwui/Bitmap.cpp @@ -19,6 +19,7 @@ #include "HardwareBitmapUploader.h" #include "Properties.h" #ifdef __ANDROID__ // Layoutlib does not support render thread +#include <com_android_graphics_surfaceflinger_flags.h> #include <private/android/AHardwareBufferHelpers.h> #include <ui/GraphicBuffer.h> #include <ui/GraphicBufferMapper.h> @@ -562,7 +563,7 @@ BitmapPalette Bitmap::computePalette(const SkImageInfo& info, const void* addr, bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* stream) { #ifdef __ANDROID__ // TODO: This isn't built for host for some reason? - if (hasGainmap() && format == JavaCompressFormat::Jpeg) { + if (hasGainmap()) { SkBitmap baseBitmap = getSkBitmap(); SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap(); if (gainmapBitmap.colorType() == SkColorType::kAlpha_8_SkColorType) { @@ -572,12 +573,27 @@ bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* str greyGainmap.setPixelRef(sk_ref_sp(gainmapBitmap.pixelRef()), 0, 0); gainmapBitmap = std::move(greyGainmap); } - SkJpegEncoder::Options options{.fQuality = quality}; - return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options, - gainmapBitmap.pixmap(), options, gainmap()->info); + switch (format) { + case JavaCompressFormat::Jpeg: { + SkJpegEncoder::Options options{.fQuality = quality}; + return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options, + gainmapBitmap.pixmap(), options, + gainmap()->info); + } + case JavaCompressFormat::Png: { + if (com::android::graphics::surfaceflinger::flags::true_hdr_screenshots()) { + SkGainmapInfo info = gainmap()->info; + SkPngEncoder::Options options{.fGainmap = &gainmapBitmap.pixmap(), + .fGainmapInfo = &info}; + return SkPngEncoder::Encode(stream, baseBitmap.pixmap(), options); + } + // fallthrough if we're not supporting HDR screenshots + } + default: + ALOGI("Format: %d doesn't support gainmap compression!", format); + } } #endif - SkBitmap skbitmap; getSkBitmap(&skbitmap); return compress(skbitmap, format, quality, stream); diff --git a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt index d3409c7256fd..e3aeaa85873d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/lifecycle/RepeatWhenAttachedTest.kt @@ -484,14 +484,12 @@ class RepeatWhenAttachedTest : SysuiTestCase() { private fun CoroutineScope.repeatWhenAttached(): DisposableHandle { return view.repeatWhenAttached( coroutineContext = coroutineContext, - block = block, + block = { block.invoke(this) }, ) } - private class Block : suspend LifecycleOwner.(View) -> Unit { - data class Invocation( - val lifecycleOwner: LifecycleOwner, - ) { + private class Block { + data class Invocation(val lifecycleOwner: LifecycleOwner) { val lifecycleState: Lifecycle.State get() = lifecycleOwner.lifecycle.currentState } @@ -504,7 +502,7 @@ class RepeatWhenAttachedTest : SysuiTestCase() { val latestLifecycleState: Lifecycle.State get() = _invocations.last().lifecycleState - override suspend fun invoke(lifecycleOwner: LifecycleOwner, view: View) { + fun invoke(lifecycleOwner: LifecycleOwner) { _invocations.add(Invocation(lifecycleOwner)) } } diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index ecffd382f542..3f9144f0d980 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -136,7 +136,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat final LocationManagerInternal locationManagerInternal = LocalServices.getService( LocationManagerInternal.class); - locationManagerInternal.setLocationPackageTagsListener( + if (locationManagerInternal != null) { + locationManagerInternal.setLocationPackageTagsListener( (uid, packageTagsList) -> { synchronized (mLock) { if (packageTagsList.isEmpty()) { @@ -158,6 +159,7 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat mLocationTags); } }); + } final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED); diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java index 137ea0617f21..51e0195f13fc 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -80,6 +80,7 @@ import com.android.server.utils.Slogf; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -1480,6 +1481,7 @@ public final class HintManagerService extends SystemService { if (!mSupportInfo.headroom.isCpuSupported) { throw new UnsupportedOperationException(); } + checkCpuHeadroomParams(params); final CpuHeadroomParams halParams = new CpuHeadroomParams(); halParams.tids = new int[]{Binder.getCallingPid()}; halParams.calculationType = params.calculationType; @@ -1487,10 +1489,6 @@ public final class HintManagerService extends SystemService { if (params.usesDeviceHeadroom) { halParams.tids = new int[]{}; } else if (params.tids != null && params.tids.length > 0) { - if (params.tids.length > 5) { - throw new IllegalArgumentException( - "More than 5 TIDs is requested: " + params.tids.length); - } if (SystemProperties.getBoolean(PROPERTY_CHECK_HEADROOM_TID, true)) { final int tgid = Process.getThreadGroupLeader(Binder.getCallingPid()); for (int tid : params.tids) { @@ -1530,11 +1528,45 @@ public final class HintManagerService extends SystemService { } } + private void checkCpuHeadroomParams(CpuHeadroomParamsInternal params) { + boolean calculationTypeMatched = false; + try { + for (final Field field : + CpuHeadroomParams.CalculationType.class.getDeclaredFields()) { + if (field.getType() == byte.class) { + byte value = field.getByte(null); + if (value == params.calculationType) { + calculationTypeMatched = true; + break; + } + } + } + } catch (IllegalAccessException e) { + Slog.wtf(TAG, "Checking the calculation type was unexpectedly not allowed"); + } + if (!calculationTypeMatched) { + throw new IllegalArgumentException( + "Unknown CPU headroom calculation type " + (int) params.calculationType); + } + if (params.calculationWindowMillis < 50 || params.calculationWindowMillis > 10000) { + throw new IllegalArgumentException( + "Invalid CPU headroom calculation window, expected [50, 10000] but got " + + params.calculationWindowMillis); + } + if (!params.usesDeviceHeadroom) { + if (params.tids != null && params.tids.length > 5) { + throw new IllegalArgumentException( + "More than 5 TIDs requested: " + params.tids.length); + } + } + } + @Override public GpuHeadroomResult getGpuHeadroom(@NonNull GpuHeadroomParamsInternal params) { if (!mSupportInfo.headroom.isGpuSupported) { throw new UnsupportedOperationException(); } + checkGpuHeadroomParams(params); final GpuHeadroomParams halParams = new GpuHeadroomParams(); halParams.calculationType = params.calculationType; halParams.calculationWindowMillis = params.calculationWindowMillis; @@ -1565,6 +1597,33 @@ public final class HintManagerService extends SystemService { } } + private void checkGpuHeadroomParams(GpuHeadroomParamsInternal params) { + boolean calculationTypeMatched = false; + try { + for (final Field field : + GpuHeadroomParams.CalculationType.class.getDeclaredFields()) { + if (field.getType() == byte.class) { + byte value = field.getByte(null); + if (value == params.calculationType) { + calculationTypeMatched = true; + break; + } + } + } + } catch (IllegalAccessException e) { + Slog.wtf(TAG, "Checking the calculation type was unexpectedly not allowed"); + } + if (!calculationTypeMatched) { + throw new IllegalArgumentException( + "Unknown GPU headroom calculation type " + (int) params.calculationType); + } + if (params.calculationWindowMillis < 50 || params.calculationWindowMillis > 10000) { + throw new IllegalArgumentException( + "Invalid GPU headroom calculation window, expected [50, 10000] but got " + + params.calculationWindowMillis); + } + } + @Override public long getCpuHeadroomMinIntervalMillis() { if (!mSupportInfo.headroom.isCpuSupported) { diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java index c26eeed6be35..fe14f6b172f1 100644 --- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java +++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java @@ -11447,7 +11447,7 @@ public class BatteryStatsImpl extends BatteryStats { mWifiPowerStatsCollector.addConsumer(this::recordPowerStats); mBluetoothPowerStatsCollector = new BluetoothPowerStatsCollector( - mPowerStatsCollectorInjector); + mPowerStatsCollectorInjector, this::onBluetoothPowerStatsRetrieved); mBluetoothPowerStatsCollector.addConsumer(this::recordPowerStats); mCameraPowerStatsCollector = new CameraPowerStatsCollector(mPowerStatsCollectorInjector); @@ -13417,6 +13417,13 @@ public class BatteryStatsImpl extends BatteryStats { private final BluetoothActivityInfoCache mLastBluetoothActivityInfo = new BluetoothActivityInfoCache(); + private void onBluetoothPowerStatsRetrieved(BluetoothActivityEnergyInfo info, + long elapsedRealtimeMs, long uptimeMs) { + // Do not populate consumed energy, because energy attribution is done by + // BluetoothPowerStatsProcessor. + updateBluetoothStateLocked(info, POWER_DATA_UNAVAILABLE, elapsedRealtimeMs, uptimeMs); + } + /** * Distribute Bluetooth energy info and network traffic to apps. * @@ -13425,10 +13432,6 @@ public class BatteryStatsImpl extends BatteryStats { @GuardedBy("this") public void updateBluetoothStateLocked(@Nullable final BluetoothActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) { - if (mBluetoothPowerStatsCollector.isEnabled()) { - return; - } - if (DEBUG_ENERGY) { Slog.d(TAG, "Updating bluetooth stats: " + info); } diff --git a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java b/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java index d7aa9876fe0d..c12ae63140c9 100644 --- a/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java +++ b/services/core/java/com/android/server/power/stats/BluetoothPowerStatsCollector.java @@ -15,6 +15,7 @@ */ package com.android.server.power.stats; +import android.annotation.Nullable; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; import android.bluetooth.UidTraffic; @@ -41,7 +42,10 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { private static final long BLUETOOTH_ACTIVITY_REQUEST_TIMEOUT = 20000; - private static final long ENERGY_UNSPECIFIED = -1; + interface Observer { + void onBluetoothPowerStatsRetrieved(@Nullable BluetoothActivityEnergyInfo info, + long elapsedRealtimeMs, long uptimeMs); + } public interface BluetoothStatsRetriever { interface Callback { @@ -65,6 +69,7 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { } private final Injector mInjector; + private final Observer mObserver; private com.android.server.power.stats.format.BluetoothPowerStatsLayout mLayout; private boolean mIsInitialized; @@ -89,13 +94,14 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { private final SparseArray<UidStats> mUidStats = new SparseArray<>(); - public BluetoothPowerStatsCollector(Injector injector) { + public BluetoothPowerStatsCollector(Injector injector, @Nullable Observer observer) { super(injector.getHandler(), injector.getPowerStatsCollectionThrottlePeriod( BatteryConsumer.powerComponentIdToString( BatteryConsumer.POWER_COMPONENT_BLUETOOTH)), injector.getUidResolver(), injector.getClock()); mInjector = injector; + mObserver = observer; } @Override @@ -146,15 +152,20 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { Arrays.fill(mDeviceStats, 0); mPowerStats.uidStats.clear(); - collectBluetoothActivityInfo(); + BluetoothActivityEnergyInfo activityInfo = collectBluetoothActivityInfo(); collectBluetoothScanStats(); mConsumedEnergyHelper.collectConsumedEnergy(mPowerStats, mLayout); + if (mObserver != null) { + mObserver.onBluetoothPowerStatsRetrieved(activityInfo, mClock.elapsedRealtime(), + mClock.uptimeMillis()); + } + return mPowerStats; } - private void collectBluetoothActivityInfo() { + private BluetoothActivityEnergyInfo collectBluetoothActivityInfo() { CompletableFuture<BluetoothActivityEnergyInfo> immediateFuture = new CompletableFuture<>(); boolean success = mBluetoothStatsRetriever.requestControllerActivityEnergyInfo( Runnable::run, @@ -173,7 +184,7 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { }); if (!success) { - return; + return null; } BluetoothActivityEnergyInfo activityInfo; @@ -186,7 +197,7 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { } if (activityInfo == null) { - return; + return null; } long rxTime = activityInfo.getControllerRxTimeMillis(); @@ -241,6 +252,8 @@ public class BluetoothPowerStatsCollector extends PowerStatsCollector { mLayout.setUidTxBytes(stats, txDelta); } } + + return activityInfo; } private void collectBluetoothScanStats() { diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index db9e19abfae2..29a71328127b 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -248,7 +248,6 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.sEnableShellTransitions; import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY; -import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; @@ -5607,18 +5606,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // stopped, then we need to set up to wait for its windows to be ready. if (!isVisible() || mAppStopped) { clearAllDrawn(); - // Reset the draw state in order to prevent the starting window to be immediately - // dismissed when the app still has the surface. - if (!Flags.resetDrawStateOnClientInvisible() - && !isVisible() && !isClientVisible()) { - forAllWindows(w -> { - if (w.mWinAnimator.mDrawState == HAS_DRAWN) { - w.mWinAnimator.resetDrawState(); - // Force add to mResizingWindows, so the window will report drawn. - w.forceReportingResized(); - } - }, true /* traverseTopToBottom */); - } } // In the case where we are making an app visible but holding off for a transition, diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index cebe790bb1b9..90bf053dfbef 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3311,8 +3311,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // Because the client is notified to be invisible, it should no longer be considered as // drawn state. This prevent the app from showing incomplete content if the app is // requested to be visible in a short time (e.g. before activity stopped). - if (Flags.resetDrawStateOnClientInvisible() && !clientVisible && mActivityRecord != null - && mWinAnimator.mDrawState == HAS_DRAWN) { + if (!clientVisible && mActivityRecord != null && mWinAnimator.mDrawState == HAS_DRAWN) { mWinAnimator.resetDrawState(); // Make sure the app can report drawn if it becomes visible again. forceReportingResized(); diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java index b166514ce0b9..428e438443cd 100644 --- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -1274,6 +1274,53 @@ public class HintManagerServiceTest { } @Test + public void testCpuHeadroomInvalidParams() { + HintManagerService service = createService(); + final CpuHeadroomParamsInternal param1 = new CpuHeadroomParamsInternal(); + param1.calculationType = 100; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getCpuHeadroom(param1); + }); + + final CpuHeadroomParamsInternal param2 = new CpuHeadroomParamsInternal(); + param2.calculationWindowMillis = 49; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getCpuHeadroom(param2); + }); + param2.calculationWindowMillis = 10001; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getCpuHeadroom(param2); + }); + + final CpuHeadroomParamsInternal param3 = new CpuHeadroomParamsInternal(); + param3.tids = new int[]{1, 2, 3, 4, 5, 6}; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getCpuHeadroom(param3); + }); + } + + @Test + public void testGpuHeadroomInvalidParams() { + HintManagerService service = createService(); + final GpuHeadroomParamsInternal param1 = new GpuHeadroomParamsInternal(); + param1.calculationType = 100; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getGpuHeadroom(param1); + }); + + final GpuHeadroomParamsInternal param2 = new GpuHeadroomParamsInternal(); + param2.calculationWindowMillis = 49; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getGpuHeadroom(param2); + }); + param2.calculationWindowMillis = 10001; + assertThrows(IllegalArgumentException.class, () -> { + service.getBinderServiceInstance().getGpuHeadroom(param2); + }); + } + + + @Test public void testCpuHeadroomCache() throws Exception { CpuHeadroomParamsInternal params1 = new CpuHeadroomParamsInternal(); CpuHeadroomParams halParams1 = new CpuHeadroomParams(); diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java index e392c5d190f7..3895cb480847 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BluetoothPowerStatsCollectorTest.java @@ -225,7 +225,10 @@ public class BluetoothPowerStatsCollectorTest { } private PowerStats collectPowerStats() { - BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector); + List<BluetoothActivityEnergyInfo> expected = new ArrayList<>(); + List<BluetoothActivityEnergyInfo> observed = new ArrayList<>(); + BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector, + (info, elapsedRealtimeMs, uptimeMs) -> observed.add(info)); collector.setEnabled(true); when(mConsumedEnergyRetriever.getVoltageMv()).thenReturn(3500); @@ -236,6 +239,7 @@ public class BluetoothPowerStatsCollectorTest { mockUidTraffic(APP_UID1, 100, 200), mockUidTraffic(APP_UID2, 300, 400), mockUidTraffic(ISOLATED_UID, 500, 600)); + expected.add(mBluetoothActivityEnergyInfo); mUidScanTimes.put(APP_UID1, 100); @@ -248,6 +252,7 @@ public class BluetoothPowerStatsCollectorTest { mockUidTraffic(APP_UID1, 1100, 2200), mockUidTraffic(APP_UID2, 3300, 4400), mockUidTraffic(ISOLATED_UID, 5500, 6600)); + expected.add(mBluetoothActivityEnergyInfo); mUidScanTimes.clear(); mUidScanTimes.put(APP_UID1, 200); @@ -257,7 +262,10 @@ public class BluetoothPowerStatsCollectorTest { mockConsumedEnergy(777, 64321); mStatsRule.setTime(20000, 20000); - return collector.collectStats(); + PowerStats powerStats = collector.collectStats(); + + assertThat(observed).isEqualTo(expected); + return powerStats; } private void mockConsumedEnergy(int consumerId, long energyUWs) { diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java index 2c580e5ab0d2..60131861ce89 100644 --- a/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java +++ b/services/tests/powerstatstests/src/com/android/server/power/stats/processor/BluetoothPowerStatsProcessorTest.java @@ -170,7 +170,7 @@ public class BluetoothPowerStatsProcessorTest { PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats( () -> new BluetoothPowerStatsProcessor(mStatsRule.getPowerProfile())); - BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector); + BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector, null); collector.setEnabled(true); mBluetoothActivityEnergyInfo = mockBluetoothActivityEnergyInfo(1000, 600, 100, 200, mockUidTraffic(APP_UID1, 100, 200), @@ -271,7 +271,7 @@ public class BluetoothPowerStatsProcessorTest { PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats( () -> new BluetoothPowerStatsProcessor(mStatsRule.getPowerProfile())); - BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector); + BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector, null); collector.setEnabled(true); mBluetoothActivityEnergyInfo = mockBluetoothActivityEnergyInfo(1000, 600, 100, 200, mockUidTraffic(APP_UID1, 100, 200), @@ -371,7 +371,7 @@ public class BluetoothPowerStatsProcessorTest { PowerComponentAggregatedPowerStats aggregatedStats = createAggregatedPowerStats( () -> new BluetoothPowerStatsProcessor(mStatsRule.getPowerProfile())); - BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector); + BluetoothPowerStatsCollector collector = new BluetoothPowerStatsCollector(mInjector, null); collector.setEnabled(true); mBluetoothActivityEnergyInfo = mockBluetoothActivityEnergyInfo(1000, 600, 100, 200, mockUidTraffic(APP_UID1, 100, 200), diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index 1b0d9dc3b170..661d07e09f99 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -3253,7 +3253,6 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse(activity.isVisibleRequested()); player.start(); - mSetFlagsRule.enableFlags(Flags.FLAG_RESET_DRAW_STATE_ON_CLIENT_INVISIBLE); // ActivityRecord#commitVisibility(false) -> WindowState#sendAppVisibilityToClients(). player.finish(); assertFalse(activity.isVisible()); diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java index f687af633283..cf807a295a2d 100644 --- a/telephony/java/android/telephony/satellite/SatelliteManager.java +++ b/telephony/java/android/telephony/satellite/SatelliteManager.java @@ -2574,6 +2574,8 @@ public final class SatelliteManager { * @param executor The executor on which the callback will be called. * @param callback The callback to handle the selected satellite subscription changed event. * + * @return The {@link SatelliteResult} result of the operation. + * * @throws SecurityException if the caller doesn't have required permission. * @throws IllegalStateException if the Telephony process is not currently available. * @@ -3301,7 +3303,7 @@ public final class SatelliteManager { * @param executor The executor on which the callback will be called. * @param callback The callback to handle the satellite supoprted state changed event. * - * @return The result of the operation. + * @return The {@link SatelliteResult} result of the operation. * * @throws SecurityException if the caller doesn't have required permission. * @throws IllegalStateException if the Telephony process is not currently available. @@ -3383,7 +3385,7 @@ public final class SatelliteManager { * * @param executor The executor on which the callback will be called. * @param callback The callback to handle satellite communication allowed state changed event. - * @return The result of the operation. + * @return The {@link SatelliteResult} result of the operation. * @throws SecurityException if the caller doesn't have required permission. * @throws IllegalStateException if the Telephony process is not currently available. * @hide |