Merge "Make PointerEventDispatcherTest faster" into main
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index eb672dc..b159321 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -48,9 +48,11 @@
import com.android.internal.appwidget.IAppWidgetService;
import com.android.internal.os.BackgroundThread;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
/**
* Updates AppWidget state; gets information about installed AppWidget providers and other
@@ -785,7 +787,25 @@
return;
}
try {
- mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
+ if (RemoteViews.isAdapterConversionEnabled()) {
+ List<CompletableFuture<Void>> updateFutures = new ArrayList<>();
+ for (int i = 0; i < appWidgetIds.length; i++) {
+ final int widgetId = appWidgetIds[i];
+ updateFutures.add(CompletableFuture.runAsync(() -> {
+ try {
+ RemoteViews views = mService.getAppWidgetViews(mPackageName, widgetId);
+ if (views.replaceRemoteCollections(viewId)) {
+ updateAppWidget(widgetId, views);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Error notifying changes in RemoteViews", e);
+ }
+ }));
+ }
+ CompletableFuture.allOf(updateFutures.toArray(CompletableFuture[]::new)).join();
+ } else {
+ mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
+ }
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 66aa66c..b0e5f777 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -786,6 +786,42 @@
}
}
+ /**
+ * @hide
+ * @return True if there is a change
+ */
+ public boolean replaceRemoteCollections(int viewId) {
+ boolean isActionReplaced = false;
+ if (mActions != null) {
+ for (int i = 0; i < mActions.size(); i++) {
+ Action action = mActions.get(i);
+ if (action instanceof SetRemoteCollectionItemListAdapterAction itemsAction
+ && itemsAction.viewId == viewId
+ && itemsAction.mServiceIntent != null) {
+ mActions.set(i, new SetRemoteCollectionItemListAdapterAction(itemsAction.viewId,
+ itemsAction.mServiceIntent));
+ isActionReplaced = true;
+ } else if (action instanceof ViewGroupActionAdd groupAction
+ && groupAction.mNestedViews != null) {
+ isActionReplaced |= groupAction.mNestedViews.replaceRemoteCollections(viewId);
+ }
+ }
+ }
+ if (mSizedRemoteViews != null) {
+ for (int i = 0; i < mSizedRemoteViews.size(); i++) {
+ isActionReplaced |= mSizedRemoteViews.get(i).replaceRemoteCollections(viewId);
+ }
+ }
+ if (mLandscape != null) {
+ isActionReplaced |= mLandscape.replaceRemoteCollections(viewId);
+ }
+ if (mPortrait != null) {
+ isActionReplaced |= mPortrait.replaceRemoteCollections(viewId);
+ }
+
+ return isActionReplaced;
+ }
+
private static void visitIconUri(Icon icon, @NonNull Consumer<Uri> visitor) {
if (icon != null && (icon.getType() == Icon.TYPE_URI
|| icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) {
@@ -1059,18 +1095,21 @@
private class SetRemoteCollectionItemListAdapterAction extends Action {
private @NonNull CompletableFuture<RemoteCollectionItems> mItemsFuture;
+ final Intent mServiceIntent;
SetRemoteCollectionItemListAdapterAction(@IdRes int id,
@NonNull RemoteCollectionItems items) {
viewId = id;
items.setHierarchyRootData(getHierarchyRootData());
mItemsFuture = CompletableFuture.completedFuture(items);
+ mServiceIntent = null;
}
SetRemoteCollectionItemListAdapterAction(@IdRes int id, Intent intent) {
viewId = id;
mItemsFuture = getItemsFutureFromIntentWithTimeout(intent);
setHierarchyRootData(getHierarchyRootData());
+ mServiceIntent = intent;
}
private static CompletableFuture<RemoteCollectionItems> getItemsFutureFromIntentWithTimeout(
@@ -1119,6 +1158,7 @@
viewId = parcel.readInt();
mItemsFuture = CompletableFuture.completedFuture(
new RemoteCollectionItems(parcel, getHierarchyRootData()));
+ mServiceIntent = parcel.readTypedObject(Intent.CREATOR);
}
@Override
@@ -1148,6 +1188,7 @@
dest.writeInt(viewId);
RemoteCollectionItems items = getCollectionItemsFromFuture(mItemsFuture);
items.writeToParcel(dest, flags, /* attached= */ true);
+ dest.writeTypedObject(mServiceIntent, flags);
}
@Override
@@ -4768,9 +4809,7 @@
*/
@Deprecated
public void setRemoteAdapter(@IdRes int viewId, Intent intent) {
- if (AppGlobals.getIntCoreSetting(
- SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION,
- SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT ? 1 : 0) == 1) {
+ if (isAdapterConversionEnabled()) {
addAction(new SetRemoteCollectionItemListAdapterAction(viewId, intent));
return;
}
@@ -4778,6 +4817,16 @@
}
/**
+ * @hide
+ * @return True if the remote adapter conversion is enabled
+ */
+ public static boolean isAdapterConversionEnabled() {
+ return AppGlobals.getIntCoreSetting(
+ SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION,
+ SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT ? 1 : 0) == 1;
+ }
+
+ /**
* Creates a simple Adapter for the viewId specified. The viewId must point to an AdapterView,
* ie. {@link ListView}, {@link GridView}, {@link StackView} or {@link AdapterViewAnimator}.
* This is a simpler but less flexible approach to populating collection widgets. Its use is
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 9eec5b1..7602f69 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2705,6 +2705,9 @@
backlight values -->
<bool name="config_displayBrightnessBucketsInDoze">false</bool>
+ <!-- True to skip the fade animation on display off event -->
+ <bool name="config_displayColorFadeDisabled">false</bool>
+
<!-- Power Management: Specifies whether to decouple the auto-suspend state of the
device from the display on/off state.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6af34a2..978849d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3867,6 +3867,7 @@
<java-symbol type="bool" name="config_dozeSupportsAodWallpaper" />
<java-symbol type="bool" name="config_displayBlanksAfterDoze" />
<java-symbol type="bool" name="config_displayBrightnessBucketsInDoze" />
+ <java-symbol type="bool" name="config_displayColorFadeDisabled" />
<java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
<java-symbol type="string" name="config_headlineFontFamily" />
<java-symbol type="string" name="config_headlineFontFamilyMedium" />
diff --git a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
index 0ca912e..d93e9ba 100644
--- a/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
+++ b/libs/WindowManager/Shell/res/layout/desktop_mode_focused_window_decor.xml
@@ -25,9 +25,8 @@
<ImageButton
android:id="@+id/caption_handle"
- android:layout_width="176dp"
+ android:layout_width="128dp"
android:layout_height="42dp"
- android:paddingHorizontal="24dp"
android:paddingVertical="19dp"
android:contentDescription="@string/handle_text"
android:src="@drawable/decor_handle_dark"
diff --git a/packages/SystemUI/shared/res/values-my/bools.xml b/packages/SystemUI/shared/res/values-my/bools.xml
deleted file mode 100644
index bcf4b2d..0000000
--- a/packages/SystemUI/shared/res/values-my/bools.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 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.
--->
-
-<!-- Formatting note: terminate all comments with a period, to avoid breaking
- the documentation output. To suppress comment lines from the documentation
- output, insert an eat-comment element after the comment lines.
--->
-
-<resources>
- <!-- Whether to add padding at the bottom of the complication clock -->
- <bool name="dream_overlay_complication_clock_bottom_padding">true</bool>
-</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/res/values/bools.xml b/packages/SystemUI/shared/res/values/bools.xml
deleted file mode 100644
index 4b74ead..0000000
--- a/packages/SystemUI/shared/res/values/bools.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2023 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.
--->
-
-<!-- Formatting note: terminate all comments with a period, to avoid breaking
- the documentation output. To suppress comment lines from the documentation
- output, insert an eat-comment element after the comment lines.
--->
-
-<resources>
- <!-- Whether to add padding at the bottom of the complication clock -->
- <bool name="dream_overlay_complication_clock_bottom_padding">false</bool>
-</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextClock.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextClock.kt
index bc4879d..5a6f184 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextClock.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/shadow/DoubleShadowTextClock.kt
@@ -16,51 +16,34 @@
package com.android.systemui.shared.shadow
import android.content.Context
-import android.content.res.Resources
-import android.content.res.TypedArray
import android.graphics.Canvas
import android.util.AttributeSet
import android.widget.TextClock
import com.android.systemui.shared.R
import com.android.systemui.shared.shadow.DoubleShadowTextHelper.ShadowInfo
import com.android.systemui.shared.shadow.DoubleShadowTextHelper.applyShadows
-import javax.inject.Inject
import kotlin.math.floor
/** Extension of [TextClock] which draws two shadows on the text (ambient and key shadows) */
-class ResourcesProvider @Inject constructor(private val context: Context) {
- fun getResources(): Resources {
- return context.resources
- }
-
- fun getBoolean(resourceId: Int): Boolean {
- return getResources().getBoolean(resourceId)
- }
-}
-
class DoubleShadowTextClock
@JvmOverloads
constructor(
- private val resourcesProvider: ResourcesProvider,
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
- defStyleRes: Int = 0,
- attributesInput: TypedArray? = null
+ defStyleRes: Int = 0
) : TextClock(context, attrs, defStyleAttr, defStyleRes) {
private val mAmbientShadowInfo: ShadowInfo
private val mKeyShadowInfo: ShadowInfo
init {
- var attributes: TypedArray =
- attributesInput
- ?: context.obtainStyledAttributes(
- attrs,
- R.styleable.DoubleShadowTextClock,
- defStyleAttr,
- defStyleRes
- )
-
+ val attributes =
+ context.obtainStyledAttributes(
+ attrs,
+ R.styleable.DoubleShadowTextClock,
+ defStyleAttr,
+ defStyleRes
+ )
try {
val keyShadowBlur =
attributes.getDimensionPixelSize(R.styleable.DoubleShadowTextClock_keyShadowBlur, 0)
@@ -115,29 +98,18 @@
0
)
if (removeTextDescent) {
- val addBottomPaddingToClock =
- resourcesProvider.getBoolean(
- R.bool.dream_overlay_complication_clock_bottom_padding
- )
- val metrics = paint.fontMetrics
- val padding =
- if (addBottomPaddingToClock) {
- textDescentExtraPadding +
- floor(metrics.descent.toDouble()).toInt() / paddingDividedOffset
- } else {
- textDescentExtraPadding - floor(metrics.descent.toDouble()).toInt()
- }
- setPaddingRelative(0, 0, 0, padding)
+ setPaddingRelative(
+ 0,
+ 0,
+ 0,
+ textDescentExtraPadding - floor(paint.fontMetrics.descent.toDouble()).toInt()
+ )
}
} finally {
attributes.recycle()
}
}
- companion object {
- private val paddingDividedOffset = 2
- }
-
public override fun onDraw(canvas: Canvas) {
applyShadows(mKeyShadowInfo, mAmbientShadowInfo, this, canvas) { super.onDraw(canvas) }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
deleted file mode 100644
index 3c9db8f..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shadow/DoubleShadowTextClockTest.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2023 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.systemui.shadow
-
-import android.content.Context
-import android.content.res.TypedArray
-import android.testing.AndroidTestingRunner
-import android.util.AttributeSet
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.shared.shadow.DoubleShadowTextClock
-import com.android.systemui.shared.shadow.ResourcesProvider
-import com.android.systemui.util.mockito.whenever
-import junit.framework.Assert.assertTrue
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class DoubleShadowTextClockTest : SysuiTestCase() {
- @get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
-
- @Mock lateinit var resourcesProvider: ResourcesProvider
-
- @Mock lateinit var attributes: TypedArray
-
- private lateinit var context: Context
- private var attrs: AttributeSet? = null
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- context = getContext()
- whenever(attributes.getBoolean(R.styleable.DoubleShadowTextClock_removeTextDescent, false))
- .thenReturn(true)
- }
-
- @Test
- fun testAddingPaddingToBottomOfClockWhenConfigIsTrue() {
- whenever(
- resourcesProvider.getBoolean(R.bool.dream_overlay_complication_clock_bottom_padding)
- )
- .thenReturn(true)
-
- val doubleShadowTextClock =
- DoubleShadowTextClock(
- resourcesProvider = resourcesProvider,
- context = context,
- attrs = attrs,
- attributesInput = attributes
- )
- assertTrue(doubleShadowTextClock.paddingBottom > 0)
- }
-
- @Test
- fun testRemovingPaddingToBottomOfClockWhenConfigIsFalse() {
- whenever(
- resourcesProvider.getBoolean(R.bool.dream_overlay_complication_clock_bottom_padding)
- )
- .thenReturn(false)
-
- val doubleShadowTextClock =
- DoubleShadowTextClock(
- resourcesProvider = resourcesProvider,
- context = context,
- attrs = attrs,
- attributesInput = attributes
- )
- assertTrue(doubleShadowTextClock.paddingBottom < 0)
- }
-}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index c980644..75c15eb 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -722,7 +722,9 @@
setUpAutoBrightness(resources, handler);
- mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic();
+ mColorFadeEnabled = !ActivityManager.isLowRamDeviceStatic()
+ && !resources.getBoolean(
+ com.android.internal.R.bool.config_displayColorFadeDisabled);
mColorFadeFadesConfig = resources.getBoolean(
com.android.internal.R.bool.config_animateScreenLights);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 847df98..42683d8 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -613,7 +613,7 @@
setUpAutoBrightness(resources, handler);
- mColorFadeEnabled = mInjector.isColorFadeEnabled();
+ mColorFadeEnabled = mInjector.isColorFadeEnabled(resources);
mColorFadeFadesConfig = resources.getBoolean(
R.bool.config_animateScreenLights);
@@ -3005,8 +3005,10 @@
sensorManager, resources);
}
- boolean isColorFadeEnabled() {
- return !ActivityManager.isLowRamDeviceStatic();
+ boolean isColorFadeEnabled(Resources resources) {
+ return !ActivityManager.isLowRamDeviceStatic()
+ && !resources.getBoolean(
+ com.android.internal.R.bool.config_displayColorFadeDisabled);
}
}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
index d8e6c26..d1d27f3 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
@@ -17,6 +17,7 @@
package com.android.server.powerstats;
import android.content.Context;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.util.FileRotator;
@@ -27,6 +28,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.Date;
import java.util.concurrent.locks.ReentrantLock;
/**
@@ -266,4 +268,51 @@
mLock.unlock();
}
}
+
+ /**
+ * Dump stats about stored data.
+ */
+ public void dump(IndentingPrintWriter ipw) {
+ mLock.lock();
+ try {
+ final int versionDot = mDataStorageFilename.lastIndexOf('.');
+ final String beforeVersionDot = mDataStorageFilename.substring(0, versionDot);
+ final File[] files = mDataStorageDir.listFiles();
+
+ int number = 0;
+ int dataSize = 0;
+ long earliestLogEpochTime = Long.MAX_VALUE;
+ for (int i = 0; i < files.length; i++) {
+ // Check that the stems before the version match.
+ final File file = files[i];
+ final String fileName = file.getName();
+ if (files[i].getName().startsWith(beforeVersionDot)) {
+ number++;
+ dataSize += file.length();
+ final int firstTimeChar = fileName.lastIndexOf('.') + 1;
+ final int endChar = fileName.lastIndexOf('-');
+ try {
+ final Long startTime =
+ Long.parseLong(fileName.substring(firstTimeChar, endChar));
+ if (startTime != null && startTime < earliestLogEpochTime) {
+ earliestLogEpochTime = startTime;
+ }
+ } catch (NumberFormatException nfe) {
+ Slog.e(TAG,
+ "Failed to extract start time from file : " + fileName, nfe);
+ }
+ }
+ }
+
+ if (earliestLogEpochTime != Long.MAX_VALUE) {
+ ipw.println("Earliest data time : " + new Date(earliestLogEpochTime));
+ } else {
+ ipw.println("Failed to parse earliest data time!!!");
+ }
+ ipw.println("# files : " + number);
+ ipw.println("Total data size (B) : " + dataSize);
+ } finally {
+ mLock.unlock();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index 39ead13..e80a86d 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -30,6 +30,7 @@
import android.os.Message;
import android.os.SystemClock;
import android.util.AtomicFile;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
@@ -354,4 +355,23 @@
updateCacheFile(residencyCacheFilename, powerEntityBytes);
}
}
+
+ /**
+ * Dump stats about stored data.
+ */
+ public void dump(IndentingPrintWriter ipw) {
+ ipw.println("PowerStats Meter Data:");
+ ipw.increaseIndent();
+ mPowerStatsMeterStorage.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.println("PowerStats Model Data:");
+ ipw.increaseIndent();
+ mPowerStatsModelStorage.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.println("PowerStats State Residency Data:");
+ ipw.increaseIndent();
+ mPowerStatsResidencyStorage.dump(ipw);
+ ipw.decreaseIndent();
+ }
+
}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 9832c49..5609f69 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -42,6 +42,7 @@
import android.power.PowerStatsInternal;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Slog;
@@ -232,18 +233,31 @@
} else if ("residency".equals(args[1])) {
mPowerStatsLogger.writeResidencyDataToFile(fd);
}
- } else if (args.length == 0) {
- pw.println("PowerStatsService dumpsys: available PowerEntities");
+ } else {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
+ ipw.println("PowerStatsService dumpsys: available PowerEntities");
PowerEntity[] powerEntity = getPowerStatsHal().getPowerEntityInfo();
- PowerEntityUtils.dumpsys(powerEntity, pw);
+ ipw.increaseIndent();
+ PowerEntityUtils.dumpsys(powerEntity, ipw);
+ ipw.decreaseIndent();
- pw.println("PowerStatsService dumpsys: available Channels");
+ ipw.println("PowerStatsService dumpsys: available Channels");
Channel[] channel = getPowerStatsHal().getEnergyMeterInfo();
- ChannelUtils.dumpsys(channel, pw);
+ ipw.increaseIndent();
+ ChannelUtils.dumpsys(channel, ipw);
+ ipw.decreaseIndent();
- pw.println("PowerStatsService dumpsys: available EnergyConsumers");
+ ipw.println("PowerStatsService dumpsys: available EnergyConsumers");
EnergyConsumer[] energyConsumer = getPowerStatsHal().getEnergyConsumerInfo();
- EnergyConsumerUtils.dumpsys(energyConsumer, pw);
+ ipw.increaseIndent();
+ EnergyConsumerUtils.dumpsys(energyConsumer, ipw);
+ ipw.decreaseIndent();
+
+ ipw.println("PowerStatsService dumpsys: PowerStatsLogger stats");
+ ipw.increaseIndent();
+ mPowerStatsLogger.dump(ipw);
+ ipw.decreaseIndent();
+
}
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 7572a64..bbc35a3 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -63,6 +63,8 @@
*/
class SurfaceAnimationRunner {
+ private static final String TAG = SurfaceAnimationRunner.class.getSimpleName();
+
private final Object mLock = new Object();
/**
@@ -186,6 +188,16 @@
// We must wait for t to be committed since otherwise the leash doesn't have the
// windows we want to screenshot and extend as children.
t.addTransactionCommittedListener(mEdgeExtensionExecutor, () -> {
+ if (!animationLeash.isValid()) {
+ Log.e(TAG, "Animation leash is not valid");
+ synchronized (mEdgeExtensionLock) {
+ mEdgeExtensions.remove(animationLeash);
+ }
+ synchronized (mLock) {
+ mPreProcessingAnimations.remove(animationLeash);
+ }
+ return;
+ }
final WindowAnimationSpec animationSpec = a.asWindowAnimationSpec();
final Transaction edgeExtensionCreationTransaction = new Transaction();
@@ -450,8 +462,7 @@
// The leash we are trying to screenshot may have been removed by this point, which is
// likely the reason for ending up with a null edgeBuffer, in which case we just want to
// return and do nothing.
- Log.e("SurfaceAnimationRunner", "Failed to create edge extension - "
- + "edge buffer is null");
+ Log.e(TAG, "Failed to create edge extension - edge buffer is null");
return;
}
diff --git a/tests/Input/src/com/android/test/input/AnrTest.kt b/tests/Input/src/com/android/test/input/AnrTest.kt
index 44da69c..5719273 100644
--- a/tests/Input/src/com/android/test/input/AnrTest.kt
+++ b/tests/Input/src/com/android/test/input/AnrTest.kt
@@ -100,6 +100,7 @@
private fun clickCloseAppOnAnrDialog() {
// Find anr dialog and kill app
+ val timestamp = System.currentTimeMillis()
val uiDevice: UiDevice = UiDevice.getInstance(instrumentation)
val closeAppButton: UiObject2? =
uiDevice.wait(Until.findObject(By.res("android:id/aerr_close")), 20000)
@@ -107,7 +108,6 @@
fail("Could not find anr dialog")
return
}
- val initialReasons = getExitReasons()
closeAppButton.click()
/**
* We must wait for the app to be fully closed before exiting this test. This is because
@@ -116,7 +116,7 @@
* the killing logic will apply to the newly launched 'am start' instance, and the second
* test will fail because the unresponsive activity will never be launched.
*/
- waitForNewExitReason(initialReasons[0].timestamp)
+ waitForNewExitReasonAfter(timestamp)
}
private fun clickWaitOnAnrDialog() {
@@ -140,12 +140,13 @@
return infos
}
- private fun waitForNewExitReason(previousExitTimestamp: Long) {
+ private fun waitForNewExitReasonAfter(timestamp: Long) {
PollingCheck.waitFor {
- getExitReasons()[0].timestamp > previousExitTimestamp
+ val reasons = getExitReasons()
+ !reasons.isEmpty() && reasons[0].timestamp >= timestamp
}
val reasons = getExitReasons()
- assertTrue(reasons[0].timestamp > previousExitTimestamp)
+ assertTrue(reasons[0].timestamp > timestamp)
assertEquals(ApplicationExitInfo.REASON_ANR, reasons[0].reason)
}