Merge "Keep mCanAffectSystemUiFlags to be false while in PiP" into tm-qpr-dev
diff --git a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
index 517e3ce..31c92ba 100644
--- a/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
+++ b/apct-tests/perftests/core/src/android/libcore/ZipFilePerfTest.java
@@ -70,6 +70,9 @@
BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
ZipFile zf = new ZipFile(mFile);
+ state.pauseTiming();
+ zf.close();
+ state.resumeTiming();
}
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 9e9e985..802458b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5894,16 +5894,16 @@
final boolean movedToDifferentDisplay = isDifferentDisplay(activity.getDisplayId(),
displayId);
- final Configuration currentConfig = activity.mCurrentConfig;
- final int diff = currentConfig.diffPublicOnly(newConfig);
- final boolean hasPublicConfigChange = diff != 0;
+ final Configuration currentResConfig = activity.getResources().getConfiguration();
+ final int diff = currentResConfig.diffPublicOnly(newConfig);
+ final boolean hasPublicResConfigChange = diff != 0;
final ActivityClientRecord r = getActivityClient(activityToken);
// TODO(b/173090263): Use diff instead after the improvement of AssetManager and
// ResourcesImpl constructions.
- final boolean shouldUpdateResources = hasPublicConfigChange
- || shouldUpdateResources(activityToken, currentConfig, newConfig, amOverrideConfig,
- movedToDifferentDisplay, hasPublicConfigChange);
- final boolean shouldReportChange = shouldReportChange(diff, currentConfig, newConfig,
+ final boolean shouldUpdateResources = hasPublicResConfigChange
+ || shouldUpdateResources(activityToken, currentResConfig, newConfig,
+ amOverrideConfig, movedToDifferentDisplay, hasPublicResConfigChange);
+ final boolean shouldReportChange = shouldReportChange(activity.mCurrentConfig, newConfig,
r != null ? r.mSizeConfigurations : null,
activity.mActivityInfo.getRealConfigChanged());
// Nothing significant, don't proceed with updating and reporting.
@@ -5927,9 +5927,6 @@
amOverrideConfig, contextThemeWrapperOverrideConfig);
mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig, displayId);
- activity.mConfigChangeFlags = 0;
- activity.mCurrentConfig = new Configuration(newConfig);
-
// Apply the ContextThemeWrapper override if necessary.
// NOTE: Make sure the configurations are not modified, as they are treated as immutable
// in many places.
@@ -5940,8 +5937,10 @@
activity.dispatchMovedToDisplay(displayId, configToReport);
}
+ activity.mConfigChangeFlags = 0;
if (shouldReportChange) {
activity.mCalled = false;
+ activity.mCurrentConfig = new Configuration(newConfig);
activity.onConfigurationChanged(configToReport);
if (!activity.mCalled) {
throw new SuperNotCalledException("Activity " + activity.getLocalClassName() +
@@ -5956,8 +5955,6 @@
* Returns {@code true} if {@link Activity#onConfigurationChanged(Configuration)} should be
* dispatched.
*
- * @param publicDiff Usually computed by {@link Configuration#diffPublicOnly(Configuration)}.
- * This parameter is to prevent we compute it again.
* @param currentConfig The current configuration cached in {@link Activity#mCurrentConfig}.
* It is {@code null} before the first config update from the server side.
* @param newConfig The updated {@link Configuration}
@@ -5966,9 +5963,10 @@
* @return {@code true} if the config change should be reported to the Activity
*/
@VisibleForTesting
- public static boolean shouldReportChange(int publicDiff, @Nullable Configuration currentConfig,
+ public static boolean shouldReportChange(@Nullable Configuration currentConfig,
@NonNull Configuration newConfig, @Nullable SizeConfigurationBuckets sizeBuckets,
int handledConfigChanges) {
+ final int publicDiff = currentConfig.diffPublicOnly(newConfig);
// Don't report the change if there's no public diff between current and new config.
if (publicDiff == 0) {
return false;
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index e98d046..a468951 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -223,6 +223,12 @@
public boolean hasAnimatingParent;
/**
+ * Whether an activity has enabled {@link android.R.styleable#Animation_showBackdrop} for
+ * transition.
+ */
+ public boolean showBackdrop;
+
+ /**
* The background color of animation in case the task info is not available if the transition
* is activity level.
*/
@@ -287,6 +293,11 @@
windowType = in.readInt();
hasAnimatingParent = in.readBoolean();
backgroundColor = in.readInt();
+ showBackdrop = in.readBoolean();
+ }
+
+ public void setShowBackdrop(boolean shouldShowBackdrop) {
+ showBackdrop = shouldShowBackdrop;
}
@Override
@@ -316,6 +327,7 @@
dest.writeInt(windowType);
dest.writeBoolean(hasAnimatingParent);
dest.writeInt(backgroundColor);
+ dest.writeBoolean(showBackdrop);
}
public void dump(PrintWriter pw, String prefix) {
@@ -337,6 +349,7 @@
pw.print(prefix); pw.print("windowType="); pw.print(windowType);
pw.print(prefix); pw.print("hasAnimatingParent="); pw.print(hasAnimatingParent);
pw.print(prefix); pw.print("backgroundColor="); pw.print(backgroundColor);
+ pw.print(prefix); pw.print("showBackdrop="); pw.print(showBackdrop);
}
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6829f3d..98d4c59 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -4503,10 +4503,13 @@
for (Map.Entry<HistoryTag, Integer> entry: mHistoryTagPool.entrySet()) {
entry.setValue(entry.getValue() | TAG_FIRST_OCCURRENCE_FLAG);
}
+ // Make a copy of mHistoryCur.
+ HistoryItem copy = new HistoryItem();
+ copy.setTo(cur);
+ // startRecordingHistory will reset mHistoryCur.
startRecordingHistory(elapsedRealtimeMs, uptimeMs, false);
- HistoryItem newItem = new HistoryItem();
- newItem.setTo(cur);
- addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, newItem);
+ // Add the copy into history buffer.
+ addHistoryBufferLocked(elapsedRealtimeMs, HistoryItem.CMD_UPDATE, copy);
return;
}
diff --git a/core/proto/android/server/windowmanagertransitiontrace.proto b/core/proto/android/server/windowmanagertransitiontrace.proto
index 9429127..4161f65 100644
--- a/core/proto/android/server/windowmanagertransitiontrace.proto
+++ b/core/proto/android/server/windowmanagertransitiontrace.proto
@@ -58,6 +58,8 @@
State state = 5;
int32 flags = 6;
repeated ChangeInfo change = 7;
+ uint64 start_transaction_id = 8;
+ uint64 finish_transaction_id = 9;
}
message ChangeInfo {
diff --git a/core/res/res/anim-ldrtl/task_fragment_clear_top_close_enter.xml b/core/res/res/anim-ldrtl/task_fragment_clear_top_close_enter.xml
new file mode 100644
index 0000000..6c44bdc0
--- /dev/null
+++ b/core/res/res/anim-ldrtl/task_fragment_clear_top_close_enter.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:showBackdrop="true">
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="100"
+ android:duration="350" />
+
+ <translate
+ android:fromXDelta="5%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim-ldrtl/task_fragment_clear_top_close_exit.xml b/core/res/res/anim-ldrtl/task_fragment_clear_top_close_exit.xml
new file mode 100644
index 0000000..65cf2c2c
--- /dev/null
+++ b/core/res/res/anim-ldrtl/task_fragment_clear_top_close_exit.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="0"
+ android:duration="100" />
+
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="-25%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim-ldrtl/task_fragment_clear_top_open_enter.xml b/core/res/res/anim-ldrtl/task_fragment_clear_top_open_enter.xml
new file mode 100644
index 0000000..022bc22
--- /dev/null
+++ b/core/res/res/anim-ldrtl/task_fragment_clear_top_open_enter.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2022 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.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:showBackdrop="true">
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="100"
+ android:duration="350" />
+
+ <translate
+ android:fromXDelta="-5%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:duration="450" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim-ldrtl/task_fragment_clear_top_open_exit.xml b/core/res/res/anim-ldrtl/task_fragment_clear_top_open_exit.xml
new file mode 100644
index 0000000..3644dea
--- /dev/null
+++ b/core/res/res/anim-ldrtl/task_fragment_clear_top_open_exit.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2022 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.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_accelerate"
+ android:startOffset="0"
+ android:duration="100" />
+
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="25%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:duration="450" />
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim-ldrtl/task_fragment_open_enter.xml b/core/res/res/anim-ldrtl/task_fragment_open_enter.xml
index b6f1af3..9e3780a 100644
--- a/core/res/res/anim-ldrtl/task_fragment_open_enter.xml
+++ b/core/res/res/anim-ldrtl/task_fragment_open_enter.xml
@@ -17,7 +17,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
+ android:shareInterpolator="false">
<alpha
android:fromAlpha="0"
diff --git a/core/res/res/anim/task_fragment_clear_top_close_enter.xml b/core/res/res/anim/task_fragment_clear_top_close_enter.xml
new file mode 100644
index 0000000..e33f718
--- /dev/null
+++ b/core/res/res/anim/task_fragment_clear_top_close_enter.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:showBackdrop="true">
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_decelerate"
+ android:startOffset="100"
+ android:duration="350" />
+
+ <translate
+ android:fromXDelta="-5%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_fragment_clear_top_close_exit.xml b/core/res/res/anim/task_fragment_clear_top_close_exit.xml
new file mode 100644
index 0000000..3d274ba9
--- /dev/null
+++ b/core/res/res/anim/task_fragment_clear_top_close_exit.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_accelerate"
+ android:startOffset="0"
+ android:duration="100" />
+
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="25%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_fragment_clear_top_open_enter.xml b/core/res/res/anim/task_fragment_clear_top_open_enter.xml
new file mode 100644
index 0000000..b963661
--- /dev/null
+++ b/core/res/res/anim/task_fragment_clear_top_open_enter.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:showBackdrop="true">
+
+ <alpha
+ android:fromAlpha="0.0"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_decelerate"
+ android:startOffset="100"
+ android:duration="350" />
+
+ <translate
+ android:fromXDelta="5%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:startOffset="0"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_fragment_clear_top_open_exit.xml b/core/res/res/anim/task_fragment_clear_top_open_exit.xml
new file mode 100644
index 0000000..22be7d1
--- /dev/null
+++ b/core/res/res/anim/task_fragment_clear_top_open_exit.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/standard_accelerate"
+ android:startOffset="0"
+ android:duration="100" />
+
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="-25%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_extra_slow_in"
+ android:duration="450" />
+
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_fragment_open_enter.xml b/core/res/res/anim/task_fragment_open_enter.xml
index aa61e6f..87ee179 100644
--- a/core/res/res/anim/task_fragment_open_enter.xml
+++ b/core/res/res/anim/task_fragment_open_enter.xml
@@ -16,7 +16,7 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false">
+ android:shareInterpolator="false">
<alpha
android:fromAlpha="0"
android:toAlpha="1.0"
diff --git a/core/res/res/anim/task_fragment_open_exit.xml b/core/res/res/anim/task_fragment_open_exit.xml
index b4914d2..55a472d 100644
--- a/core/res/res/anim/task_fragment_open_exit.xml
+++ b/core/res/res/anim/task_fragment_open_exit.xml
@@ -32,5 +32,5 @@
android:fillBefore="true"
android:fillAfter="true"
android:interpolator="@interpolator/fast_out_extra_slow_in"
- android:duration="400" />
-</set>
\ No newline at end of file
+ android:duration="400"/>
+</set>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0817102..1438e7f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1706,6 +1706,10 @@
<java-symbol type="anim" name="task_fragment_close_exit" />
<java-symbol type="anim" name="task_fragment_open_enter" />
<java-symbol type="anim" name="task_fragment_open_exit" />
+ <java-symbol type="anim" name="task_fragment_clear_top_close_enter" />
+ <java-symbol type="anim" name="task_fragment_clear_top_close_exit" />
+ <java-symbol type="anim" name="task_fragment_clear_top_open_enter" />
+ <java-symbol type="anim" name="task_fragment_clear_top_open_exit" />
<java-symbol type="array" name="config_autoRotationTiltTolerance" />
<java-symbol type="array" name="config_longPressVibePattern" />
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
index 3858792..dd0e9ff 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsHistoryIteratorTest.java
@@ -154,19 +154,21 @@
for (int i = 0; i < eventCount; i++) {
String name = "a" + (i % 10);
- assertThat(iterator.next(item)).isTrue();
- // Skip a blank event inserted at the start of every buffer
- if (item.eventCode == BatteryStats.HistoryItem.EVENT_NONE) {
+ do {
assertThat(iterator.next(item)).isTrue();
- }
+ // Skip a blank event inserted at the start of every buffer
+ } while (item.cmd != BatteryStats.HistoryItem.CMD_UPDATE
+ || item.eventCode == BatteryStats.HistoryItem.EVENT_NONE);
+
assertThat(item.eventCode).isEqualTo(BatteryStats.HistoryItem.EVENT_ALARM
| BatteryStats.HistoryItem.EVENT_FLAG_START);
assertThat(item.eventTag.string).isEqualTo(name);
- assertThat(iterator.next(item)).isTrue();
- if (item.eventCode == BatteryStats.HistoryItem.EVENT_NONE) {
+ do {
assertThat(iterator.next(item)).isTrue();
- }
+ } while (item.cmd != BatteryStats.HistoryItem.CMD_UPDATE
+ || item.eventCode == BatteryStats.HistoryItem.EVENT_NONE);
+
assertThat(item.eventCode).isEqualTo(BatteryStats.HistoryItem.EVENT_ALARM
| BatteryStats.HistoryItem.EVENT_FLAG_FINISH);
assertThat(item.eventTag.string).isEqualTo(name);
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index 8d3751e..47f70dd 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -207,8 +207,8 @@
final Configuration currentConfig = new Configuration();
assertFalse("Must not report change if no public diff",
- shouldReportChange(0 /* publicDiff */, currentConfig, newConfig,
- null /* sizeBuckets */, 0 /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, null /* sizeBuckets */,
+ 0 /* handledConfigChanges */));
final int[] verticalThresholds = {100, 400};
final SizeConfigurationBuckets buckets = new SizeConfigurationBuckets(
@@ -221,25 +221,25 @@
newConfig.screenHeightDp = 300;
assertFalse("Must not report changes if the diff is small and not handled",
- shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig,
- newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_FONT_SCALE /* handledConfigChanges */));
assertTrue("Must report changes if the small diff is handled",
- shouldReportChange(CONFIG_SCREEN_SIZE /* publicDiff */, currentConfig, newConfig,
- buckets, CONFIG_SCREEN_SIZE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_SCREEN_SIZE /* handledConfigChanges */));
currentConfig.fontScale = 0.8f;
newConfig.fontScale = 1.2f;
assertTrue("Must report handled changes regardless of small unhandled change",
- shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */,
- currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_FONT_SCALE /* handledConfigChanges */));
newConfig.screenHeightDp = 500;
assertFalse("Must not report changes if there's unhandled big changes",
- shouldReportChange(CONFIG_SCREEN_SIZE | CONFIG_FONT_SCALE /* publicDiff */,
- currentConfig, newConfig, buckets, CONFIG_FONT_SCALE /* handledConfigChanges */));
+ shouldReportChange(currentConfig, newConfig, buckets,
+ CONFIG_FONT_SCALE /* handledConfigChanges */));
}
private void recreateAndVerifyNoRelaunch(ActivityThread activityThread, TestActivity activity) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
index 586ac1f..5cc496a 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
@@ -180,9 +180,18 @@
Animation loadOpenAnimation(@NonNull RemoteAnimationTarget target,
@NonNull Rect wholeAnimationBounds) {
final boolean isEnter = target.mode != MODE_CLOSING;
- final Animation animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
- ? com.android.internal.R.anim.task_fragment_open_enter
- : com.android.internal.R.anim.task_fragment_open_exit);
+ final Animation animation;
+ // Background color on TaskDisplayArea has already been set earlier in
+ // WindowContainer#getAnimationAdapter.
+ if (target.showBackdrop) {
+ animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
+ ? com.android.internal.R.anim.task_fragment_clear_top_open_enter
+ : com.android.internal.R.anim.task_fragment_clear_top_open_exit);
+ } else {
+ animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
+ ? com.android.internal.R.anim.task_fragment_open_enter
+ : com.android.internal.R.anim.task_fragment_open_exit);
+ }
animation.initialize(target.localBounds.width(), target.localBounds.height(),
wholeAnimationBounds.width(), wholeAnimationBounds.height());
animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
@@ -192,9 +201,16 @@
Animation loadCloseAnimation(@NonNull RemoteAnimationTarget target,
@NonNull Rect wholeAnimationBounds) {
final boolean isEnter = target.mode != MODE_CLOSING;
- final Animation animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
- ? com.android.internal.R.anim.task_fragment_close_enter
- : com.android.internal.R.anim.task_fragment_close_exit);
+ final Animation animation;
+ if (target.showBackdrop) {
+ animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
+ ? com.android.internal.R.anim.task_fragment_clear_top_close_enter
+ : com.android.internal.R.anim.task_fragment_clear_top_close_exit);
+ } else {
+ animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
+ ? com.android.internal.R.anim.task_fragment_close_enter
+ : com.android.internal.R.anim.task_fragment_close_exit);
+ }
animation.initialize(target.localBounds.width(), target.localBounds.height(),
wholeAnimationBounds.width(), wholeAnimationBounds.height());
animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 1724180..920dcc7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -216,24 +216,24 @@
/** Applies new configuration, returns {@code false} if there's no effect to the layout. */
public boolean updateConfiguration(Configuration configuration) {
- // Always update configuration after orientation changed to make sure to render divider bar
- // with proper resources that matching screen orientation.
- final int orientation = configuration.orientation;
- if (mOrientation != orientation) {
- mContext = mContext.createConfigurationContext(configuration);
- mSplitWindowManager.setConfiguration(configuration);
- mOrientation = orientation;
- }
-
// Update the split bounds when necessary. Besides root bounds changed, split bounds need to
// be updated when the rotation changed to cover the case that users rotated the screen 180
// degrees.
+ // Make sure to render the divider bar with proper resources that matching the screen
+ // orientation.
final int rotation = configuration.windowConfiguration.getRotation();
final Rect rootBounds = configuration.windowConfiguration.getBounds();
- if (mRotation == rotation && mRootBounds.equals(rootBounds)) {
+ final int orientation = configuration.orientation;
+
+ if (mOrientation == orientation
+ && mRotation == rotation
+ && mRootBounds.equals(rootBounds)) {
return false;
}
+ mContext = mContext.createConfigurationContext(configuration);
+ mSplitWindowManager.setConfiguration(configuration);
+ mOrientation = orientation;
mTempRect.set(mRootBounds);
mRootBounds.set(rootBounds);
mRotation = rotation;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
index 9a64b58..ed70ab9 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
@@ -1653,7 +1653,7 @@
modeList.contains(CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF));
checkArrayValuesInRange(key, modes,
CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF,
- CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON);
+ CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION);
return modes;
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
index 3dd4386..f9fc1f3 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayNotificationCountProvider.java
@@ -20,7 +20,6 @@
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
-import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
@@ -33,13 +32,10 @@
import java.util.Set;
import java.util.concurrent.Executor;
-import javax.inject.Inject;
-
/***
* {@link DreamOverlayNotificationCountProvider} provides the current notification count to
* registered callbacks. Ongoing notifications are not included in the count.
*/
-@SysUISingleton
public class DreamOverlayNotificationCountProvider
implements CallbackController<DreamOverlayNotificationCountProvider.Callback> {
private final Set<String> mNotificationKeys = new HashSet<>();
@@ -82,7 +78,6 @@
}
};
- @Inject
public DreamOverlayNotificationCountProvider(
NotificationListener notificationListener,
@Background Executor bgExecutor) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
index e878b22..250313d 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java
@@ -49,6 +49,7 @@
import java.util.Locale;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -65,7 +66,8 @@
private final Resources mResources;
private final DateFormatUtil mDateFormatUtil;
private final IndividualSensorPrivacyController mSensorPrivacyController;
- private final DreamOverlayNotificationCountProvider mDreamOverlayNotificationCountProvider;
+ private final Optional<DreamOverlayNotificationCountProvider>
+ mDreamOverlayNotificationCountProvider;
private final ZenModeController mZenModeController;
private final Executor mMainExecutor;
@@ -125,7 +127,7 @@
NextAlarmController nextAlarmController,
DateFormatUtil dateFormatUtil,
IndividualSensorPrivacyController sensorPrivacyController,
- DreamOverlayNotificationCountProvider dreamOverlayNotificationCountProvider,
+ Optional<DreamOverlayNotificationCountProvider> dreamOverlayNotificationCountProvider,
ZenModeController zenModeController,
StatusBarWindowStateController statusBarWindowStateController) {
super(view);
@@ -161,7 +163,9 @@
mZenModeController.addCallback(mZenModeCallback);
updatePriorityModeStatusIcon();
- mDreamOverlayNotificationCountProvider.addCallback(mNotificationCountCallback);
+ mDreamOverlayNotificationCountProvider.ifPresent(
+ provider -> provider.addCallback(mNotificationCountCallback));
+
mTouchInsetSession.addViewToTracking(mView);
}
@@ -171,7 +175,8 @@
mSensorPrivacyController.removeCallback(mSensorCallback);
mNextAlarmController.removeCallback(mNextAlarmCallback);
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
- mDreamOverlayNotificationCountProvider.removeCallback(mNotificationCountCallback);
+ mDreamOverlayNotificationCountProvider.ifPresent(
+ provider -> provider.removeCallback(mNotificationCountCallback));
mTouchInsetSession.clear();
mIsAttached = false;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index cd23f14..2dd2098 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -20,9 +20,13 @@
import android.content.res.Resources;
import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.DreamOverlayNotificationCountProvider;
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
+import java.util.Optional;
+
import javax.inject.Named;
import dagger.Module;
@@ -50,6 +54,18 @@
return DreamBackend.getInstance(context);
}
+ /**
+ * Provides an instance of a {@link DreamOverlayNotificationCountProvider}.
+ */
+ @SysUISingleton
+ @Provides
+ static Optional<DreamOverlayNotificationCountProvider>
+ providesDreamOverlayNotificationCountProvider() {
+ // If we decide to bring this back, we should gate it on a config that can be changed in
+ // an overlay.
+ return Optional.empty();
+ }
+
/** */
@Provides
@Named(DREAM_ONLY_ENABLED_FOR_SYSTEM_USER)
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index f86541a..47c678b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -45,9 +45,6 @@
/***************************************/
// 100 - notification
- public static final BooleanFlag NEW_NOTIFICATION_PIPELINE_RENDERING =
- new BooleanFlag(101, true);
-
public static final BooleanFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
new BooleanFlag(103, false);
@@ -194,6 +191,8 @@
public static final SysPropBooleanFlag WM_ALWAYS_ENFORCE_PREDICTIVE_BACK =
new SysPropBooleanFlag(1202, "persist.wm.debug.predictive_back_always_enforce", false);
+ public static final BooleanFlag NEW_BACK_AFFORDANCE = new BooleanFlag(1203, true);
+
// Pay no attention to the reflection behind the curtain.
// ========================== Curtain ==========================
// | |
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c5f6b78..d29655a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -486,6 +486,8 @@
*/
private IRemoteAnimationRunner mKeyguardExitAnimationRunner;
+ private CentralSurfaces mCentralSurfaces;
+
private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
new DeviceConfig.OnPropertiesChangedListener() {
@Override
@@ -846,6 +848,13 @@
+ mOccluded);
}
+ @Override
+ public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
+ if (launchIsFullScreen) {
+ mCentralSurfaces.instantCollapseNotificationPanel();
+ }
+ }
+
@NonNull
@Override
public ViewGroup getLaunchContainer() {
@@ -2853,6 +2862,7 @@
@Nullable PanelExpansionStateManager panelExpansionStateManager,
BiometricUnlockController biometricUnlockController,
View notificationContainer, KeyguardBypassController bypassController) {
+ mCentralSurfaces = centralSurfaces;
mKeyguardViewControllerLazy.get().registerCentralSurfaces(
centralSurfaces,
panelView,
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 05da4bb..90cca15 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -52,7 +52,7 @@
return factory.create("NotifLog", 1000 /* maxSize */, false /* systrace */);
}
- /** Provides a logging buffer for all logs related to the data layer of notifications. */
+ /** Provides a logging buffer for logs related to heads up presentation of notifications. */
@Provides
@SysUISingleton
@NotificationHeadsUpLog
@@ -60,6 +60,14 @@
return factory.create("NotifHeadsUpLog", 1000);
}
+ /** Provides a logging buffer for notification interruption calculations. */
+ @Provides
+ @SysUISingleton
+ @NotificationInterruptLog
+ public static LogBuffer provideNotificationInterruptLogBuffer(LogBufferFactory factory) {
+ return factory.create("NotifInterruptLog", 100);
+ }
+
/** Provides a logging buffer for all logs for lockscreen to shade transition events. */
@Provides
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
new file mode 100644
index 0000000..760fbf3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 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.log.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import com.android.systemui.log.LogBuffer;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Qualifier;
+
+/** A {@link LogBuffer} for notification interruption logging. */
+@Qualifier
+@Documented
+@Retention(RUNTIME)
+public @interface NotificationInterruptLog {
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index b2ab12a..5b2cda0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -219,4 +219,21 @@
/** Whether or not to show the broadcast button */
val showBroadcastButton: Boolean
-)
+) {
+ /**
+ * Check whether [MediaDeviceData] objects are equal in all fields except the icon. The icon
+ * is ignored because it can change by reference frequently depending on the device type's
+ * implementation, but this is not usually relevant unless other info has changed
+ */
+ fun equalsWithoutIcon(other: MediaDeviceData?): Boolean {
+ if (other == null) {
+ return false
+ }
+
+ return enabled == other.enabled &&
+ name == other.name &&
+ intent == other.intent &&
+ id == other.id &&
+ showBroadcastButton == other.showBroadcastButton
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index b552d9f..8305050 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -168,8 +168,8 @@
private var playbackType = PLAYBACK_TYPE_UNKNOWN
private var current: MediaDeviceData? = null
set(value) {
- val hasSameId = value?.id != null && value.id == field?.id
- if (!started || (!hasSameId && value != field)) {
+ val sameWithoutIcon = value != null && value.equalsWithoutIcon(field)
+ if (!started || !sameWithoutIcon) {
field = value
fgExecutor.execute {
processDevice(key, oldKey, value)
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index d41837b..e210d68 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -234,7 +234,7 @@
private boolean mIsBackGestureAllowed;
private boolean mGestureBlockingActivityRunning;
private boolean mIsInPipMode;
- private boolean mIsPredictiveBackAnimEnabled;
+ private boolean mIsNewBackAffordanceEnabled;
private InputMonitor mInputMonitor;
private InputChannelCompat.InputEventReceiver mInputEventReceiver;
@@ -524,8 +524,7 @@
Choreographer.getInstance(), this::onInputEvent);
// Add a nav bar panel window
- mIsPredictiveBackAnimEnabled =
- mFeatureFlags.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_ANIM);
+ mIsNewBackAffordanceEnabled = mFeatureFlags.isEnabled(Flags.NEW_BACK_AFFORDANCE);
resetEdgeBackPlugin();
mPluginManager.addPluginListener(
this, NavigationEdgeBackPlugin.class, /*allowMultiple=*/ false);
@@ -545,7 +544,7 @@
}
private void resetEdgeBackPlugin() {
- if (mIsPredictiveBackAnimEnabled) {
+ if (mIsNewBackAffordanceEnabled) {
setEdgeBackPlugin(
mBackPanelControllerFactory.create(mContext, mBackAnimation));
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
index f6a55e6..478f7aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -48,8 +48,7 @@
fun assertLegacyPipelineEnabled(): Unit =
check(!isNewPipelineEnabled()) { "Old pipeline code running w/ new pipeline enabled" }
- fun isNewPipelineEnabled(): Boolean =
- featureFlags.isEnabled(Flags.NEW_NOTIFICATION_PIPELINE_RENDERING)
+ fun isNewPipelineEnabled(): Boolean = true
fun isDevLoggingEnabled(): Boolean =
featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
index e98ae8d..792ff8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListDumper.java
@@ -115,6 +115,7 @@
) {
sb.append(indent)
.append("[").append(index).append("] ")
+ .append(index.length() == 1 ? " " : "")
.append(entry.getKey());
if (includeParent) {
@@ -192,7 +193,7 @@
if (notifEntry.getAttachState().getSuppressedChanges().getSection() != null) {
rksb.append("suppressedSection=")
.append(notifEntry.getAttachState().getSuppressedChanges()
- .getSection())
+ .getSection().getLabel())
.append(" ");
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 410593a..ecce1ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -104,6 +104,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -829,11 +830,9 @@
@Override
public void dump(PrintWriter pw, @NonNull String[] args) {
final List<NotificationEntry> entries = new ArrayList<>(getAllNotifs());
+ entries.sort(Comparator.comparing(NotificationEntry::getKey));
- pw.println("\t" + TAG + " unsorted/unfiltered notifications:");
- if (entries.size() == 0) {
- pw.println("\t\t None");
- }
+ pw.println("\t" + TAG + " unsorted/unfiltered notifications: " + entries.size());
pw.println(
ListDumper.dumpList(
entries,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
index 6c99e3a..1d18ca3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
@@ -20,16 +20,14 @@
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.LogLevel.INFO
-import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.log.dagger.NotificationInterruptLog
import javax.inject.Inject
class NotificationInterruptLogger @Inject constructor(
- @NotificationLog val notifBuffer: LogBuffer,
- @NotificationHeadsUpLog val hunBuffer: LogBuffer
+ @NotificationInterruptLog val buffer: LogBuffer
) {
fun logHeadsUpFeatureChanged(useHeadsUp: Boolean) {
- hunBuffer.log(TAG, INFO, {
+ buffer.log(TAG, INFO, {
bool1 = useHeadsUp
}, {
"heads up is enabled=$bool1"
@@ -37,14 +35,14 @@
}
fun logWillDismissAll() {
- hunBuffer.log(TAG, INFO, {
+ buffer.log(TAG, INFO, {
}, {
"dismissing any existing heads up notification on disable event"
})
}
fun logNoBubbleNotAllowed(sbn: StatusBarNotification) {
- notifBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No bubble up: not allowed to bubble: $str1"
@@ -52,7 +50,7 @@
}
fun logNoBubbleNoMetadata(sbn: StatusBarNotification) {
- notifBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No bubble up: notification: $str1 doesn't have valid metadata"
@@ -60,14 +58,14 @@
}
fun logNoHeadsUpFeatureDisabled() {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
}, {
"No heads up: no huns"
})
}
fun logNoHeadsUpPackageSnoozed(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: snoozed package: $str1"
@@ -75,7 +73,7 @@
}
fun logNoHeadsUpAlreadyBubbled(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: in unlocked shade where notification is shown as a bubble: $str1"
@@ -83,7 +81,7 @@
}
fun logNoHeadsUpSuppressedByDnd(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: suppressed by DND: $str1"
@@ -91,7 +89,7 @@
}
fun logNoHeadsUpNotImportant(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: unimportant notification: $str1"
@@ -99,7 +97,7 @@
}
fun logNoHeadsUpNotInUse(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No heads up: not in use: $str1"
@@ -110,7 +108,7 @@
sbn: StatusBarNotification,
suppressor: NotificationInterruptSuppressor
) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
str2 = suppressor.name
}, {
@@ -119,7 +117,7 @@
}
fun logHeadsUp(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"Heads up: $str1"
@@ -127,7 +125,7 @@
}
fun logNoAlertingFilteredOut(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: filtered notification: $str1"
@@ -135,7 +133,7 @@
}
fun logNoAlertingGroupAlertBehavior(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: suppressed due to group alert behavior: $str1"
@@ -147,7 +145,7 @@
suppressor: NotificationInterruptSuppressor,
awake: Boolean
) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
str2 = suppressor.name
bool1 = awake
@@ -157,7 +155,7 @@
}
fun logNoAlertingRecentFullscreen(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No alerting: recent fullscreen: $str1"
@@ -165,7 +163,7 @@
}
fun logNoPulsingSettingDisabled(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: disabled by setting: $str1"
@@ -173,7 +171,7 @@
}
fun logNoPulsingBatteryDisabled(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: disabled by battery saver: $str1"
@@ -181,7 +179,7 @@
}
fun logNoPulsingNoAlert(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: notification shouldn't alert: $str1"
@@ -189,7 +187,7 @@
}
fun logNoPulsingNoAmbientEffect(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: ambient effect suppressed: $str1"
@@ -197,7 +195,7 @@
}
fun logNoPulsingNotImportant(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"No pulsing: not important enough: $str1"
@@ -205,7 +203,7 @@
}
fun logPulsing(sbn: StatusBarNotification) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = sbn.key
}, {
"Pulsing: $str1"
@@ -213,7 +211,7 @@
}
fun keyguardHideNotification(key: String) {
- hunBuffer.log(TAG, DEBUG, {
+ buffer.log(TAG, DEBUG, {
str1 = key
}, {
"Keyguard Hide Notification: $str1"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index b785435..cd4a44e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -141,7 +141,7 @@
public static final float DEFAULT_HEADER_VISIBLE_AMOUNT = 1.0f;
private static final long RECENTLY_ALERTED_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(30);
- private boolean mUpdateBackgroundOnUpdate;
+ private boolean mUpdateSelfBackgroundOnUpdate;
private boolean mNotificationTranslationFinished = false;
private boolean mIsSnoozed;
private boolean mIsFaded;
@@ -553,9 +553,28 @@
updateLimits();
updateShelfIconColor();
updateRippleAllowed();
- if (mUpdateBackgroundOnUpdate) {
- mUpdateBackgroundOnUpdate = false;
- updateBackgroundColors();
+ if (mUpdateSelfBackgroundOnUpdate) {
+ // Because this is triggered by UiMode change which we already propagated to children,
+ // we know that child rows will receive the same event, and will update their own
+ // backgrounds when they finish inflating, so propagating again would be redundant.
+ mUpdateSelfBackgroundOnUpdate = false;
+ updateBackgroundColorsOfSelf();
+ }
+ }
+
+ private void updateBackgroundColorsOfSelf() {
+ super.updateBackgroundColors();
+ }
+
+ @Override
+ public void updateBackgroundColors() {
+ // Because this call is made by the NSSL only on attached rows at the moment of the
+ // UiMode or Theme change, we have to propagate to our child views.
+ updateBackgroundColorsOfSelf();
+ if (mIsSummaryWithChildren) {
+ for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) {
+ child.updateBackgroundColors();
+ }
}
}
@@ -1242,7 +1261,7 @@
}
public void onUiModeChanged() {
- mUpdateBackgroundOnUpdate = true;
+ mUpdateSelfBackgroundOnUpdate = true;
reInflateViews();
if (mChildrenContainer != null) {
for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 8c61764..5181af7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -1597,7 +1597,7 @@
}
}
});
- mStatusBarKeyguardViewManager.registerCentralSurfaces(
+ mKeyguardViewMediator.registerCentralSurfaces(
/* statusBar= */ this,
mNotificationPanelViewController,
mPanelExpansionStateManager,
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
index 313d56f..4e9030f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/condition/Monitor.java
@@ -16,17 +16,17 @@
package com.android.systemui.util.condition;
+import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.statusbar.policy.CallbackController;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
@@ -37,149 +37,120 @@
* {@link Monitor} takes in a set of conditions, monitors whether all of them have
* been fulfilled, and informs any registered listeners.
*/
-public class Monitor implements CallbackController<Monitor.Callback> {
+public class Monitor {
private final String mTag = getClass().getSimpleName();
-
- private final ArrayList<Callback> mCallbacks = new ArrayList<>();
-
- // Set of all conditions that need to be monitored.
- private final Set<Condition> mConditions;
private final Executor mExecutor;
- // Whether all conditions have been met.
- private boolean mAllConditionsMet = false;
+ private final HashMap<Condition, ArraySet<Subscription.Token>> mConditions = new HashMap<>();
+ private final HashMap<Subscription.Token, SubscriptionState> mSubscriptions = new HashMap<>();
- // Whether the monitor has started listening for all the conditions.
- private boolean mHaveConditionsStarted = false;
+ private static class SubscriptionState {
+ private final Subscription mSubscription;
+ private Boolean mAllConditionsMet;
+
+ SubscriptionState(Subscription subscription) {
+ mSubscription = subscription;
+ }
+
+ public Set<Condition> getConditions() {
+ return mSubscription.mConditions;
+ }
+
+ public void update() {
+ // Overriding conditions do not override each other
+ final Collection<Condition> overridingConditions = mSubscription.mConditions.stream()
+ .filter(Condition::isOverridingCondition).collect(Collectors.toSet());
+
+ final Collection<Condition> targetCollection = overridingConditions.isEmpty()
+ ? mSubscription.mConditions : overridingConditions;
+
+ final boolean newAllConditionsMet = targetCollection.isEmpty() ? true : targetCollection
+ .stream()
+ .map(Condition::isConditionMet)
+ .allMatch(conditionMet -> conditionMet);
+
+ if (mAllConditionsMet != null && newAllConditionsMet == mAllConditionsMet) {
+ return;
+ }
+
+ mAllConditionsMet = newAllConditionsMet;
+ mSubscription.mCallback.onConditionsChanged(mAllConditionsMet);
+ }
+ }
// Callback for when each condition has been updated.
private final Condition.Callback mConditionCallback = new Condition.Callback() {
@Override
public void onConditionChanged(Condition condition) {
- mExecutor.execute(() -> updateConditionMetState());
+ mExecutor.execute(() -> updateConditionMetState(condition));
}
};
@Inject
- public Monitor(@Main Executor executor, Set<Condition> conditions) {
- mConditions = new HashSet<>();
+ public Monitor(@Main Executor executor) {
mExecutor = executor;
-
- if (conditions != null) {
- mConditions.addAll(conditions);
- }
}
- private void updateConditionMetState() {
- // Overriding conditions do not override each other
- final Collection<Condition> overridingConditions = mConditions.stream()
- .filter(Condition::isOverridingCondition).collect(Collectors.toSet());
-
- final Collection<Condition> targetCollection = overridingConditions.isEmpty()
- ? mConditions : overridingConditions;
-
- final boolean newAllConditionsMet = targetCollection.isEmpty() ? true : targetCollection
- .stream()
- .map(Condition::isConditionMet)
- .allMatch(conditionMet -> conditionMet);
-
- if (newAllConditionsMet == mAllConditionsMet) {
- return;
- }
-
- if (shouldLog()) Log.d(mTag, "all conditions met: " + newAllConditionsMet);
- mAllConditionsMet = newAllConditionsMet;
-
- // Updates all callbacks.
- final Iterator<Callback> iterator = mCallbacks.iterator();
- while (iterator.hasNext()) {
- final Callback callback = iterator.next();
- if (callback == null) {
- iterator.remove();
- } else {
- callback.onConditionsChanged(mAllConditionsMet);
- }
- }
- }
-
- private void addConditionLocked(@NotNull Condition condition) {
- mConditions.add(condition);
-
- if (!mHaveConditionsStarted) {
- return;
- }
-
- condition.addCallback(mConditionCallback);
- updateConditionMetState();
+ private void updateConditionMetState(Condition condition) {
+ mConditions.get(condition).stream().forEach(token -> mSubscriptions.get(token).update());
}
/**
- * Adds a condition for the monitor to listen to and consider when determining whether the
- * overall condition state is met.
+ * Registers a callback and the set of conditions to trigger it.
+ * @param subscription A {@link Subscription} detailing the desired conditions and callback.
+ * @return A {@link Subscription.Token} that can be used to remove the subscription.
*/
- public void addCondition(@NotNull Condition condition) {
- mExecutor.execute(() -> addConditionLocked(condition));
- }
+ public Subscription.Token addSubscription(@NotNull Subscription subscription) {
+ final Subscription.Token token = new Subscription.Token();
+ final SubscriptionState state = new SubscriptionState(subscription);
- /**
- * Removes a condition from further consideration.
- */
- public void removeCondition(@NotNull Condition condition) {
mExecutor.execute(() -> {
- mConditions.remove(condition);
+ mSubscriptions.put(token, state);
- if (!mHaveConditionsStarted) {
+ // Add and associate conditions.
+ subscription.getConditions().stream().forEach(condition -> {
+ if (!mConditions.containsKey(condition)) {
+ mConditions.put(condition, new ArraySet<>());
+ condition.addCallback(mConditionCallback);
+ }
+
+ mConditions.get(condition).add(token);
+ });
+
+ // Update subscription state.
+ state.update();
+
+ });
+ return token;
+ }
+
+ /**
+ * Removes a subscription from participating in future callbacks.
+ * @param token The {@link Subscription.Token} returned when the {@link Subscription} was
+ * originally added.
+ */
+ public void removeSubscription(@NotNull Subscription.Token token) {
+ mExecutor.execute(() -> {
+ if (shouldLog()) Log.d(mTag, "removing callback");
+ if (!mSubscriptions.containsKey(token)) {
+ Log.e(mTag, "subscription not present:" + token);
return;
}
- condition.removeCallback(mConditionCallback);
- updateConditionMetState();
- });
- }
+ mSubscriptions.remove(token).getConditions().forEach(condition -> {
+ if (!mConditions.containsKey(condition)) {
+ Log.e(mTag, "condition not present:" + condition);
+ return;
- private void addCallbackLocked(@NotNull Callback callback) {
- if (mCallbacks.contains(callback)) {
- return;
- }
-
- if (shouldLog()) Log.d(mTag, "adding callback");
- mCallbacks.add(callback);
-
- // Updates the callback immediately.
- callback.onConditionsChanged(mAllConditionsMet);
-
- if (!mHaveConditionsStarted) {
- if (shouldLog()) Log.d(mTag, "starting all conditions");
- mConditions.forEach(condition -> condition.addCallback(mConditionCallback));
- updateConditionMetState();
- mHaveConditionsStarted = true;
- }
- }
-
- @Override
- public void addCallback(@NotNull Callback callback) {
- mExecutor.execute(() -> addCallbackLocked(callback));
- }
-
- @Override
- public void removeCallback(@NotNull Callback callback) {
- mExecutor.execute(() -> {
- if (shouldLog()) Log.d(mTag, "removing callback");
- final Iterator<Callback> iterator = mCallbacks.iterator();
- while (iterator.hasNext()) {
- final Callback cb = iterator.next();
- if (cb == null || cb == callback) {
- iterator.remove();
}
- }
+ final Set<Subscription.Token> conditionSubscriptions = mConditions.get(condition);
- if (mCallbacks.isEmpty() && mHaveConditionsStarted) {
- if (shouldLog()) Log.d(mTag, "stopping all conditions");
- mConditions.forEach(condition -> condition.removeCallback(mConditionCallback));
-
- mAllConditionsMet = false;
- mHaveConditionsStarted = false;
- }
+ conditionSubscriptions.remove(token);
+ if (conditionSubscriptions.isEmpty()) {
+ condition.removeCallback(mConditionCallback);
+ mConditions.remove(condition);
+ }
+ });
});
}
@@ -188,10 +159,92 @@
}
/**
+ * A {@link Subscription} represents a set of conditions and a callback that is informed when
+ * these conditions change.
+ */
+ public static class Subscription {
+ private final Set<Condition> mConditions;
+ private final Callback mCallback;
+
+ /** */
+ public Subscription(Set<Condition> conditions, Callback callback) {
+ this.mConditions = Collections.unmodifiableSet(conditions);
+ this.mCallback = callback;
+ }
+
+ public Set<Condition> getConditions() {
+ return mConditions;
+ }
+
+ public Callback getCallback() {
+ return mCallback;
+ }
+
+ /**
+ * A {@link Token} is an identifier that is associated with a {@link Subscription} which is
+ * registered with a {@link Monitor}.
+ */
+ public static class Token {
+ }
+
+ /**
+ * {@link Builder} is a helper class for constructing a {@link Subscription}.
+ */
+ public static class Builder {
+ private final Callback mCallback;
+ private final ArraySet<Condition> mConditions;
+
+ /**
+ * Default constructor specifying the {@link Callback} for the {@link Subscription}.
+ * @param callback
+ */
+ public Builder(Callback callback) {
+ mCallback = callback;
+ mConditions = new ArraySet<>();
+ }
+
+ /**
+ * Adds a {@link Condition} to be associated with the {@link Subscription}.
+ * @param condition
+ * @return The updated {@link Builder}.
+ */
+ public Builder addCondition(Condition condition) {
+ mConditions.add(condition);
+ return this;
+ }
+
+ /**
+ * Adds a set of {@link Condition} to be associated with the {@link Subscription}.
+ * @param condition
+ * @return The updated {@link Builder}.
+ */
+ public Builder addConditions(Set<Condition> condition) {
+ mConditions.addAll(condition);
+ return this;
+ }
+
+ /**
+ * Builds the {@link Subscription}.
+ * @return The resulting {@link Subscription}.
+ */
+ public Subscription build() {
+ return new Subscription(mConditions, mCallback);
+ }
+ }
+ }
+
+ /**
* Callback that receives updates of whether all conditions have been fulfilled.
*/
public interface Callback {
/**
+ * Returns the conditions associated with this callback.
+ */
+ default ArrayList<Condition> getConditions() {
+ return new ArrayList<>();
+ }
+
+ /**
* Triggered when the fulfillment of all conditions have been met.
*
* @param allConditionsMet True if all conditions have been fulfilled. False if none or
diff --git a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java b/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java
deleted file mode 100644
index 8e739d6..0000000
--- a/packages/SystemUI/src/com/android/systemui/util/condition/dagger/MonitorComponent.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2021 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.util.condition.dagger;
-
-import com.android.systemui.util.condition.Condition;
-import com.android.systemui.util.condition.Monitor;
-
-import java.util.Set;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * Component for {@link Monitor}.
- */
-@Subcomponent
-public interface MonitorComponent {
- /**
- * Factory for {@link MonitorComponent}.
- */
- @Subcomponent.Factory
- interface Factory {
- MonitorComponent create(@BindsInstance Set<Condition> conditions);
- }
-
- /**
- * Provides {@link Monitor}.
- * @return
- */
- Monitor getMonitor();
-}
diff --git a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
index 7892d6e..981bf01 100644
--- a/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/dagger/UtilModule.java
@@ -18,7 +18,6 @@
import com.android.systemui.util.RingerModeTracker;
import com.android.systemui.util.RingerModeTrackerImpl;
-import com.android.systemui.util.condition.dagger.MonitorComponent;
import com.android.systemui.util.wrapper.UtilWrapperModule;
import dagger.Binds;
@@ -27,9 +26,6 @@
/** Dagger Module for code in the util package. */
@Module(includes = {
UtilWrapperModule.class
- },
- subcomponents = {
- MonitorComponent.class,
})
public interface UtilModule {
/** */
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
index 3c28d48..d334694 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java
@@ -57,6 +57,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.Optional;
import java.util.concurrent.Executor;
@SmallTest
@@ -115,7 +116,7 @@
mNextAlarmController,
mDateFormatUtil,
mSensorPrivacyController,
- mDreamOverlayNotificationCountProvider,
+ Optional.of(mDreamOverlayNotificationCountProvider),
mZenModeController,
mStatusBarWindowStateController);
}
@@ -231,6 +232,26 @@
}
@Test
+ public void testNotificationsIconNotShownWhenCountProviderAbsent() {
+ DreamOverlayStatusBarViewController controller = new DreamOverlayStatusBarViewController(
+ mView,
+ mResources,
+ mMainExecutor,
+ mConnectivityManager,
+ mTouchSession,
+ mAlarmManager,
+ mNextAlarmController,
+ mDateFormatUtil,
+ mSensorPrivacyController,
+ Optional.empty(),
+ mZenModeController,
+ mStatusBarWindowStateController);
+ controller.onViewAttached();
+ verify(mView, never()).showIcon(
+ eq(DreamOverlayStatusBarView.STATUS_ICON_NOTIFICATIONS), eq(true), any());
+ }
+
+ @Test
public void testOnViewAttachedShowsPriorityModeIconWhenEnabled() {
when(mZenModeController.getZen()).thenReturn(
Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index 11fe87d..ee10426 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -56,7 +56,9 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
@@ -64,6 +66,7 @@
private const val KEY_OLD = "TEST_KEY_OLD"
private const val PACKAGE = "PKG"
private const val SESSION_KEY = "SESSION_KEY"
+private const val DEVICE_ID = "DEVICE_ID"
private const val DEVICE_NAME = "DEVICE_NAME"
private const val REMOTE_DEVICE_NAME = "REMOTE_DEVICE_NAME"
private const val BROADCAST_APP_NAME = "BROADCAST_APP_NAME"
@@ -478,6 +481,89 @@
}
@Test
+ fun deviceIdChanged_informListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ // and later the manager gets a new device ID
+ val deviceCallback = captureCallback()
+ val updatedId = DEVICE_ID + "_new"
+ whenever(device.id).thenReturn(updatedId)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener gets the updated info
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ val firstDevice = dataCaptor.allValues.get(0)
+ assertThat(firstDevice.id).isEqualTo(DEVICE_ID)
+
+ val secondDevice = dataCaptor.allValues.get(1)
+ assertThat(secondDevice.id).isEqualTo(updatedId)
+ }
+
+ @Test
+ fun deviceNameChanged_informListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ whenever(device.name).thenReturn(DEVICE_NAME)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ // and later the manager gets a new device name
+ val deviceCallback = captureCallback()
+ val updatedName = DEVICE_NAME + "_new"
+ whenever(device.name).thenReturn(updatedName)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener gets the updated info
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener, times(2)).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ val firstDevice = dataCaptor.allValues.get(0)
+ assertThat(firstDevice.name).isEqualTo(DEVICE_NAME)
+
+ val secondDevice = dataCaptor.allValues.get(1)
+ assertThat(secondDevice.name).isEqualTo(updatedName)
+ }
+
+ @Test
+ fun deviceIconChanged_doesNotCallListener() {
+ // GIVEN a notification is added, with a particular device connected
+ whenever(device.id).thenReturn(DEVICE_ID)
+ whenever(device.name).thenReturn(DEVICE_NAME)
+ val firstIcon = mock(Drawable::class.java)
+ whenever(device.icon).thenReturn(firstIcon)
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+
+ val dataCaptor = ArgumentCaptor.forClass(MediaDeviceData::class.java)
+ verify(listener).onMediaDeviceChanged(eq(KEY), any(), dataCaptor.capture())
+
+ // and later the manager gets a callback with only the icon changed
+ val deviceCallback = captureCallback()
+ val secondIcon = mock(Drawable::class.java)
+ whenever(device.icon).thenReturn(secondIcon)
+ deviceCallback.onDeviceListUpdate(mutableListOf(device))
+
+ // THEN the listener is not called again
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ verifyNoMoreInteractions(listener)
+ }
+
+ @Test
fun testRemotePlaybackDeviceOverride() {
whenever(route.name).thenReturn(DEVICE_NAME)
val deviceData = MediaDeviceData(false, null, REMOTE_DEVICE_NAME, null,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index b1bf971..f8b39e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -43,6 +43,7 @@
import android.app.Notification;
import android.app.NotificationChannel;
+import android.graphics.Color;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -110,6 +111,28 @@
}
@Test
+ public void testUpdateBackgroundColors_isRecursive() {
+ mGroupRow.setTintColor(Color.RED);
+ mGroupRow.getChildNotificationAt(0).setTintColor(Color.GREEN);
+ mGroupRow.getChildNotificationAt(1).setTintColor(Color.BLUE);
+
+ assertThat(mGroupRow.getCurrentBackgroundTint()).isEqualTo(Color.RED);
+ assertThat(mGroupRow.getChildNotificationAt(0).getCurrentBackgroundTint())
+ .isEqualTo(Color.GREEN);
+ assertThat(mGroupRow.getChildNotificationAt(1).getCurrentBackgroundTint())
+ .isEqualTo(Color.BLUE);
+
+ mGroupRow.updateBackgroundColors();
+
+ int resetTint = mGroupRow.getCurrentBackgroundTint();
+ assertThat(resetTint).isNotEqualTo(Color.RED);
+ assertThat(mGroupRow.getChildNotificationAt(0).getCurrentBackgroundTint())
+ .isEqualTo(resetTint);
+ assertThat(mGroupRow.getChildNotificationAt(1).getCurrentBackgroundTint())
+ .isEqualTo(resetTint);
+ }
+
+ @Test
public void testSetSensitiveOnNotifRowNotifiesOfHeightChange() throws InterruptedException {
// GIVEN a sensitive notification row that's currently redacted
measureAndLayout(mNotifRow);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
index 7589616..1e35b0f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/condition/ConditionMonitorTest.java
@@ -65,7 +65,12 @@
mCondition3 = spy(new FakeCondition());
mConditions = new HashSet<>(Arrays.asList(mCondition1, mCondition2, mCondition3));
- mConditionMonitor = new Monitor(mExecutor, mConditions);
+ mConditionMonitor = new Monitor(mExecutor);
+ }
+
+ public Monitor.Subscription.Builder getDefaultBuilder(Monitor.Callback callback) {
+ return new Monitor.Subscription.Builder(callback)
+ .addConditions(mConditions);
}
@Test
@@ -74,11 +79,19 @@
final Condition regularCondition = Mockito.mock(Condition.class);
final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
- final Monitor monitor = new Monitor(
- mExecutor,
- new HashSet<>(Arrays.asList(overridingCondition, regularCondition)));
+ final Monitor.Callback referenceCallback = Mockito.mock(Monitor.Callback.class);
- monitor.addCallback(callback);
+ final Monitor monitor = new Monitor(mExecutor);
+
+ monitor.addSubscription(getDefaultBuilder(callback)
+ .addCondition(overridingCondition)
+ .addCondition(regularCondition)
+ .build());
+
+ monitor.addSubscription(getDefaultBuilder(referenceCallback)
+ .addCondition(regularCondition)
+ .build());
+
mExecutor.runAllReady();
when(overridingCondition.isOverridingCondition()).thenReturn(true);
@@ -94,7 +107,9 @@
mExecutor.runAllReady();
verify(callback).onConditionsChanged(eq(true));
+ verify(referenceCallback).onConditionsChanged(eq(false));
Mockito.clearInvocations(callback);
+ Mockito.clearInvocations(referenceCallback);
when(regularCondition.isConditionMet()).thenReturn(true);
when(overridingCondition.isConditionMet()).thenReturn(false);
@@ -103,12 +118,7 @@
mExecutor.runAllReady();
verify(callback).onConditionsChanged(eq(false));
-
- clearInvocations(callback);
- monitor.removeCondition(overridingCondition);
- mExecutor.runAllReady();
-
- verify(callback).onConditionsChanged(eq(true));
+ verify(referenceCallback, never()).onConditionsChanged(anyBoolean());
}
/**
@@ -122,11 +132,13 @@
final Condition regularCondition = Mockito.mock(Condition.class);
final Monitor.Callback callback = Mockito.mock(Monitor.Callback.class);
- final Monitor monitor = new Monitor(
- mExecutor,
- new HashSet<>(Arrays.asList(overridingCondition, overridingCondition2,
- regularCondition)));
- monitor.addCallback(callback);
+ final Monitor monitor = new Monitor(mExecutor);
+
+ monitor.addSubscription(getDefaultBuilder(callback)
+ .addCondition(overridingCondition)
+ .addCondition(overridingCondition2)
+ .build());
+
mExecutor.runAllReady();
when(overridingCondition.isOverridingCondition()).thenReturn(true);
@@ -151,13 +163,13 @@
public void addCallback_addFirstCallback_addCallbackToAllConditions() {
final Monitor.Callback callback1 =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback1);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback1).build());
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition).addCallback(any()));
final Monitor.Callback callback2 =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback2);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback2).build());
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition, times(1)).addCallback(any()));
}
@@ -166,7 +178,7 @@
public void addCallback_addFirstCallback_reportWithDefaultValue() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
}
@@ -177,66 +189,65 @@
mock(Monitor.Callback.class);
final Condition condition = mock(Condition.class);
when(condition.isConditionMet()).thenReturn(true);
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition)));
- monitor.addCallback(callback1);
+ final Monitor monitor = new Monitor(mExecutor);
+ monitor.addSubscription(new Monitor.Subscription.Builder(callback1)
+ .addCondition(condition)
+ .build());
final Monitor.Callback callback2 =
mock(Monitor.Callback.class);
- monitor.addCallback(callback2);
+ monitor.addSubscription(new Monitor.Subscription.Builder(callback2)
+ .addCondition(condition)
+ .build());
mExecutor.runAllReady();
verify(callback2).onConditionsChanged(eq(true));
}
@Test
public void addCallback_noConditions_reportAllConditionsMet() {
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>());
+ final Monitor monitor = new Monitor(mExecutor);
final Monitor.Callback callback = mock(Monitor.Callback.class);
- monitor.addCallback(callback);
+ monitor.addSubscription(new Monitor.Subscription.Builder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(true);
}
@Test
- public void addCallback_withMultipleInstancesOfTheSameCallback_registerOnlyOne() {
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>());
- final Monitor.Callback callback = mock(Monitor.Callback.class);
-
- // Adds the same instance multiple times.
- monitor.addCallback(callback);
- monitor.addCallback(callback);
- monitor.addCallback(callback);
+ public void removeCallback_noFailureOnDoubleRemove() {
+ final Condition condition = mock(Condition.class);
+ final Monitor monitor = new Monitor(mExecutor);
+ final Monitor.Callback callback =
+ mock(Monitor.Callback.class);
+ final Monitor.Subscription.Token token = monitor.addSubscription(
+ new Monitor.Subscription.Builder(callback).addCondition(condition).build()
+ );
+ monitor.removeSubscription(token);
mExecutor.runAllReady();
-
- // Callback should only be triggered once.
- verify(callback, times(1)).onConditionsChanged(true);
+ // Ensure second removal doesn't cause an exception.
+ monitor.removeSubscription(token);
+ mExecutor.runAllReady();
}
@Test
public void removeCallback_shouldNoLongerReceiveUpdate() {
final Condition condition = mock(Condition.class);
- final Monitor monitor = new Monitor(mExecutor, new HashSet<>(Arrays.asList(condition)));
+ final Monitor monitor = new Monitor(mExecutor);
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- monitor.addCallback(callback);
- monitor.removeCallback(callback);
+ final Monitor.Subscription.Token token = monitor.addSubscription(
+ new Monitor.Subscription.Builder(callback).addCondition(condition).build()
+ );
+ monitor.removeSubscription(token);
mExecutor.runAllReady();
clearInvocations(callback);
final ArgumentCaptor<Condition.Callback> conditionCallbackCaptor =
ArgumentCaptor.forClass(Condition.Callback.class);
verify(condition).addCallback(conditionCallbackCaptor.capture());
+
final Condition.Callback conditionCallback = conditionCallbackCaptor.getValue();
-
- when(condition.isConditionMet()).thenReturn(true);
- conditionCallback.onConditionChanged(condition);
- mExecutor.runAllReady();
- verify(callback, never()).onConditionsChanged(true);
-
- when(condition.isConditionMet()).thenReturn(false);
- conditionCallback.onConditionChanged(condition);
- mExecutor.runAllReady();
- verify(callback, never()).onConditionsChanged(false);
+ verify(condition).removeCallback(conditionCallback);
}
@Test
@@ -245,14 +256,16 @@
mock(Monitor.Callback.class);
final Monitor.Callback callback2 =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback1);
- mConditionMonitor.addCallback(callback2);
+ final Monitor.Subscription.Token subscription1 =
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback1).build());
+ final Monitor.Subscription.Token subscription2 =
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback2).build());
- mConditionMonitor.removeCallback(callback1);
+ mConditionMonitor.removeSubscription(subscription1);
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition, never()).removeCallback(any()));
- mConditionMonitor.removeCallback(callback2);
+ mConditionMonitor.removeSubscription(subscription2);
mExecutor.runAllReady();
mConditions.forEach(condition -> verify(condition).removeCallback(any()));
}
@@ -261,7 +274,7 @@
public void updateCallbacks_allConditionsMet_reportTrue() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
clearInvocations(callback);
mCondition1.fakeUpdateCondition(true);
@@ -276,7 +289,7 @@
public void updateCallbacks_oneConditionStoppedMeeting_reportFalse() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mCondition1.fakeUpdateCondition(true);
mCondition2.fakeUpdateCondition(true);
@@ -292,7 +305,7 @@
public void updateCallbacks_shouldOnlyUpdateWhenValueChanges() {
final Monitor.Callback callback =
mock(Monitor.Callback.class);
- mConditionMonitor.addCallback(callback);
+ mConditionMonitor.addSubscription(getDefaultBuilder(callback).build());
mExecutor.runAllReady();
verify(callback).onConditionsChanged(false);
clearInvocations(callback);
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index 03e18a0..8e00ccf 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -40,6 +40,8 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.SystemProperties;
+import android.os.Trace;
import android.util.Slog;
import android.util.SparseArray;
@@ -144,15 +146,30 @@
private Set<Integer> mDeviceStatesAvailableForAppRequests;
+ @VisibleForTesting
+ interface SystemPropertySetter {
+ void setDebugTracingDeviceStateProperty(String value);
+ }
+ @NonNull
+ private final SystemPropertySetter mSystemPropertySetter;
+
public DeviceStateManagerService(@NonNull Context context) {
this(context, DeviceStatePolicy.Provider
.fromResources(context.getResources())
.instantiate(context));
}
+ private DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
+ this(context, policy, (value) -> {
+ SystemProperties.set("debug.tracing.device_state", value);
+ });
+ }
+
@VisibleForTesting
- DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy) {
+ DeviceStateManagerService(@NonNull Context context, @NonNull DeviceStatePolicy policy,
+ @NonNull SystemPropertySetter systemPropertySetter) {
super(context);
+ mSystemPropertySetter = systemPropertySetter;
// We use the DisplayThread because this service indirectly drives
// display (on/off) and window (position) events through its callbacks.
DisplayThread displayThread = DisplayThread.get();
@@ -462,6 +479,10 @@
FrameworkStatsLog.write(FrameworkStatsLog.DEVICE_STATE_CHANGED,
newState.getIdentifier(), !mCommittedState.isPresent());
+ String traceString = newState.getIdentifier() + ":" + newState.getName();
+ Trace.instantForTrack(
+ Trace.TRACE_TAG_SYSTEM_SERVER, "DeviceStateChanged", traceString);
+ mSystemPropertySetter.setDebugTracingDeviceStateProperty(traceString);
mCommittedState = Optional.of(newState);
mPendingState = Optional.empty();
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index cf63b69..6fd8841 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -1057,7 +1057,17 @@
public void recalculateSplines(boolean applyAdjustment, float[] adjustment) {
mCurrentBrightnessMapper.recalculateSplines(applyAdjustment, adjustment);
- updateAutoBrightness(true /*sendUpdate*/, false /*isManuallySet*/);
+
+ // If rbc is turned on, off or there is a change in strength, we want to reset the short
+ // term model. Since the nits range at which brightness now operates has changed due to
+ // RBC/strength change, any short term model based on the previous range should be
+ // invalidated.
+ resetShortTermModel();
+
+ // When rbc is turned on, we want to accommodate this change in the short term model.
+ if (applyAdjustment) {
+ setScreenBrightnessByUser(getAutomaticScreenBrightness());
+ }
}
private final class AutomaticBrightnessHandler extends Handler {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index a5bb716..d05a902 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -657,12 +657,6 @@
}
mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);
-
- // If rbc is turned on, off or there is a change in strength, we want to reset the short
- // term model. Since the nits range at which brightness now operates has changed due to
- // RBC/strength change, any short term model based on the previous range should be
- // invalidated.
- mAutomaticBrightnessController.resetShortTermModel();
}
/**
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index dd0ec94..43d62aa 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -21,6 +21,7 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
import android.os.AsyncTask;
+import android.os.Trace;
import android.os.UserHandle;
import android.util.Slog;
import android.webkit.UserPackage;
@@ -265,10 +266,12 @@
// Either the current relro creation isn't done yet, or the new relro creatioin
// hasn't kicked off yet (the last relro creation used an out-of-date WebView).
webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
- Slog.e(TAG, "Timed out waiting for relro creation, relros started "
+ String timeoutError = "Timed out waiting for relro creation, relros started "
+ mNumRelroCreationsStarted
+ " relros finished " + mNumRelroCreationsFinished
- + " package dirty? " + mWebViewPackageDirty);
+ + " package dirty? " + mWebViewPackageDirty;
+ Slog.e(TAG, timeoutError);
+ Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, timeoutError);
}
}
if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 9a35970..b3b392c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -9735,6 +9735,7 @@
false /*isNotInRecents*/,
record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
record.mStartBounds, task.getTaskInfo(), checkEnterPictureInPictureAppOpsState());
+ target.setShowBackdrop(record.mShowBackdrop);
target.hasAnimatingParent = record.hasAnimatingParent();
return target;
}
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index caaaf47..53f2c71 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -314,6 +314,10 @@
setAppTransitionState(APP_STATE_TIMEOUT);
}
+ @ColorInt int getNextAppTransitionBackgroundColor() {
+ return mNextAppTransitionBackgroundColor;
+ }
+
HardwareBuffer getAppTransitionThumbnailHeader(WindowContainer container) {
AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
container.hashCode());
@@ -523,6 +527,95 @@
return TransitionAnimation.loadAnimationSafely(context, resId, TAG);
}
+ static int mapOpenCloseTransitTypes(int transit, boolean enter) {
+ int animAttr = 0;
+ switch (transit) {
+ case TRANSIT_OLD_ACTIVITY_OPEN:
+ case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN:
+ animAttr = enter
+ ? WindowAnimation_activityOpenEnterAnimation
+ : WindowAnimation_activityOpenExitAnimation;
+ break;
+ case TRANSIT_OLD_ACTIVITY_CLOSE:
+ case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE:
+ animAttr = enter
+ ? WindowAnimation_activityCloseEnterAnimation
+ : WindowAnimation_activityCloseExitAnimation;
+ break;
+ case TRANSIT_OLD_TASK_OPEN:
+ animAttr = enter
+ ? WindowAnimation_taskOpenEnterAnimation
+ : WindowAnimation_taskOpenExitAnimation;
+ break;
+ case TRANSIT_OLD_TASK_CLOSE:
+ animAttr = enter
+ ? WindowAnimation_taskCloseEnterAnimation
+ : WindowAnimation_taskCloseExitAnimation;
+ break;
+ case TRANSIT_OLD_TASK_TO_FRONT:
+ animAttr = enter
+ ? WindowAnimation_taskToFrontEnterAnimation
+ : WindowAnimation_taskToFrontExitAnimation;
+ break;
+ case TRANSIT_OLD_TASK_TO_BACK:
+ animAttr = enter
+ ? WindowAnimation_taskToBackEnterAnimation
+ : WindowAnimation_taskToBackExitAnimation;
+ break;
+ case TRANSIT_OLD_WALLPAPER_OPEN:
+ animAttr = enter
+ ? WindowAnimation_wallpaperOpenEnterAnimation
+ : WindowAnimation_wallpaperOpenExitAnimation;
+ break;
+ case TRANSIT_OLD_WALLPAPER_CLOSE:
+ animAttr = enter
+ ? WindowAnimation_wallpaperCloseEnterAnimation
+ : WindowAnimation_wallpaperCloseExitAnimation;
+ break;
+ case TRANSIT_OLD_WALLPAPER_INTRA_OPEN:
+ animAttr = enter
+ ? WindowAnimation_wallpaperIntraOpenEnterAnimation
+ : WindowAnimation_wallpaperIntraOpenExitAnimation;
+ break;
+ case TRANSIT_OLD_WALLPAPER_INTRA_CLOSE:
+ animAttr = enter
+ ? WindowAnimation_wallpaperIntraCloseEnterAnimation
+ : WindowAnimation_wallpaperIntraCloseExitAnimation;
+ break;
+ case TRANSIT_OLD_TASK_OPEN_BEHIND:
+ animAttr = enter
+ ? WindowAnimation_launchTaskBehindSourceAnimation
+ : WindowAnimation_launchTaskBehindTargetAnimation;
+ break;
+ // TODO(b/189386466): Use activity transition as the fallback. Investigate if we
+ // need new TaskFragment transition.
+ case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
+ animAttr = enter
+ ? WindowAnimation_activityOpenEnterAnimation
+ : WindowAnimation_activityOpenExitAnimation;
+ break;
+ // TODO(b/189386466): Use activity transition as the fallback. Investigate if we
+ // need new TaskFragment transition.
+ case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
+ animAttr = enter
+ ? WindowAnimation_activityCloseEnterAnimation
+ : WindowAnimation_activityCloseExitAnimation;
+ break;
+ case TRANSIT_OLD_DREAM_ACTIVITY_OPEN:
+ animAttr = enter
+ ? WindowAnimation_dreamActivityOpenEnterAnimation
+ : WindowAnimation_dreamActivityOpenExitAnimation;
+ break;
+ case TRANSIT_OLD_DREAM_ACTIVITY_CLOSE:
+ animAttr = enter
+ ? 0
+ : WindowAnimation_dreamActivityCloseExitAnimation;
+ break;
+ }
+
+ return animAttr;
+ }
+
@Nullable
Animation loadAnimationAttr(LayoutParams lp, int animAttr, int transit) {
return mTransitionAnimation.loadAnimationAttr(lp, animAttr, transit);
@@ -773,94 +866,11 @@
"applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s",
a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
} else {
- int animAttr = 0;
- switch (transit) {
- case TRANSIT_OLD_ACTIVITY_OPEN:
- case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN:
- animAttr = enter
- ? WindowAnimation_activityOpenEnterAnimation
- : WindowAnimation_activityOpenExitAnimation;
- break;
- case TRANSIT_OLD_ACTIVITY_CLOSE:
- case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE:
- animAttr = enter
- ? WindowAnimation_activityCloseEnterAnimation
- : WindowAnimation_activityCloseExitAnimation;
- break;
- case TRANSIT_OLD_TASK_OPEN:
- animAttr = enter
- ? WindowAnimation_taskOpenEnterAnimation
- : WindowAnimation_taskOpenExitAnimation;
- break;
- case TRANSIT_OLD_TASK_CLOSE:
- animAttr = enter
- ? WindowAnimation_taskCloseEnterAnimation
- : WindowAnimation_taskCloseExitAnimation;
- break;
- case TRANSIT_OLD_TASK_TO_FRONT:
- animAttr = enter
- ? WindowAnimation_taskToFrontEnterAnimation
- : WindowAnimation_taskToFrontExitAnimation;
- break;
- case TRANSIT_OLD_TASK_TO_BACK:
- animAttr = enter
- ? WindowAnimation_taskToBackEnterAnimation
- : WindowAnimation_taskToBackExitAnimation;
- break;
- case TRANSIT_OLD_WALLPAPER_OPEN:
- animAttr = enter
- ? WindowAnimation_wallpaperOpenEnterAnimation
- : WindowAnimation_wallpaperOpenExitAnimation;
- break;
- case TRANSIT_OLD_WALLPAPER_CLOSE:
- animAttr = enter
- ? WindowAnimation_wallpaperCloseEnterAnimation
- : WindowAnimation_wallpaperCloseExitAnimation;
- break;
- case TRANSIT_OLD_WALLPAPER_INTRA_OPEN:
- animAttr = enter
- ? WindowAnimation_wallpaperIntraOpenEnterAnimation
- : WindowAnimation_wallpaperIntraOpenExitAnimation;
- break;
- case TRANSIT_OLD_WALLPAPER_INTRA_CLOSE:
- animAttr = enter
- ? WindowAnimation_wallpaperIntraCloseEnterAnimation
- : WindowAnimation_wallpaperIntraCloseExitAnimation;
- break;
- case TRANSIT_OLD_TASK_OPEN_BEHIND:
- animAttr = enter
- ? WindowAnimation_launchTaskBehindSourceAnimation
- : WindowAnimation_launchTaskBehindTargetAnimation;
- break;
- // TODO(b/189386466): Use activity transition as the fallback. Investigate if we
- // need new TaskFragment transition.
- case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
- animAttr = enter
- ? WindowAnimation_activityOpenEnterAnimation
- : WindowAnimation_activityOpenExitAnimation;
- break;
- // TODO(b/189386466): Use activity transition as the fallback. Investigate if we
- // need new TaskFragment transition.
- case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
- animAttr = enter
- ? WindowAnimation_activityCloseEnterAnimation
- : WindowAnimation_activityCloseExitAnimation;
- break;
- case TRANSIT_OLD_DREAM_ACTIVITY_OPEN:
- animAttr = enter
- ? WindowAnimation_dreamActivityOpenEnterAnimation
- : WindowAnimation_dreamActivityOpenExitAnimation;
- break;
- case TRANSIT_OLD_DREAM_ACTIVITY_CLOSE:
- animAttr = enter
- ? 0
- : WindowAnimation_dreamActivityCloseExitAnimation;
- break;
- }
-
+ int animAttr = mapOpenCloseTransitTypes(transit, enter);
a = animAttr == 0 ? null : (canCustomizeAppTransition
- ? loadAnimationAttr(lp, animAttr, transit)
- : mTransitionAnimation.loadDefaultAnimationAttr(animAttr, transit));
+ ? loadAnimationAttr(lp, animAttr, transit)
+ : mTransitionAnimation.loadDefaultAnimationAttr(animAttr, transit));
+
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
"applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b "
+ " canCustomizeAppTransition=%b Callers=%s",
@@ -1011,18 +1021,19 @@
}
void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter) {
- overridePendingAppTransitionRemote(remoteAnimationAdapter, false /* sync */);
+ overridePendingAppTransitionRemote(remoteAnimationAdapter, false /* sync */,
+ false /* isActivityEmbedding*/);
}
void overridePendingAppTransitionRemote(RemoteAnimationAdapter remoteAnimationAdapter,
- boolean sync) {
+ boolean sync, boolean isActivityEmbedding) {
ProtoLog.i(WM_DEBUG_APP_TRANSITIONS, "Override pending remote transitionSet=%b adapter=%s",
isTransitionSet(), remoteAnimationAdapter);
if (isTransitionSet() && !mNextAppTransitionIsSync) {
clear();
mNextAppTransitionType = NEXT_TRANSIT_TYPE_REMOTE;
mRemoteAnimationController = new RemoteAnimationController(mService, mDisplayContent,
- remoteAnimationAdapter, mHandler);
+ remoteAnimationAdapter, mHandler, isActivityEmbedding);
mNextAppTransitionIsSync = sync;
}
}
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index fbb7dac..3d66122 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -693,7 +693,8 @@
if (adapter == null) {
return false;
}
- mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(adapter);
+ mDisplayContent.mAppTransition.overridePendingAppTransitionRemote(
+ adapter, false /* sync */, true /*isActivityEmbedding*/);
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"Override with TaskFragment remote animation for transit=%s",
AppTransition.appTransitionOldToString(transit));
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index fd06313..7ca38b8 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -99,19 +99,28 @@
state.setRoundedCorners(roundedCorners);
state.setPrivacyIndicatorBounds(indicatorBounds);
state.getDisplayCutoutSafe(safe);
- if (!cutout.isEmpty()) {
+ if (safe.left > unrestricted.left) {
state.getSource(ITYPE_LEFT_DISPLAY_CUTOUT).setFrame(
unrestricted.left, unrestricted.top, safe.left, unrestricted.bottom);
+ } else {
+ state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
+ }
+ if (safe.top > unrestricted.top) {
state.getSource(ITYPE_TOP_DISPLAY_CUTOUT).setFrame(
unrestricted.left, unrestricted.top, unrestricted.right, safe.top);
+ } else {
+ state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
+ }
+ if (safe.right < unrestricted.right) {
state.getSource(ITYPE_RIGHT_DISPLAY_CUTOUT).setFrame(
safe.right, unrestricted.top, unrestricted.right, unrestricted.bottom);
+ } else {
+ state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
+ }
+ if (safe.bottom < unrestricted.bottom) {
state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(
unrestricted.left, safe.bottom, unrestricted.right, unrestricted.bottom);
} else {
- state.removeSource(ITYPE_LEFT_DISPLAY_CUTOUT);
- state.removeSource(ITYPE_TOP_DISPLAY_CUTOUT);
- state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
}
return true;
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 4a0a6e3..ad158c7 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -22,6 +22,7 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Point;
@@ -57,7 +58,7 @@
*/
class RemoteAnimationController implements DeathRecipient {
private static final String TAG = TAG_WITH_CLASS_NAME
- ? "RemoteAnimationController" : TAG_WM;
+ ? "RemoteAnimationController" : TAG_WM;
private static final long TIMEOUT_MS = 10000;
private final WindowManagerService mService;
@@ -72,35 +73,40 @@
private final Runnable mTimeoutRunnable = () -> cancelAnimation("timeoutRunnable");
private FinishedCallback mFinishedCallback;
+ private final boolean mIsActivityEmbedding;
private boolean mCanceled;
private boolean mLinkedToDeathOfRunner;
@Nullable
private Runnable mOnRemoteAnimationReady;
RemoteAnimationController(WindowManagerService service, DisplayContent displayContent,
- RemoteAnimationAdapter remoteAnimationAdapter, Handler handler) {
+ RemoteAnimationAdapter remoteAnimationAdapter, Handler handler,
+ boolean isActivityEmbedding) {
mService = service;
mDisplayContent = displayContent;
mRemoteAnimationAdapter = remoteAnimationAdapter;
mHandler = handler;
+ mIsActivityEmbedding = isActivityEmbedding;
}
/**
* Creates an animation record for each individual {@link WindowContainer}.
*
* @param windowContainer The windows to animate.
- * @param position The position app bounds relative to its parent.
- * @param localBounds The bounds of the app relative to its parent.
- * @param endBounds The end bounds after the transition, in screen coordinates.
- * @param startBounds The start bounds before the transition, in screen coordinates.
+ * @param position The position app bounds relative to its parent.
+ * @param localBounds The bounds of the app relative to its parent.
+ * @param endBounds The end bounds after the transition, in screen coordinates.
+ * @param startBounds The start bounds before the transition, in screen coordinates.
+ * @param showBackdrop To show background behind a window during animation.
* @return The record representing animation(s) to run on the app.
*/
RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
- Point position, Rect localBounds, Rect endBounds, Rect startBounds) {
+ Point position, Rect localBounds, Rect endBounds, Rect startBounds,
+ boolean showBackdrop) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
windowContainer);
final RemoteAnimationRecord adapters = new RemoteAnimationRecord(windowContainer, position,
- localBounds, endBounds, startBounds);
+ localBounds, endBounds, startBounds, showBackdrop);
mPendingAnimations.add(adapters);
return adapters;
}
@@ -111,6 +117,15 @@
}
/**
+ * We use isFromActivityEmbedding() in the server process to tell if we're running an
+ * Activity Embedding type remote animation, where animations are driven by the client.
+ * This is currently supporting features like showBackdrop where we need to load App XML.
+ */
+ public boolean isFromActivityEmbedding() {
+ return mIsActivityEmbedding;
+ }
+
+ /**
* Called when the transition is ready to be started, and all leashes have been set up.
*/
void goodToGo(@WindowManager.TransitionOldType int transit) {
@@ -416,30 +431,37 @@
RemoteAnimationTarget mTarget;
final WindowContainer mWindowContainer;
final Rect mStartBounds;
+ final boolean mShowBackdrop;
+ @ColorInt int mBackdropColor = 0;
private @RemoteAnimationTarget.Mode int mMode = RemoteAnimationTarget.MODE_CHANGING;
RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds,
- Rect endBounds, Rect startBounds) {
+ Rect endBounds, Rect startBounds, boolean showBackdrop) {
mWindowContainer = windowContainer;
+ mShowBackdrop = showBackdrop;
if (startBounds != null) {
mStartBounds = new Rect(startBounds);
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
- mStartBounds);
+ mStartBounds, mShowBackdrop);
if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
final Rect thumbnailLocalBounds = new Rect(startBounds);
thumbnailLocalBounds.offsetTo(0, 0);
// Snapshot is located at (0,0) of the animation leash. It doesn't have size
// change, so the startBounds is its end bounds, and no start bounds for it.
mThumbnailAdapter = new RemoteAnimationAdapterWrapper(this, new Point(0, 0),
- thumbnailLocalBounds, startBounds, new Rect());
+ thumbnailLocalBounds, startBounds, new Rect(), mShowBackdrop);
}
} else {
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
- new Rect());
+ new Rect(), mShowBackdrop);
mStartBounds = null;
}
}
+ void setBackDropColor(@ColorInt int backdropColor) {
+ mBackdropColor = backdropColor;
+ }
+
RemoteAnimationTarget createRemoteAnimationTarget() {
if (mAdapter == null
|| mAdapter.mCapturedFinishCallback == null
@@ -481,14 +503,27 @@
final Rect mLocalBounds;
final Rect mEndBounds = new Rect();
final Rect mStartBounds = new Rect();
+ final boolean mShowBackdrop;
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
- Rect localBounds, Rect endBounds, Rect startBounds) {
+ Rect localBounds, Rect endBounds, Rect startBounds, boolean showBackdrop) {
mRecord = record;
mPosition.set(position.x, position.y);
mLocalBounds = localBounds;
mEndBounds.set(endBounds);
mStartBounds.set(startBounds);
+ mShowBackdrop = showBackdrop;
+ }
+
+ @Override
+ @ColorInt
+ public int getBackgroundColor() {
+ return mRecord.mBackdropColor;
+ }
+
+ @Override
+ public boolean getShowBackground() {
+ return mShowBackdrop;
}
@Override
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index d8404a7..3c0cac0 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -305,6 +305,16 @@
return mFlags;
}
+ @VisibleForTesting
+ SurfaceControl.Transaction getStartTransaction() {
+ return mStartTransaction;
+ }
+
+ @VisibleForTesting
+ SurfaceControl.Transaction getFinishTransaction() {
+ return mFinishTransaction;
+ }
+
/** Starts collecting phase. Once this starts, all relevant surface operations are sync. */
void startCollecting(long timeoutMs) {
if (mState != STATE_PENDING) {
@@ -771,6 +781,8 @@
}
mState = STATE_PLAYING;
+ mStartTransaction = transaction;
+ mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
mController.moveToPlaying(this);
if (dc.isKeyguardLocked()) {
@@ -856,8 +868,6 @@
if (controller != null && mTargets.contains(dc)) {
controller.setupStartTransaction(transaction);
}
- mStartTransaction = transaction;
- mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get();
buildFinishTransaction(mFinishTransaction, info.getRootLeash());
if (mController.getTransitionPlayer() != null) {
mController.dispatchLegacyAppTransitionStarting(info);
diff --git a/services/core/java/com/android/server/wm/TransitionTracer.java b/services/core/java/com/android/server/wm/TransitionTracer.java
index 192b9ab..b1951e0 100644
--- a/services/core/java/com/android/server/wm/TransitionTracer.java
+++ b/services/core/java/com/android/server/wm/TransitionTracer.java
@@ -23,8 +23,10 @@
import static com.android.server.wm.shell.ChangeInfo.TRANSIT_MODE;
import static com.android.server.wm.shell.ChangeInfo.WINDOW_IDENTIFIER;
import static com.android.server.wm.shell.Transition.CHANGE;
+import static com.android.server.wm.shell.Transition.FINISH_TRANSACTION_ID;
import static com.android.server.wm.shell.Transition.FLAGS;
import static com.android.server.wm.shell.Transition.ID;
+import static com.android.server.wm.shell.Transition.START_TRANSACTION_ID;
import static com.android.server.wm.shell.Transition.STATE;
import static com.android.server.wm.shell.Transition.TIMESTAMP;
import static com.android.server.wm.shell.Transition.TRANSITION_TYPE;
@@ -82,6 +84,13 @@
outputStream.write(TRANSITION_TYPE, transition.mType);
outputStream.write(STATE, transition.getState());
outputStream.write(FLAGS, transition.getFlags());
+ if (transition.getStartTransaction() != null) {
+ outputStream.write(START_TRANSACTION_ID, transition.getStartTransaction().getId());
+ }
+ if (transition.getFinishTransaction() != null) {
+ outputStream.write(FINISH_TRANSACTION_ID,
+ transition.getFinishTransaction().getId());
+ }
for (int i = 0; i < transition.mChanges.size(); ++i) {
final WindowContainer window = transition.mChanges.keyAt(i);
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 51adb16..59aed83 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2940,18 +2940,34 @@
getAnimationPosition(mTmpPoint);
mTmpRect.offsetTo(0, 0);
- final RemoteAnimationController controller =
- getDisplayContent().mAppTransition.getRemoteAnimationController();
+ final AppTransition appTransition = getDisplayContent().mAppTransition;
+ final RemoteAnimationController controller = appTransition.getRemoteAnimationController();
final boolean isChanging = AppTransition.isChangeTransitOld(transit) && enter
&& isChangingAppTransition();
// Delaying animation start isn't compatible with remote animations at all.
if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
+ // Here we load App XML in order to read com.android.R.styleable#Animation_showBackdrop.
+ boolean showBackdrop = false;
+ // Optionally set backdrop color if App explicitly provides it through
+ // {@link Activity#overridePendingTransition(int, int, int)}.
+ @ColorInt int backdropColor = 0;
+ if (controller.isFromActivityEmbedding()) {
+ final int animAttr = AppTransition.mapOpenCloseTransitTypes(transit, enter);
+ final Animation a = animAttr != 0
+ ? appTransition.loadAnimationAttr(lp, animAttr, transit) : null;
+ showBackdrop = a != null && a.getShowBackdrop();
+ backdropColor = appTransition.getNextAppTransitionBackgroundColor();
+ }
final Rect localBounds = new Rect(mTmpRect);
localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
final RemoteAnimationController.RemoteAnimationRecord adapters =
- controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,
- screenBounds, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
+ controller.createRemoteAnimationRecord(
+ this, mTmpPoint, localBounds, screenBounds,
+ (isChanging ? mSurfaceFreezer.mFreezeBounds : null), showBackdrop);
+ if (backdropColor != 0) {
+ adapters.setBackDropColor(backdropColor);
+ }
if (!isChanging) {
adapters.setMode(enter
? RemoteAnimationTarget.MODE_OPENING
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 54cf57f..1d93c89 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -328,7 +328,8 @@
}
adapter.setCallingPidUid(caller.mPid, caller.mUid);
dc.prepareAppTransition(type);
- dc.mAppTransition.overridePendingAppTransitionRemote(adapter, true /* sync */);
+ dc.mAppTransition.overridePendingAppTransitionRemote(adapter, true /* sync */,
+ false /* isActivityEmbedding */);
syncId = startSyncWithOrganizer(callback);
applyTransaction(t, syncId, null /* transition */, caller);
setSyncReady(syncId);
diff --git a/services/proguard.flags b/services/proguard.flags
index bad02b4..c648f7d 100644
--- a/services/proguard.flags
+++ b/services/proguard.flags
@@ -68,6 +68,9 @@
# TODO(b/210510433): Revisit and consider generating from frameworks/base/core/res/res/values/config.xml.
-keep,allowoptimization,allowaccessmodification public class com.android.server.notification.** implements com.android.server.notification.NotificationSignalExtractor
+# OEM provided DisplayAreaPolicy.Provider defined in frameworks/base/core/res/res/values/config.xml.
+-keep,allowoptimization,allowaccessmodification class com.android.server.wm.** implements com.android.server.wm.DisplayAreaPolicy$Provider
+
# JNI keep rules
# TODO(b/210510433): Revisit and fix with @Keep, or consider auto-generating from
# frameworks/base/services/core/jni/onload.cpp.
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index fe3034d..038cbc0 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -76,12 +76,15 @@
private TestDeviceStatePolicy mPolicy;
private TestDeviceStateProvider mProvider;
private DeviceStateManagerService mService;
+ private TestSystemPropertySetter mSysPropSetter;
@Before
public void setup() {
mProvider = new TestDeviceStateProvider();
mPolicy = new TestDeviceStatePolicy(mProvider);
- mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy);
+ mSysPropSetter = new TestSystemPropertySetter();
+ mService = new DeviceStateManagerService(InstrumentationRegistry.getContext(), mPolicy,
+ mSysPropSetter);
// Necessary to allow us to check for top app process id in tests
mService.mActivityTaskManagerInternal = mock(ActivityTaskManagerInternal.class);
@@ -107,6 +110,8 @@
public void baseStateChanged() {
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -115,6 +120,8 @@
flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -128,6 +135,8 @@
flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -136,6 +145,8 @@
flushHandler();
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -157,6 +168,8 @@
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -170,6 +183,8 @@
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -182,6 +197,8 @@
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE);
@@ -193,6 +210,8 @@
// supported.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE);
@@ -211,6 +230,8 @@
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE);
@@ -223,6 +244,8 @@
// supported.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertThat(mService.getSupportedStates()).asList().containsExactly(DEFAULT_DEVICE_STATE,
OTHER_DEVICE_STATE);
@@ -315,6 +338,8 @@
TestDeviceStateManagerCallback.STATUS_ACTIVE);
// Committed state changes as there is a requested override.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -333,6 +358,8 @@
TestDeviceStateManagerCallback.STATUS_CANCELED);
// Committed state is set back to the requested state once the override is cleared.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertFalse(mService.getOverrideState().isPresent());
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -385,9 +412,10 @@
// callback.
assertEquals(callback.getLastNotifiedStatus(secondRequestToken),
TestDeviceStateManagerCallback.STATUS_UNKNOWN);
-
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -397,6 +425,8 @@
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -412,6 +442,8 @@
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
DEFAULT_DEVICE_STATE.getIdentifier());
@@ -458,6 +490,8 @@
// Committed state changes as there is a requested override.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -471,6 +505,8 @@
// Committed state is set back to the requested state once the override is cleared.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
assertEquals(mService.getBaseState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertFalse(mService.getOverrideState().isPresent());
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
OTHER_DEVICE_STATE.getIdentifier());
@@ -495,6 +531,8 @@
TestDeviceStateManagerCallback.STATUS_ACTIVE);
// Committed state changes as there is a requested override.
assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ OTHER_DEVICE_STATE.getIdentifier() + ":" + OTHER_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getOverrideState().get(), OTHER_DEVICE_STATE);
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -509,6 +547,8 @@
// Committed state is set back to the requested state as the override state is no longer
// supported.
assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
+ assertEquals(mSysPropSetter.getValue(),
+ DEFAULT_DEVICE_STATE.getIdentifier() + ":" + DEFAULT_DEVICE_STATE.getName());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertFalse(mService.getOverrideState().isPresent());
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
@@ -673,4 +713,18 @@
return mLastNotifiedStatus.getOrDefault(requestToken, STATUS_UNKNOWN);
}
}
+
+ private static final class TestSystemPropertySetter implements
+ DeviceStateManagerService.SystemPropertySetter {
+ private String mValue;
+
+ @Override
+ public void setDebugTracingDeviceStateProperty(String value) {
+ mValue = value;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index b0c52f1..9d82f1a 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -24,6 +24,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyFloat;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -258,29 +259,36 @@
@Test
public void testRecalculateSplines() throws Exception {
// Enabling the light sensor, and setting the ambient lux to 1000
+ int currentLux = 1000;
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
- listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1000));
+ listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, currentLux));
- //Setting the brightnessFloat to 0.5f
- float currentBrightnessFloat = 0.5f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(currentBrightnessFloat);
+ // User sets brightness to 0.5f
+ when(mBrightnessMappingStrategy.getBrightness(currentLux,
+ null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(0.5f);
mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
- currentBrightnessFloat /* brightness */, false /* userChangedBrightness */,
- 0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
+ 0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
+ false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
- // Adjusting spline, and accordingly remapping the current 0.5f brightnessFloat to 0.3f
- float updatedBrightnessFloat = 0.3f;
- when(mBrightnessMappingStrategy.getBrightness(1000,
- null, ApplicationInfo.CATEGORY_UNDEFINED)).thenReturn(updatedBrightnessFloat);
- float[] adjustments = new float[]{0.2f, 0.5f};
+ //Recalculating the spline with RBC enabled, verifying that the short term model is reset,
+ //and the interaction is learnt in short term model
+ float[] adjustments = new float[]{0.2f, 0.6f};
mController.recalculateSplines(true, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
verify(mBrightnessMappingStrategy).recalculateSplines(true, adjustments);
- assertEquals(mController.getAutomaticScreenBrightness(), updatedBrightnessFloat, EPSILON);
+ verify(mBrightnessMappingStrategy, times(2)).addUserDataPoint(currentLux, 0.5f);
+
+ clearInvocations(mBrightnessMappingStrategy);
+
+ // Verify short term model is not learnt when RBC is disabled
+ mController.recalculateSplines(false, adjustments);
+ verify(mBrightnessMappingStrategy).clearUserDataPoints();
+ verify(mBrightnessMappingStrategy).recalculateSplines(false, adjustments);
+ verifyNoMoreInteractions(mBrightnessMappingStrategy);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index a4851ad5..204c7e6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -78,19 +78,25 @@
/**
* Build/Install/Run:
- * atest WmTests:RemoteAnimationControllerTest
+ * atest WmTests:RemoteAnimationControllerTest
*/
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
public class RemoteAnimationControllerTest extends WindowTestsBase {
- @Mock SurfaceControl mMockLeash;
- @Mock SurfaceControl mMockThumbnailLeash;
- @Mock Transaction mMockTransaction;
- @Mock OnAnimationFinishedCallback mFinishedCallback;
- @Mock OnAnimationFinishedCallback mThumbnailFinishedCallback;
- @Mock IRemoteAnimationRunner mMockRunner;
+ @Mock
+ SurfaceControl mMockLeash;
+ @Mock
+ SurfaceControl mMockThumbnailLeash;
+ @Mock
+ Transaction mMockTransaction;
+ @Mock
+ OnAnimationFinishedCallback mFinishedCallback;
+ @Mock
+ OnAnimationFinishedCallback mThumbnailFinishedCallback;
+ @Mock
+ IRemoteAnimationRunner mMockRunner;
private RemoteAnimationAdapter mAdapter;
private RemoteAnimationController mController;
private final OffsettableClock mClock = new OffsettableClock.Stopped();
@@ -104,7 +110,8 @@
mAdapter = new RemoteAnimationAdapter(mMockRunner, 100, 50, true /* changeNeedsSnapshot */);
mAdapter.setCallingPidUid(123, 456);
runWithScissors(mWm.mH, () -> mHandler = new TestHandler(null, mClock), 0);
- mController = new RemoteAnimationController(mWm, mDisplayContent, mAdapter, mHandler);
+ mController = new RemoteAnimationController(mWm, mDisplayContent, mAdapter,
+ mHandler, false /*isActivityEmbedding*/);
}
private WindowState createAppOverlayWindow() {
@@ -116,13 +123,47 @@
}
@Test
+ public void testForwardsShowBackdrop() throws Exception {
+ final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
+ mDisplayContent.mOpeningApps.add(win.mActivityRecord);
+ final WindowState overlayWin = createAppOverlayWindow();
+ try {
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null,
+ true /* showBackdrop */).mAdapter;
+ adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
+ mFinishedCallback);
+ mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
+ mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+ final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
+ ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+ final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
+ ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+ final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
+ ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
+ final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
+ ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
+ verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
+ appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
+ finishedCaptor.capture());
+ assertEquals(1, appsCaptor.getValue().length);
+ final RemoteAnimationTarget app = appsCaptor.getValue()[0];
+ assertTrue(app.showBackdrop);
+ } finally {
+ mDisplayContent.mOpeningApps.clear();
+ }
+ }
+
+ @Test
public void testRun() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
final WindowState overlayWin = createAppOverlayWindow();
try {
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -161,8 +202,9 @@
@Test
public void testCancel() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -174,8 +216,9 @@
@Test
public void testTimeout() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -196,7 +239,7 @@
"testWin");
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
- null).mAdapter;
+ null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -228,7 +271,7 @@
public void testNotReallyStarted() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
verify(mMockRunner).onAnimationCancelled();
@@ -239,9 +282,10 @@
final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
mController.createRemoteAnimationRecord(win1.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null);
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win2.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false);
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win2.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -264,8 +308,9 @@
@Test
public void testRemovedBeforeStarted() throws Exception {
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
win.mActivityRecord.removeImmediately();
@@ -309,7 +354,7 @@
try {
final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
- new Rect(0, 0, 200, 200));
+ new Rect(0, 0, 200, 200), false);
assertNotNull(record.mThumbnailAdapter);
((AnimationAdapter) record.mAdapter)
.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
@@ -363,7 +408,7 @@
try {
final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(0, 0), null, new Rect(0, 0, 200, 200),
- new Rect(50, 100, 150, 150));
+ new Rect(50, 100, 150, 150), false);
assertNotNull(record.mThumbnailAdapter);
((AnimationAdapter) record.mAdapter)
.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
@@ -417,7 +462,7 @@
try {
final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(100, 100), null, new Rect(150, 150, 400, 400),
- new Rect(50, 100, 150, 150));
+ new Rect(50, 100, 150, 150), false);
assertNotNull(record.mThumbnailAdapter);
((AnimationAdapter) record.mAdapter)
.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
@@ -474,8 +519,9 @@
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
try {
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -506,8 +552,9 @@
final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
mDisplayContent.mOpeningApps.add(win.mActivityRecord);
try {
- final AnimationAdapter adapter = mController.createRemoteAnimationRecord(win.mActivityRecord,
- new Point(50, 100), null, new Rect(50, 100, 150, 150), null).mAdapter;
+ final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+ win.mActivityRecord,
+ new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
@@ -543,7 +590,7 @@
try {
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(50, 100), null,
- new Rect(50, 100, 150, 150), null).mAdapter;
+ new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY);
@@ -593,7 +640,7 @@
try {
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(50, 100), null,
- new Rect(50, 100, 150, 150), null).mAdapter;
+ new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
@@ -727,7 +774,7 @@
mDisplayContent.mOpeningApps.add(win2.mActivityRecord);
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
win2.mActivityRecord, new Point(50, 100), null,
- new Rect(50, 100, 150, 150), null).mAdapter;
+ new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
@@ -757,7 +804,7 @@
final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
win.mActivityRecord, new Point(50, 100), null,
- new Rect(50, 100, 150, 150), null).mAdapter;
+ new Rect(50, 100, 150, 150), null, false).mAdapter;
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
mFinishedCallback);
mController.goodToGo(transit);