summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Xin Li <delphij@google.com> 2022-02-14 23:57:02 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-02-14 23:57:02 +0000
commit5409ef1ab7ea2138a5e22f7e0d30b837ce0c4f04 (patch)
tree9cdc6ca664c398de7055bb70f9b2360a006e38c6
parent5dbc71e1f0f4878ac05106e3ef5ba96c120111f3 (diff)
parent2b87be68b86accaadfd2bdf5efe68f1a4d4cd1f9 (diff)
Merge "Merge SP2A.220305.012" into stage-aosp-master
-rw-r--r--core/java/android/app/ServiceStartNotAllowedException.java7
-rw-r--r--core/java/android/app/WallpaperManager.java40
-rw-r--r--core/java/com/android/internal/app/LocalePickerWithRegion.java8
-rw-r--r--libs/WindowManager/Shell/res/values/config.xml3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java6
-rw-r--r--packages/SystemUI/res/layout/internet_connectivity_dialog.xml18
-rw-r--r--packages/SystemUI/res/values/styles.xml3
-rw-r--r--packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java23
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java66
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt83
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java16
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java117
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java27
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java1
-rw-r--r--services/core/java/com/android/server/wm/Task.java6
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java1
27 files changed, 395 insertions, 163 deletions
diff --git a/core/java/android/app/ServiceStartNotAllowedException.java b/core/java/android/app/ServiceStartNotAllowedException.java
index 33285b2190eb..b1f47eee4bfd 100644
--- a/core/java/android/app/ServiceStartNotAllowedException.java
+++ b/core/java/android/app/ServiceStartNotAllowedException.java
@@ -40,4 +40,11 @@ public abstract class ServiceStartNotAllowedException extends IllegalStateExcept
return new BackgroundServiceStartNotAllowedException(message);
}
}
+
+ @Override
+ public synchronized Throwable getCause() {
+ // "Cause" is often used for clustering exceptions, and developers don't want to have it
+ // for this exception. b/210890426
+ return null;
+ }
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 3712caeddaf5..fca4c698c49c 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1488,27 +1488,18 @@ public class WallpaperManager {
mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
- final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid));
+ boolean ok = false;
try {
- // If the stream can't be decoded, treat it as an invalid input.
- if (tmp != null) {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
- // The 'close()' is the trigger for any server-side image manipulation,
- // so we must do that before waiting for completion.
- fos.close();
- completion.waitForCompletion();
- } else {
- throw new IllegalArgumentException(
- "Resource 0x" + Integer.toHexString(resid) + " is invalid");
- }
+ fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
+ // The 'close()' is the trigger for any server-side image manipulation,
+ // so we must do that before waiting for completion.
+ fos.close();
+ completion.waitForCompletion();
} finally {
// Might be redundant but completion shouldn't wait unless the write
// succeeded; this is a fallback if it threw past the close+wait.
IoUtils.closeQuietly(fos);
- if (tmp != null) {
- tmp.recycle();
- }
}
}
} catch (RemoteException e) {
@@ -1750,22 +1741,13 @@ public class WallpaperManager {
result, which, completion, mContext.getUserId());
if (fd != null) {
FileOutputStream fos = null;
- final Bitmap tmp = BitmapFactory.decodeStream(bitmapData);
try {
- // If the stream can't be decoded, treat it as an invalid input.
- if (tmp != null) {
- fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
- tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
- fos.close();
- completion.waitForCompletion();
- } else {
- throw new IllegalArgumentException("InputStream is invalid");
- }
+ fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ copyStreamToWallpaperFile(bitmapData, fos);
+ fos.close();
+ completion.waitForCompletion();
} finally {
IoUtils.closeQuietly(fos);
- if (tmp != null) {
- tmp.recycle();
- }
}
}
} catch (RemoteException e) {
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index d0719eeca04e..b4ae56f23443 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -159,6 +159,14 @@ public class LocalePickerWithRegion extends ListFragment implements SearchView.O
}
@Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ // In order to make the list view work with CollapsingToolbarLayout,
+ // we have to enable the nested scrolling feature of the list view.
+ getListView().setNestedScrollingEnabled(true);
+ }
+
+ @Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
int id = menuItem.getItemId();
switch (id) {
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 0cdaa206c156..1b8032b7077b 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -43,6 +43,9 @@
<!-- PiP minimum size, which is a % based off the shorter side of display width and height -->
<fraction name="config_pipShortestEdgePercent">40%</fraction>
+ <!-- Show PiP enter split icon, which allows apps to directly enter splitscreen from PiP. -->
+ <bool name="config_pipEnableEnterSplitButton">false</bool>
+
<!-- Animation duration when using long press on recents to dock -->
<integer name="long_press_dock_anim_duration">250</integer>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 620c291b357b..14433c233273 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -1724,6 +1724,7 @@ public class BubbleStackView extends FrameLayout
/**
* Changes the expanded state of the stack.
+ * Don't call this directly, call mBubbleData#setExpanded.
*
* @param shouldExpand whether the bubble stack should appear expanded
*/
@@ -1770,7 +1771,7 @@ public class BubbleStackView extends FrameLayout
} else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
mManageEduView.hide();
} else {
- setExpanded(false);
+ mBubbleData.setExpanded(false);
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index da4bbe81a3e6..e1475efcdb57 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -104,8 +104,6 @@ public class PipMenuView extends FrameLayout {
private static final float MENU_BACKGROUND_ALPHA = 0.3f;
private static final float DISABLED_ACTION_ALPHA = 0.54f;
- private static final boolean ENABLE_ENTER_SPLIT = true;
-
private int mMenuState;
private boolean mAllowMenuTimeout = true;
private boolean mAllowTouches = true;
@@ -277,6 +275,8 @@ public class PipMenuView extends FrameLayout {
boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
mAllowMenuTimeout = allowMenuTimeout;
mDidLastShowMenuResize = resizeMenuOnShow;
+ final boolean enableEnterSplit =
+ mContext.getResources().getBoolean(R.bool.config_pipEnableEnterSplitButton);
if (mMenuState != menuState) {
// Disallow touches if the menu needs to resize while showing, and we are transitioning
// to/from a full menu state.
@@ -297,7 +297,7 @@ public class PipMenuView extends FrameLayout {
mDismissButton.getAlpha(), 1f);
ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA,
mEnterSplitButton.getAlpha(),
- ENABLE_ENTER_SPLIT && mFocusedTaskAllowSplitScreen ? 1f : 0f);
+ enableEnterSplit && mFocusedTaskAllowSplitScreen ? 1f : 0f);
if (menuState == MENU_STATE_FULL) {
mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
enterSplitAnim);
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index e69582f52ebf..f72a8dc08c9c 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -378,7 +378,8 @@
android:clickable="true"/>
</LinearLayout>
</LinearLayout>
- <FrameLayout
+
+ <LinearLayout
android:id="@+id/button_layout"
android:orientation="horizontal"
android:layout_width="match_parent"
@@ -390,9 +391,10 @@
android:clickable="false"
android:focusable="false">
- <FrameLayout
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_weight="1"
android:layout_gravity="start|center_vertical"
android:orientation="vertical">
<Button
@@ -401,12 +403,13 @@
android:layout_height="wrap_content"
android:text="@string/turn_off_airplane_mode"
android:ellipsize="end"
+ android:maxLines="1"
style="@style/Widget.Dialog.Button.BorderButton"
android:clickable="true"
android:focusable="true"/>
- </FrameLayout>
+ </LinearLayout>
- <FrameLayout
+ <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -417,10 +420,13 @@
android:layout_height="wrap_content"
android:text="@string/inline_done_button"
style="@style/Widget.Dialog.Button"
+ android:maxLines="1"
+ android:ellipsize="end"
android:clickable="true"
android:focusable="true"/>
- </FrameLayout>
- </FrameLayout>
+ </LinearLayout>
+ </LinearLayout>
+
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 051a30ccb524..f26159f5176a 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -942,8 +942,9 @@
</style>
<style name="InternetDialog.NetworkSummary">
- <item name="android:layout_marginEnd">34dp</item>
+ <item name="android:layout_marginEnd">7dp</item>
<item name="android:ellipsize">end</item>
+ <item name="android:maxLines">2</item>
<item name="android:textAppearance">@style/TextAppearance.InternetDialog.Secondary</item>
</style>
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
index 0934b32a71e4..b920a17a0c1c 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
@@ -16,12 +16,15 @@
package com.android.systemui.flags;
+import android.content.res.Resources;
import android.util.SparseBooleanArray;
+import androidx.annotation.BoolRes;
import androidx.annotation.NonNull;
import com.android.systemui.Dumpable;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import java.io.FileDescriptor;
@@ -38,8 +41,11 @@ import javax.inject.Inject;
@SysUISingleton
public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
SparseBooleanArray mAccessedFlags = new SparseBooleanArray();
+ private Resources mResources;
+
@Inject
- public FeatureFlagManager(DumpManager dumpManager) {
+ public FeatureFlagManager(DumpManager dumpManager, @Main Resources resources) {
+ mResources = resources;
dumpManager.registerDumpable("SysUIFlags", this);
}
@@ -51,7 +57,20 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
@Override
public boolean isEnabled(BooleanFlag flag) {
- return isEnabled(flag.getId(), flag.getDefault());
+ boolean def = flag.getDefault();
+ if (flag.hasResourceOverride()) {
+ try {
+ def = isEnabledInOverlay(flag.getResourceOverride());
+ } catch (Resources.NotFoundException e) {
+ // no-op
+ }
+ }
+
+ return isEnabled(flag.getId(), def);
+ }
+
+ private boolean isEnabledInOverlay(@BoolRes int resId) {
+ return mResources.getBoolean(resId);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java
index 0340904cbd9d..b2658c9f9bdb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardConstants.java
@@ -16,6 +16,8 @@
package com.android.keyguard;
+import android.util.Log;
+
/**
* Defines constants for the Keyguard.
*/
@@ -25,7 +27,7 @@ public class KeyguardConstants {
* Turns on debugging information for the whole Keyguard. This is very verbose and should only
* be used temporarily for debugging.
*/
- public static final boolean DEBUG = false;
+ public static final boolean DEBUG = Log.isLoggable("Keyguard", Log.DEBUG);
public static final boolean DEBUG_SIM_STATES = true;
public static final boolean DEBUG_BIOMETRIC_WAKELOCK = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index 66c51d278dab..e2716e992c48 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -159,7 +159,9 @@ public class MediaProjectionPermissionActivity extends Activity
mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setFilterTouchesWhenObscured(true);
final Window w = mDialog.getWindow();
- w.setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ // QS is not closed when pressing CastTile. Match the type of the dialog shown from the
+ // tile.
+ w.setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
w.addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
mDialog.show();
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index ca63ec269bf4..0d11070fd220 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -86,6 +86,7 @@ import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
+import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.QuickStepContract;
@@ -162,6 +163,7 @@ public class ScreenshotView extends FrameLayout implements
private GestureDetector mSwipeDetector;
private SwipeDismissHandler mSwipeDismissHandler;
private InputMonitorCompat mInputMonitor;
+ private InputChannelCompat.InputEventReceiver mInputEventReceiver;
private boolean mShowScrollablePreview;
private String mPackageName = "";
@@ -302,8 +304,8 @@ public class ScreenshotView extends FrameLayout implements
private void startInputListening() {
stopInputListening();
mInputMonitor = new InputMonitorCompat("Screenshot", Display.DEFAULT_DISPLAY);
- mInputMonitor.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance(),
- ev -> {
+ mInputEventReceiver = mInputMonitor.getInputReceiver(
+ Looper.getMainLooper(), Choreographer.getInstance(), ev -> {
if (ev instanceof MotionEvent) {
MotionEvent event = (MotionEvent) ev;
if (event.getActionMasked() == MotionEvent.ACTION_DOWN
@@ -320,6 +322,10 @@ public class ScreenshotView extends FrameLayout implements
mInputMonitor.dispose();
mInputMonitor = null;
}
+ if (mInputEventReceiver != null) {
+ mInputEventReceiver.dispose();
+ mInputEventReceiver = null;
+ }
}
@Override // ViewGroup
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
index 5993f1dee3a7..c29905bc7008 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/NotificationGroupManagerLegacy.java
@@ -384,9 +384,9 @@ public class NotificationGroupManagerLegacy implements
// * Only necessary when all notifications in the group use GROUP_ALERT_SUMMARY
// * Only necessary when at least one notification in the group is on a priority channel
if (group.summary.getSbn().getNotification().getGroupAlertBehavior()
- != Notification.GROUP_ALERT_SUMMARY) {
+ == Notification.GROUP_ALERT_CHILDREN) {
if (SPEW) {
- Log.d(TAG, "getPriorityConversationAlertOverride: summary != GROUP_ALERT_SUMMARY");
+ Log.d(TAG, "getPriorityConversationAlertOverride: summary == GROUP_ALERT_CHILDREN");
}
return null;
}
@@ -529,8 +529,10 @@ public class NotificationGroupManagerLegacy implements
mIsolatedEntries.put(entry.getKey(), entry.getSbn());
if (groupKeysChanged) {
updateSuppression(mGroupMap.get(oldGroupKey));
- updateSuppression(mGroupMap.get(newGroupKey));
}
+ // Always update the suppression of the group from which you're isolated, in case
+ // this entry was or now is the alertOverride for that group.
+ updateSuppression(mGroupMap.get(newGroupKey));
} else if (!wasGroupChild && isGroupChild) {
onEntryBecomingChild(entry);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 73a48c3b5cb0..c14e2f96320c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -130,6 +130,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
+ private static final boolean SPEW = Log.isLoggable(TAG, Log.VERBOSE);
// Usage:
// adb shell setprop persist.debug.nssl true && adb reboot
@@ -3156,6 +3157,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
AnimationEvent event = new AnimationEvent(row, type);
event.headsUpFromBottom = onBottom;
mAnimationEvents.add(event);
+ if (SPEW) {
+ Log.v(TAG, "Generating HUN animation event: "
+ + " isHeadsUp=" + isHeadsUp
+ + " type=" + type
+ + " onBottom=" + onBottom
+ + " row=" + row.getEntry().getKey());
+ }
}
mHeadsUpChangeAnimations.clear();
mAddedHeadsUpChildren.clear();
@@ -4679,7 +4687,22 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
public void generateHeadsUpAnimation(ExpandableNotificationRow row, boolean isHeadsUp) {
- if (mAnimationsEnabled && (isHeadsUp || mHeadsUpGoingAwayAnimationsAllowed)) {
+ final boolean add = mAnimationsEnabled && (isHeadsUp || mHeadsUpGoingAwayAnimationsAllowed);
+ if (SPEW) {
+ Log.v(TAG, "generateHeadsUpAnimation:"
+ + " willAdd=" + add
+ + " isHeadsUp=" + isHeadsUp
+ + " row=" + row.getEntry().getKey());
+ }
+ if (add) {
+ // If we're hiding a HUN we just started showing THIS FRAME, then remove that event,
+ // and do not add the disappear event either.
+ if (!isHeadsUp && mHeadsUpChangeAnimations.remove(new Pair<>(row, true))) {
+ if (SPEW) {
+ Log.v(TAG, "generateHeadsUpAnimation: previous hun appear animation cancelled");
+ }
+ return;
+ }
mHeadsUpChangeAnimations.add(new Pair<>(row, isHeadsUp));
mNeedsAnimation = true;
if (!mIsExpanded && !mWillExpand && !isHeadsUp) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index 83ab8cb80b29..4ba794fe8408 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -6,6 +6,7 @@ import android.animation.ValueAnimator
import android.content.Context
import android.database.ContentObserver
import android.os.Handler
+import android.os.PowerManager
import android.provider.Settings
import android.view.Surface
import android.view.View
@@ -50,9 +51,10 @@ class UnlockedScreenOffAnimationController @Inject constructor(
private val keyguardViewMediatorLazy: dagger.Lazy<KeyguardViewMediator>,
private val keyguardStateController: KeyguardStateController,
private val dozeParameters: dagger.Lazy<DozeParameters>,
- private val globalSettings: GlobalSettings
+ private val globalSettings: GlobalSettings,
+ private val powerManager: PowerManager,
+ private val handler: Handler = Handler()
) : WakefulnessLifecycle.Observer {
- private val handler = Handler()
private lateinit var statusBar: StatusBar
private lateinit var lightRevealScrim: LightRevealScrim
@@ -205,10 +207,18 @@ class UnlockedScreenOffAnimationController @Inject constructor(
lightRevealAnimationPlaying = true
lightRevealAnimator.start()
handler.postDelayed({
- aodUiAnimationPlaying = true
-
- // Show AOD. That'll cause the KeyguardVisibilityHelper to call #animateInKeyguard.
- statusBar.notificationPanelViewController.showAodUi()
+ // Only run this callback if the device is sleeping (not interactive). This callback
+ // is removed in onStartedWakingUp, but since that event is asynchronously
+ // dispatched, a race condition could make it possible for this callback to be run
+ // as the device is waking up. That results in the AOD UI being shown while we wake
+ // up, with unpredictable consequences.
+ if (!powerManager.isInteractive) {
+ aodUiAnimationPlaying = true
+
+ // Show AOD. That'll cause the KeyguardVisibilityHelper to call
+ // #animateInKeyguard.
+ statusBar.notificationPanelViewController.showAodUi()
+ }
}, (ANIMATE_IN_KEYGUARD_DELAY * animatorDurationScale).toLong())
} else {
decidedToAnimateGoingToSleep = false
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
index 634763866d02..856bbeaa85e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
@@ -25,15 +25,14 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
-import android.content.Context;
+import android.content.res.Resources;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -53,14 +52,14 @@ import java.io.StringWriter;
public class FeatureFlagManagerTest extends SysuiTestCase {
FeatureFlagManager mFeatureFlagManager;
- @Mock private Context mContext;
@Mock private DumpManager mDumpManager;
+ @Mock private Resources mResources;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mFeatureFlagManager = new FeatureFlagManager(mDumpManager);
+ mFeatureFlagManager = new FeatureFlagManager(mDumpManager, mResources);
}
@After
@@ -70,6 +69,24 @@ public class FeatureFlagManagerTest extends SysuiTestCase {
verifyNoMoreInteractions(mDumpManager);
}
+
+ @Test
+ public void testSimpleFlag() {
+ BooleanFlag flagA = new BooleanFlag(100, false);
+ BooleanFlag flagB = new BooleanFlag(200, true);
+
+ assertThat(mFeatureFlagManager.isEnabled(flagA)).isFalse();
+ assertThat(mFeatureFlagManager.isEnabled(flagB)).isTrue();
+ }
+
+ @Test
+ public void testResourceOverride() {
+ when(mResources.getBoolean(1)).thenReturn(true);
+ BooleanFlag flag = new BooleanFlag(100, false, 1);
+
+ assertThat(mFeatureFlagManager.isEnabled(flag)).isTrue();
+ }
+
@Test
public void testIsEnabled() {
mFeatureFlagManager.setEnabled(1, true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
index 1be27da27d25..6d170b673cc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationGroupManagerLegacyTest.java
@@ -178,20 +178,68 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
}
/**
+ * Helper for testing various sibling counts
+ */
+ private void helpTestAlertOverrideWithSiblings(int numSiblings) {
+ helpTestAlertOverride(
+ /* numSiblings */ numSiblings,
+ /* summaryAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* childAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* siblingAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* expectAlertOverride */ true);
+ }
+
+ @Test
+ public void testAlertOverrideWithParentAlertAll() {
+ // tests that summary can have GROUP_ALERT_ALL and this still works
+ helpTestAlertOverride(
+ /* numSiblings */ 1,
+ /* summaryAlert */ Notification.GROUP_ALERT_ALL,
+ /* childAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* siblingAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* expectAlertOverride */ true);
+ }
+
+ @Test
+ public void testAlertOverrideWithParentAlertChild() {
+ // Tests that if the summary alerts CHILDREN, there's no alertOverride
+ helpTestAlertOverride(
+ /* numSiblings */ 1,
+ /* summaryAlert */ Notification.GROUP_ALERT_CHILDREN,
+ /* childAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* siblingAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* expectAlertOverride */ false);
+ }
+
+ @Test
+ public void testAlertOverrideWithChildrenAlertAll() {
+ // Tests that if the children alert ALL, there's no alertOverride
+ helpTestAlertOverride(
+ /* numSiblings */ 1,
+ /* summaryAlert */ Notification.GROUP_ALERT_SUMMARY,
+ /* childAlert */ Notification.GROUP_ALERT_ALL,
+ /* siblingAlert */ Notification.GROUP_ALERT_ALL,
+ /* expectAlertOverride */ false);
+ }
+
+ /**
* This tests, for a group with a priority entry and the given number of siblings, that:
* 1) the priority entry is identified as the alertOverride for the group
* 2) the onAlertOverrideChanged method is called at that time
* 3) when the priority entry is removed, these are reversed
*/
- private void helpTestAlertOverrideWithSiblings(int numSiblings) {
- int groupAlert = Notification.GROUP_ALERT_SUMMARY;
+ private void helpTestAlertOverride(int numSiblings,
+ @Notification.GroupAlertBehavior int summaryAlert,
+ @Notification.GroupAlertBehavior int childAlert,
+ @Notification.GroupAlertBehavior int siblingAlert,
+ boolean expectAlertOverride) {
// Create entries in an order so that the priority entry can be deemed the newest child.
NotificationEntry[] siblings = new NotificationEntry[numSiblings];
for (int i = 0; i < numSiblings; i++) {
- siblings[i] = mGroupTestHelper.createChildNotification(groupAlert);
+ siblings[i] = mGroupTestHelper.createChildNotification(siblingAlert);
}
- NotificationEntry priorityEntry = mGroupTestHelper.createChildNotification(groupAlert);
- NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(groupAlert);
+ NotificationEntry priorityEntry = mGroupTestHelper.createChildNotification(childAlert);
+ NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(summaryAlert);
// The priority entry is an important conversation.
when(mPeopleNotificationIdentifier.getPeopleNotificationType(eq(priorityEntry)))
@@ -208,6 +256,14 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
}
mGroupManager.onEntryAdded(priorityEntry);
+ if (!expectAlertOverride) {
+ // Test expectation is that there will NOT be an alert, so verify that!
+ NotificationGroup summaryGroup =
+ mGroupManager.getGroupForSummary(summaryEntry.getSbn());
+ assertNull(summaryGroup.alertOverride);
+ return;
+ }
+
// Verify that the summary group has the priority child as its alertOverride
NotificationGroup summaryGroup = mGroupManager.getGroupForSummary(summaryEntry.getSbn());
assertEquals(priorityEntry, summaryGroup.alertOverride);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
index a8a33dabf1aa..fb8c9858be0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.phone
import android.animation.Animator
+import android.os.Handler
+import android.os.PowerManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.View
@@ -28,13 +30,20 @@ import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.StatusBarStateControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.settings.GlobalSettings
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.mockingDetails
+import org.mockito.Mockito.never
import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
@@ -52,13 +61,19 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
@Mock
private lateinit var globalSettings: GlobalSettings
@Mock
- private lateinit var statusbar: StatusBar
+ private lateinit var statusBar: StatusBar
+ @Mock
+ private lateinit var notificationPanelViewController: NotificationPanelViewController
@Mock
private lateinit var lightRevealScrim: LightRevealScrim
@Mock
private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock
private lateinit var statusBarStateController: StatusBarStateControllerImpl
+ @Mock
+ private lateinit var powerManager: PowerManager
+ @Mock
+ private lateinit var handler: Handler
@Before
fun setUp() {
@@ -71,9 +86,24 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
keyguardStateController,
dagger.Lazy<DozeParameters> { dozeParameters },
- globalSettings
+ globalSettings,
+ powerManager,
+ handler = handler
)
- controller.initialize(statusbar, lightRevealScrim)
+ controller.initialize(statusBar, lightRevealScrim)
+ `when`(statusBar.notificationPanelViewController).thenReturn(
+ notificationPanelViewController)
+
+ // Screen off does not run if the panel is expanded, so we should say it's collapsed to test
+ // screen off.
+ `when`(notificationPanelViewController.isFullyCollapsed).thenReturn(true)
+ }
+
+ @After
+ fun cleanUp() {
+ // Tell the screen off controller to cancel the animations and clean up its state, or
+ // subsequent tests will act unpredictably as the animator continues running.
+ controller.onStartedWakingUp()
}
@Test
@@ -89,4 +119,51 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
listener.value.onAnimationEnd(null)
Mockito.verify(animator).setListener(null)
}
+
+ /**
+ * The AOD UI is shown during the screen off animation, after a delay to allow the light reveal
+ * animation to start. If the device is woken up during the screen off, we should *never* do
+ * this.
+ *
+ * This test confirms that we do show the AOD UI when the device is not woken up
+ * (PowerManager#isInteractive = false).
+ */
+ @Test
+ fun testAodUiShownIfNotInteractive() {
+ `when`(dozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true)
+ `when`(powerManager.isInteractive).thenReturn(false)
+
+ val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java)
+ controller.onStartedGoingToSleep()
+
+ verify(handler).postDelayed(callbackCaptor.capture(), anyLong())
+
+ callbackCaptor.value.run()
+
+ verify(notificationPanelViewController, times(1)).showAodUi()
+ }
+
+ /**
+ * The AOD UI is shown during the screen off animation, after a delay to allow the light reveal
+ * animation to start. If the device is woken up during the screen off, we should *never* do
+ * this.
+ *
+ * This test confirms that we do not show the AOD UI when the device is woken up during screen
+ * off (PowerManager#isInteractive = true).
+ */
+ @Test
+ fun testAodUiNotShownIfInteractive() {
+ `when`(dozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true)
+ `when`(powerManager.isInteractive).thenReturn(true)
+
+ val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java)
+ controller.onStartedGoingToSleep()
+
+ mockingDetails(handler).printInvocations()
+
+ verify(handler).postDelayed(callbackCaptor.capture(), anyLong())
+ callbackCaptor.value.run()
+
+ verify(notificationPanelViewController, never()).showAodUi()
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 15a92dcf26b7..ecfa1aaf49dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -1275,6 +1275,22 @@ public class BubblesTest extends SysuiTestCase {
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
}
+ @Test
+ public void testStackViewOnBackPressed_updatesBubbleDataExpandState() {
+ mBubbleController.updateBubble(mBubbleEntry);
+
+ // Expand the stack
+ mBubbleData.setExpanded(true);
+ assertStackExpanded();
+
+ // Hit back
+ BubbleStackView stackView = mBubbleController.getStackView();
+ stackView.onBackPressed();
+
+ // Make sure we're collapsed
+ assertStackCollapsed();
+ }
+
/** Creates a bubble using the userId and package. */
private Bubble createBubble(int userId, String pkg) {
final UserHandle userHandle = new UserHandle(userId);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index 43b181ed3ab9..6207b76e840f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -1091,6 +1091,22 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
assertSysuiStates(false /* stackExpanded */, false /* mangeMenuExpanded */);
}
+ @Test
+ public void testStackViewOnBackPressed_updatesBubbleDataExpandState() {
+ mBubbleController.updateBubble(mBubbleEntry);
+
+ // Expand the stack
+ mBubbleData.setExpanded(true);
+ assertStackExpanded();
+
+ // Hit back
+ BubbleStackView stackView = mBubbleController.getStackView();
+ stackView.onBackPressed();
+
+ // Make sure we're collapsed
+ assertStackCollapsed();
+ }
+
/**
* Sets the bubble metadata flags for this entry. These flags are normally set by
* NotificationManagerService when the notification is sent, however, these tests do not
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index cbc2c0c6c8ac..22dd2c05c157 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -50,8 +50,6 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.MathUtils;
-import android.util.MutableFloat;
-import android.util.MutableInt;
import android.util.Slog;
import android.util.TimeUtils;
import android.view.Display;
@@ -1325,7 +1323,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Animate the screen brightness when the screen is on or dozing.
// Skip the animation when the screen is off or suspended or transition to/from VR.
- boolean brightnessAdjusted = false;
if (!mPendingScreenOff) {
if (mSkipScreenOnBrightnessRamp) {
if (state == Display.STATE_ON) {
@@ -1413,19 +1410,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// slider event so notify as if the system changed the brightness.
userInitiatedChange = false;
}
- notifyBrightnessTrackerChanged(brightnessState, userInitiatedChange,
+ notifyBrightnessChanged(brightnessState, userInitiatedChange,
hadUserBrightnessPoint);
}
// We save the brightness info *after* the brightness setting has been changed and
// adjustments made so that the brightness info reflects the latest value.
- brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
+ saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
} else {
- brightnessAdjusted = saveBrightnessInfo(getScreenBrightnessSetting());
- }
-
- if (brightnessAdjusted) {
- postBrightnessChangeRunnable();
+ saveBrightnessInfo(getScreenBrightnessSetting());
}
// Log any changes to what is currently driving the brightness setting.
@@ -1541,50 +1534,31 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
public BrightnessInfo getBrightnessInfo() {
synchronized (mCachedBrightnessInfo) {
return new BrightnessInfo(
- mCachedBrightnessInfo.brightness.value,
- mCachedBrightnessInfo.adjustedBrightness.value,
- mCachedBrightnessInfo.brightnessMin.value,
- mCachedBrightnessInfo.brightnessMax.value,
- mCachedBrightnessInfo.hbmMode.value,
- mCachedBrightnessInfo.hbmTransitionPoint.value);
+ mCachedBrightnessInfo.brightness,
+ mCachedBrightnessInfo.adjustedBrightness,
+ mCachedBrightnessInfo.brightnessMin,
+ mCachedBrightnessInfo.brightnessMax,
+ mCachedBrightnessInfo.hbmMode,
+ mCachedBrightnessInfo.highBrightnessTransitionPoint);
}
}
- private boolean saveBrightnessInfo(float brightness) {
- return saveBrightnessInfo(brightness, brightness);
+ private void saveBrightnessInfo(float brightness) {
+ saveBrightnessInfo(brightness, brightness);
}
- private boolean saveBrightnessInfo(float brightness, float adjustedBrightness) {
+ private void saveBrightnessInfo(float brightness, float adjustedBrightness) {
synchronized (mCachedBrightnessInfo) {
- boolean changed = false;
-
- changed |=
- mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightness,
- brightness);
- changed |=
- mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.adjustedBrightness,
- adjustedBrightness);
- changed |=
- mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMin,
- mHbmController.getCurrentBrightnessMin());
- changed |=
- mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.brightnessMax,
- mHbmController.getCurrentBrightnessMax());
- changed |=
- mCachedBrightnessInfo.checkAndSetInt(mCachedBrightnessInfo.hbmMode,
- mHbmController.getHighBrightnessMode());
- changed |=
- mCachedBrightnessInfo.checkAndSetFloat(mCachedBrightnessInfo.hbmTransitionPoint,
- mHbmController.getTransitionPoint());
-
- return changed;
+ mCachedBrightnessInfo.brightness = brightness;
+ mCachedBrightnessInfo.adjustedBrightness = adjustedBrightness;
+ mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin();
+ mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax();
+ mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode();
+ mCachedBrightnessInfo.highBrightnessTransitionPoint =
+ mHbmController.getTransitionPoint();
}
}
- void postBrightnessChangeRunnable() {
- mHandler.post(mOnBrightnessChangeRunnable);
- }
-
private HighBrightnessModeController createHbmControllerLocked() {
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
@@ -1597,7 +1571,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
() -> {
sendUpdatePowerStateLocked();
- postBrightnessChangeRunnable();
+ mHandler.post(mOnBrightnessChangeRunnable);
// TODO(b/192258832): Switch the HBMChangeCallback to a listener pattern.
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.update();
@@ -2099,7 +2073,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private void setCurrentScreenBrightness(float brightnessValue) {
if (brightnessValue != mCurrentScreenBrightnessSetting) {
mCurrentScreenBrightnessSetting = brightnessValue;
- postBrightnessChangeRunnable();
+ mHandler.post(mOnBrightnessChangeRunnable);
}
}
@@ -2151,7 +2125,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return true;
}
- private void notifyBrightnessTrackerChanged(float brightness, boolean userInitiated,
+ private void notifyBrightnessChanged(float brightness, boolean userInitiated,
boolean hadUserDataPoint) {
final float brightnessInNits = convertToNits(brightness);
if (mPowerRequest.useAutoBrightness && brightnessInNits >= 0.0f
@@ -2262,17 +2236,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
pw.println(" mColorFadeEnabled=" + mColorFadeEnabled);
synchronized (mCachedBrightnessInfo) {
- pw.println(" mCachedBrightnessInfo.brightness=" +
- mCachedBrightnessInfo.brightness.value);
+ pw.println(" mCachedBrightnessInfo.brightness=" + mCachedBrightnessInfo.brightness);
pw.println(" mCachedBrightnessInfo.adjustedBrightness=" +
- mCachedBrightnessInfo.adjustedBrightness.value);
+ mCachedBrightnessInfo.adjustedBrightness);
pw.println(" mCachedBrightnessInfo.brightnessMin=" +
- mCachedBrightnessInfo.brightnessMin.value);
+ mCachedBrightnessInfo.brightnessMin);
pw.println(" mCachedBrightnessInfo.brightnessMax=" +
- mCachedBrightnessInfo.brightnessMax.value);
- pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode.value);
- pw.println(" mCachedBrightnessInfo.hbmTransitionPoint=" +
- mCachedBrightnessInfo.hbmTransitionPoint.value);
+ mCachedBrightnessInfo.brightnessMax);
+ pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode);
+ pw.println(" mCachedBrightnessInfo.highBrightnessTransitionPoint=" +
+ mCachedBrightnessInfo.highBrightnessTransitionPoint);
}
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
@@ -2690,31 +2663,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
static class CachedBrightnessInfo {
- public MutableFloat brightness = new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
- public MutableFloat adjustedBrightness =
- new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
- public MutableFloat brightnessMin =
- new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
- public MutableFloat brightnessMax =
- new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
- public MutableInt hbmMode = new MutableInt(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
- public MutableFloat hbmTransitionPoint =
- new MutableFloat(HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID);
-
- public boolean checkAndSetFloat(MutableFloat mf, float f) {
- if (mf.value != f) {
- mf.value = f;
- return true;
- }
- return false;
- }
-
- public boolean checkAndSetInt(MutableInt mi, int i) {
- if (mi.value != i) {
- mi.value = i;
- return true;
- }
- return false;
- }
+ public float brightness;
+ public float adjustedBrightness;
+ public float brightnessMin;
+ public float brightnessMax;
+ public int hbmMode;
+ public float highBrightnessTransitionPoint;
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index a4fbb504beb1..f580bd078a0d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2730,9 +2730,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
boolean isResizeable() {
+ return isResizeable(/* checkPictureInPictureSupport */ true);
+ }
+
+ boolean isResizeable(boolean checkPictureInPictureSupport) {
return mAtmService.mForceResizableActivities
|| ActivityInfo.isResizeableMode(info.resizeMode)
- || info.supportsPictureInPicture()
+ || (info.supportsPictureInPicture() && checkPictureInPictureSupport)
// If the activity can be embedded, it should inherit the bounds of task fragment.
|| isEmbedded();
}
@@ -6921,7 +6925,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
void prepareSurfaces() {
- final boolean show = isVisible() || isAnimating(TRANSITION | PARENTS,
+ final boolean show = isVisible() || isAnimating(PARENTS,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS);
if (mSurfaceControl != null) {
@@ -7691,10 +7695,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// orientation with insets applied.
return;
}
- // Activity should be resizable if the task is.
+ // Not using Task#isResizeable() or ActivityRecord#isResizeable() directly because app
+ // compatibility testing showed that android:supportsPictureInPicture="true" alone is not
+ // sufficient signal for not letterboxing an app.
+ // TODO(214602463): Remove multi-window check since orientation and aspect ratio
+ // restrictions should always be applied in multi-window.
final boolean isResizeable = task != null
- ? task.isResizeable() || isResizeable()
- : isResizeable();
+ // Activity should be resizable if the task is.
+ ? task.isResizeable(/* checkPictureInPictureSupport */ false)
+ || isResizeable(/* checkPictureInPictureSupport */ false)
+ : isResizeable(/* checkPictureInPictureSupport */ false);
if (WindowConfiguration.inMultiWindowMode(windowingMode) && isResizeable) {
// Ignore orientation request for resizable apps in multi window.
return;
@@ -8223,8 +8233,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final float maxAspectRatio = info.getMaxAspectRatio();
final Task rootTask = getRootTask();
final float minAspectRatio = getMinAspectRatio();
+ // Not using ActivityRecord#isResizeable() directly because app compatibility testing
+ // showed that android:supportsPictureInPicture="true" alone is not sufficient signal for
+ // not letterboxing an app.
+ // TODO(214602463): Remove multi-window check since orientation and aspect ratio
+ // restrictions should always be applied in multi-window.
if (task == null || rootTask == null
- || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
+ || (inMultiWindowMode() && isResizeable(/* checkPictureInPictureSupport */ false)
&& !fixedOrientationLetterboxed)
|| (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1)
|| isInVrUiMode(getConfiguration())) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 40549548da62..42c6dd43ebce 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1067,8 +1067,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
- mTransitionController.registerLegacyListener(
- mWmService.mActivityManagerAppTransitionNotifier);
mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
mAppTransitionController = new AppTransitionController(mWmService, this);
mUnknownAppVisibilityController = new UnknownAppVisibilityController(mWmService, this);
@@ -4124,9 +4122,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* which controls the visibility and animation of the input method window.
*/
void updateImeInputAndControlTarget(WindowState target) {
- if (target != null && target.mActivityRecord != null) {
- target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
- }
if (mImeInputTarget != target) {
ProtoLog.i(WM_DEBUG_IME, "setInputMethodInputTarget %s", target);
setImeInputTarget(target);
@@ -4134,6 +4129,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
.getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
updateImeControlTarget();
}
+ // Unfreeze IME insets after the new target updated, in case updateAboveInsetsState may
+ // deliver unrelated IME insets change to the non-IME requester.
+ if (target != null && target.mActivityRecord != null) {
+ target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
+ }
}
void updateImeControlTarget() {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 3d9061b63ff9..d69d32effc76 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3315,6 +3315,7 @@ public class DisplayPolicy {
}
void release() {
+ mDisplayContent.mTransitionController.unregisterLegacyListener(mAppTransitionListener);
mHandler.post(mGestureNavigationSettingsObserver::unregister);
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index a8dd26e51911..632c63708549 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2731,10 +2731,14 @@ class Task extends TaskFragment {
}
boolean isResizeable() {
+ return isResizeable(/* checkPictureInPictureSupport */ true);
+ }
+
+ boolean isResizeable(boolean checkPictureInPictureSupport) {
final boolean forceResizable = mAtmService.mForceResizableActivities
&& getActivityType() == ACTIVITY_TYPE_STANDARD;
return forceResizable || ActivityInfo.isResizeableMode(mResizeMode)
- || mSupportsPictureInPicture;
+ || (mSupportsPictureInPicture && checkPictureInPictureSupport);
}
/**
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index e05457010df8..929ec3b929b2 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -430,6 +430,10 @@ class TransitionController {
mLegacyListeners.add(listener);
}
+ void unregisterLegacyListener(WindowManagerInternal.AppTransitionListener listener) {
+ mLegacyListeners.remove(listener);
+ }
+
void dispatchLegacyAppTransitionPending() {
for (int i = 0; i < mLegacyListeners.size(); ++i) {
mLegacyListeners.get(i).onAppTransitionPendingLocked();
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 42766bdb0732..6970c7942a50 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -137,6 +137,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
void setWindowManager(WindowManagerService wms) {
mTransitionController = new TransitionController(mService, wms.mTaskSnapshotController);
+ mTransitionController.registerLegacyListener(wms.mActivityManagerAppTransitionNotifier);
}
TransitionController getTransitionController() {