diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index b117a9afb6f5d..3bf9ca0441417 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -16,9 +16,7 @@
package android.preference;
-import android.Manifest;
import android.annotation.NonNull;
-import android.annotation.RequiresPermission;
import android.app.NotificationManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
@@ -37,7 +35,6 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.preference.VolumePreference.VolumeStore;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Settings.System;
@@ -47,7 +44,6 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.os.SomeArgs;
import java.util.concurrent.TimeUnit;
@@ -119,6 +115,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
private final int mMaxStreamVolume;
private boolean mAffectedByRingerMode;
private boolean mNotificationOrRing;
+ private final boolean mNotifAliasRing;
private final Receiver mReceiver = new Receiver();
private Handler mHandler;
@@ -161,7 +158,6 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
this(context, streamType, defaultUri, callback, true /* playSample */);
}
- @RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
public SeekBarVolumizer(
Context context,
int streamType,
@@ -184,6 +180,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
if (mNotificationOrRing) {
mRingerMode = mAudioManager.getRingerModeInternal();
}
+ mNotifAliasRing = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types);
mZenMode = mNotificationManager.getZenMode();
if (hasAudioProductStrategies()) {
@@ -290,9 +288,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
* so that when user attempts to slide the notification seekbar out of vibrate the
* seekbar doesn't wrongly snap back to 0 when the streams aren't aliased
*/
- if (!DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false)
- || mStreamType == AudioManager.STREAM_RING
+ if (mNotifAliasRing || mStreamType == AudioManager.STREAM_RING
|| (mStreamType == AudioManager.STREAM_NOTIFICATION && mMuted)) {
mSeekBar.setProgress(0, true);
}
@@ -369,9 +365,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
// set the time of stop volume
if ((mStreamType == AudioManager.STREAM_VOICE_CALL
|| mStreamType == AudioManager.STREAM_RING
- || (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false)
- && mStreamType == AudioManager.STREAM_NOTIFICATION)
+ || (!mNotifAliasRing && mStreamType == AudioManager.STREAM_NOTIFICATION)
|| mStreamType == AudioManager.STREAM_ALARM)) {
sStopVolumeTime = java.lang.System.currentTimeMillis();
}
@@ -650,10 +644,8 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba
}
private void updateVolumeSlider(int streamType, int streamValue) {
- final boolean streamMatch = !DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false)
- && mNotificationOrRing ? isNotificationOrRing(streamType) :
- streamType == mStreamType;
+ final boolean streamMatch = mNotifAliasRing && mNotificationOrRing
+ ? isNotificationOrRing(streamType) : streamType == mStreamType;
if (mSeekBar != null && streamMatch && streamValue != -1) {
final boolean muted = mAudioManager.isStreamMute(mStreamType)
|| streamValue == 0;
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 4f7f8ba2b45c6..b916878ff4612 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -561,11 +561,6 @@ public final class SystemUiDeviceConfigFlags {
public static final String TASK_MANAGER_SHOW_USER_VISIBLE_JOBS =
"task_manager_show_user_visible_jobs";
- /**
- * (boolean) Whether to show notification volume control slider separate from ring.
- */
- public static final String VOLUME_SEPARATE_NOTIFICATION = "volume_separate_notification";
-
/**
* (boolean) Whether the clipboard overlay is enabled.
*/
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e949b19769223..1c2f4ee1050e0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2018,6 +2018,10 @@
STREAM_MUSIC as if it's on TV platform. -->
false
+
+ true
+
7
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 74f7333e8e9b0..db9d979ed6a60 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -278,6 +278,7 @@
+
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 54aa3516d867f..0f81b0b8d6e07 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -791,13 +791,13 @@ private class AnimatedDialog(
// Move the drawing of the source in the overlay of this dialog, then animate. We trigger a
// one-off synchronization to make sure that this is done in sync between the two different
// windows.
+ controller.startDrawingInOverlayOf(decorView)
synchronizeNextDraw(
then = {
isSourceDrawnInDialog = true
maybeStartLaunchAnimation()
}
)
- controller.startDrawingInOverlayOf(decorView)
}
/**
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
index 0028d13ffd5e1..dfac02d99c4df 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
@@ -195,14 +195,16 @@ open class GhostedViewLaunchAnimatorController @JvmOverloads constructor(
backgroundDrawable = WrappedDrawable(background)
backgroundView?.background = backgroundDrawable
+ // Delay the calls to `ghostedView.setVisibility()` during the animation. This must be
+ // called before `GhostView.addGhost()` is called because the latter will change the
+ // *transition* visibility, which won't be blocked and will affect the normal View
+ // visibility that is saved by `setShouldBlockVisibilityChanges()` for a later restoration.
+ (ghostedView as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
+
// Create a ghost of the view that will be moving and fading out. This allows to fade out
// the content before fading out the background.
ghostView = GhostView.addGhost(ghostedView, launchContainer)
- // The ghost was just created, so ghostedView is currently invisible. We need to make sure
- // that it stays invisible as long as we are animating.
- (ghostedView as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
-
val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX
matrix.getValues(initialGhostViewMatrixValues)
@@ -297,14 +299,19 @@ open class GhostedViewLaunchAnimatorController @JvmOverloads constructor(
backgroundDrawable?.wrapped?.alpha = startBackgroundAlpha
GhostView.removeGhost(ghostedView)
- (ghostedView as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
launchContainerOverlay.remove(backgroundView)
- // Make sure that the view is considered VISIBLE by accessibility by first making it
- // INVISIBLE then VISIBLE (see b/204944038#comment17 for more info).
- ghostedView.visibility = View.INVISIBLE
- ghostedView.visibility = View.VISIBLE
- ghostedView.invalidate()
+ if (ghostedView is LaunchableView) {
+ // Restore the ghosted view visibility.
+ ghostedView.setShouldBlockVisibilityChanges(false)
+ } else {
+ // Make the ghosted view visible. We ensure that the view is considered VISIBLE by
+ // accessibility by first making it INVISIBLE then VISIBLE (see b/204944038#comment17
+ // for more info).
+ ghostedView.visibility = View.INVISIBLE
+ ghostedView.visibility = View.VISIBLE
+ ghostedView.invalidate()
+ }
}
companion object {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index 67b59e0e9928e..774255be4007a 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -21,15 +21,19 @@ import android.view.View
/** A view that can expand/launch into an app or a dialog. */
interface LaunchableView {
/**
- * Set whether this view should block/postpone all visibility changes. This ensures that this
- * view:
+ * Set whether this view should block/postpone all calls to [View.setVisibility]. This ensures
+ * that this view:
* - remains invisible during the launch animation given that it is ghosted and already drawn
* somewhere else.
* - remains invisible as long as a dialog expanded from it is shown.
* - restores its expected visibility once the dialog expanded from it is dismissed.
*
- * Note that when this is set to true, both the [normal][android.view.View.setVisibility] and
- * [transition][android.view.View.setTransitionVisibility] visibility changes must be blocked.
+ * When `setShouldBlockVisibilityChanges(false)` is called, then visibility of the View should
+ * be restored to its expected value, i.e. it should have the visibility of the last call to
+ * `View.setVisibility()` that was made after `setShouldBlockVisibilityChanges(true)`, if any,
+ * or the original view visibility otherwise.
+ *
+ * Note that calls to [View.setTransitionVisibility] shouldn't be blocked.
*
* @param block whether we should block/postpone all calls to `setVisibility` and
* `setTransitionVisibility`.
@@ -46,27 +50,31 @@ class LaunchableViewDelegate(
* super.setVisibility(visibility).
*/
private val superSetVisibility: (Int) -> Unit,
-
- /**
- * The lambda that should set the actual transition visibility of [view], usually by calling
- * super.setTransitionVisibility(visibility).
- */
- private val superSetTransitionVisibility: (Int) -> Unit,
-) {
+) : LaunchableView {
private var blockVisibilityChanges = false
private var lastVisibility = view.visibility
/** Call this when [LaunchableView.setShouldBlockVisibilityChanges] is called. */
- fun setShouldBlockVisibilityChanges(block: Boolean) {
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
if (block == blockVisibilityChanges) {
return
}
blockVisibilityChanges = block
if (block) {
+ // Save the current visibility for later.
lastVisibility = view.visibility
} else {
- superSetVisibility(lastVisibility)
+ // Restore the visibility. To avoid accessibility issues, we change the visibility twice
+ // which makes sure that we trigger a visibility flag change (see b/204944038#comment17
+ // for more info).
+ if (lastVisibility == View.VISIBLE) {
+ superSetVisibility(View.INVISIBLE)
+ superSetVisibility(View.VISIBLE)
+ } else {
+ superSetVisibility(View.VISIBLE)
+ superSetVisibility(lastVisibility)
+ }
}
}
@@ -79,16 +87,4 @@ class LaunchableViewDelegate(
superSetVisibility(visibility)
}
-
- /** Call this when [View.setTransitionVisibility] is called. */
- fun setTransitionVisibility(visibility: Int) {
- if (blockVisibilityChanges) {
- // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
- // the transition visibility separately from the normal visibility.
- lastVisibility = visibility
- return
- }
-
- superSetTransitionVisibility(visibility)
- }
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
index 964ef8c880982..46d5a5c0af8c0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt
@@ -34,23 +34,29 @@ internal constructor(
override val sourceIdentity: Any = source
override fun startDrawingInOverlayOf(viewGroup: ViewGroup) {
+ // Delay the calls to `source.setVisibility()` during the animation. This must be called
+ // before `GhostView.addGhost()` is called because the latter will change the *transition*
+ // visibility, which won't be blocked and will affect the normal View visibility that is
+ // saved by `setShouldBlockVisibilityChanges()` for a later restoration.
+ (source as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
+
// Create a temporary ghost of the source (which will make it invisible) and add it
// to the host dialog.
GhostView.addGhost(source, viewGroup)
-
- // The ghost of the source was just created, so the source is currently invisible.
- // We need to make sure that it stays invisible as long as the dialog is shown or
- // animating.
- (source as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
}
override fun stopDrawingInOverlay() {
// Note: here we should remove the ghost from the overlay, but in practice this is
- // already done by the launch controllers created below.
+ // already done by the launch controller created below.
- // Make sure we allow the source to change its visibility again.
- (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
- source.visibility = View.VISIBLE
+ if (source is LaunchableView) {
+ // Make sure we allow the source to change its visibility again and restore its previous
+ // value.
+ source.setShouldBlockVisibilityChanges(false)
+ } else {
+ // We made the source invisible earlier, so let's make it visible again.
+ source.visibility = View.VISIBLE
+ }
}
override fun createLaunchController(): LaunchAnimator.Controller {
@@ -67,10 +73,14 @@ internal constructor(
override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
delegate.onLaunchAnimationEnd(isExpandingFullyAbove)
- // We hide the source when the dialog is showing. We will make this view
- // visible again when dismissing the dialog. This does nothing if the source
- // implements [LaunchableView], as it's already INVISIBLE in that case.
- source.visibility = View.INVISIBLE
+ // At this point the view visibility is restored by the delegate, so we delay the
+ // visibility changes again and make it invisible while the dialog is shown.
+ if (source is LaunchableView) {
+ source.setShouldBlockVisibilityChanges(true)
+ source.setTransitionVisibility(View.INVISIBLE)
+ } else {
+ source.visibility = View.INVISIBLE
+ }
}
}
}
@@ -90,13 +100,15 @@ internal constructor(
}
override fun onExitAnimationCancelled() {
- // Make sure we allow the source to change its visibility again.
- (source as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
-
- // If the view is invisible it's probably because of us, so we make it visible
- // again.
- if (source.visibility == View.INVISIBLE) {
- source.visibility = View.VISIBLE
+ if (source is LaunchableView) {
+ // Make sure we allow the source to change its visibility again.
+ source.setShouldBlockVisibilityChanges(false)
+ } else {
+ // If the view is invisible it's probably because of us, so we make it visible
+ // again.
+ if (source.visibility == View.INVISIBLE) {
+ source.visibility = View.VISIBLE
+ }
}
}
diff --git a/packages/SystemUI/res/drawable/ic_ring_volume.xml b/packages/SystemUI/res/drawable/ic_ring_volume.xml
deleted file mode 100644
index 343fe5d4cb698..0000000000000
--- a/packages/SystemUI/res/drawable/ic_ring_volume.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_ring_volume_off.xml b/packages/SystemUI/res/drawable/ic_ring_volume_off.xml
deleted file mode 100644
index 74f30d1a44d25..0000000000000
--- a/packages/SystemUI/res/drawable/ic_ring_volume_off.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
diff --git a/packages/SystemUI/res/drawable/ic_speaker_mute.xml b/packages/SystemUI/res/drawable/ic_speaker_mute.xml
deleted file mode 100644
index 4e402cf530e4b..0000000000000
--- a/packages/SystemUI/res/drawable/ic_speaker_mute.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_speaker_on.xml b/packages/SystemUI/res/drawable/ic_speaker_on.xml
deleted file mode 100644
index 2a90e051b83bc..0000000000000
--- a/packages/SystemUI/res/drawable/ic_speaker_on.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index a565988c14ade..d689828764489 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -148,9 +148,4 @@
-
\ No newline at end of file
diff --git a/packages/SystemUI/res/xml/qs_header.xml b/packages/SystemUI/res/xml/qs_header.xml
index eca2b2acb0792..d97031f35d6bd 100644
--- a/packages/SystemUI/res/xml/qs_header.xml
+++ b/packages/SystemUI/res/xml/qs_header.xml
@@ -56,13 +56,9 @@
@@ -87,39 +83,27 @@
-
-
-
-
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
index f95a8ee89a2c0..7bbfec7df9d80 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableImageView.kt
@@ -28,7 +28,6 @@ class LaunchableImageView : ImageView, LaunchableView {
LaunchableViewDelegate(
this,
superSetVisibility = { super.setVisibility(it) },
- superSetTransitionVisibility = { super.setTransitionVisibility(it) },
)
constructor(context: Context?) : super(context)
@@ -53,8 +52,4 @@ class LaunchableImageView : ImageView, LaunchableView {
override fun setVisibility(visibility: Int) {
delegate.setVisibility(visibility)
}
-
- override fun setTransitionVisibility(visibility: Int) {
- delegate.setTransitionVisibility(visibility)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
index c27b82aeeb47c..ddde6280f3a2b 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/view/LaunchableLinearLayout.kt
@@ -28,7 +28,6 @@ class LaunchableLinearLayout : LinearLayout, LaunchableView {
LaunchableViewDelegate(
this,
superSetVisibility = { super.setVisibility(it) },
- superSetTransitionVisibility = { super.setTransitionVisibility(it) },
)
constructor(context: Context?) : super(context)
@@ -53,8 +52,4 @@ class LaunchableLinearLayout : LinearLayout, LaunchableView {
override fun setVisibility(visibility: Int) {
delegate.setVisibility(visibility)
}
-
- override fun setTransitionVisibility(visibility: Int) {
- delegate.setTransitionVisibility(visibility)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 7cf63f678c1d8..1da30ade951bb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -36,7 +36,6 @@ public interface QSHost {
void removeCallback(Callback callback);
void removeTile(String tileSpec);
void removeTiles(Collection specs);
- void unmarkTileAsAutoAdded(String tileSpec);
int indexOf(String tileSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index cad296b671b30..100853caa2d7e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -427,11 +427,6 @@ public class QSTileHost implements QSHost, Tunable, PluginListener, P
mMainExecutor.execute(() -> changeTileSpecs(tileSpecs -> tileSpecs.removeAll(specs)));
}
- @Override
- public void unmarkTileAsAutoAdded(String spec) {
- if (mAutoTiles != null) mAutoTiles.unmarkTileAsAutoAdded(spec);
- }
-
/**
* Add a tile to the end
*
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 79fcc7d813721..17124901e4de2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -24,6 +24,7 @@ import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toolbar;
@@ -74,8 +75,8 @@ public class QSCustomizer extends LinearLayout {
toolbar.setNavigationIcon(
getResources().getDrawable(value.resourceId, mContext.getTheme()));
- toolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
- mContext.getString(com.android.internal.R.string.reset));
+ toolbar.getMenu().add(Menu.NONE, MENU_RESET, 0, com.android.internal.R.string.reset)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
toolbar.setTitle(R.string.qs_edit);
mRecyclerView = findViewById(android.R.id.list);
mTransparentView = findViewById(R.id.customizer_transparent_view);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 3d48fd109e393..84a18d8dd3659 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -132,7 +132,7 @@ public class TileServices extends IQSService.Stub {
final String slot = tile.getComponent().getClassName();
// TileServices doesn't know how to add more than 1 icon per slot, so remove all
mMainHandler.post(() -> mHost.getIconController()
- .removeAllIconsForSlot(slot));
+ .removeAllIconsForExternalSlot(slot));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
index 30f81243e8d01..19215867e6789 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt
@@ -219,9 +219,9 @@ object FooterActionsViewBinder {
// Small button with the number only.
foregroundServicesWithTextView.isVisible = false
- foregroundServicesWithNumberView.visibility = View.VISIBLE
+ foregroundServicesWithNumberView.isVisible = true
foregroundServicesWithNumberView.setOnClickListener {
- foregroundServices.onClick(Expandable.fromView(foregroundServicesWithTextView))
+ foregroundServices.onClick(Expandable.fromView(foregroundServicesWithNumberView))
}
foregroundServicesWithNumberHolder.number.text = foregroundServicesCount.toString()
foregroundServicesWithNumberHolder.number.contentDescription = foregroundServices.text
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index b355d4bb67feb..29d7fb02e6139 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -145,7 +145,6 @@ open class QSTileViewImpl @JvmOverloads constructor(
private val launchableViewDelegate = LaunchableViewDelegate(
this,
superSetVisibility = { super.setVisibility(it) },
- superSetTransitionVisibility = { super.setTransitionVisibility(it) },
)
private var lastDisabledByPolicy = false
@@ -362,10 +361,6 @@ open class QSTileViewImpl @JvmOverloads constructor(
launchableViewDelegate.setVisibility(visibility)
}
- override fun setTransitionVisibility(visibility: Int) {
- launchableViewDelegate.setTransitionVisibility(visibility)
- }
-
// Accessibility
override fun onInitializeAccessibilityEvent(event: AccessibilityEvent) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
index a6c7781d891c0..72c6bfe371ce2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java
@@ -101,7 +101,6 @@ public class WorkModeTile extends QSTileImpl implements
@MainThread
public void onManagedProfileRemoved() {
mHost.removeTile(getTileSpec());
- mHost.unmarkTileAsAutoAdded(getTileSpec());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
index 28da38b701bc1..61390c582fd60 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
@@ -112,7 +112,7 @@ class UserTrackerImpl internal constructor(
// These get called when a managed profile goes in or out of quiet mode.
addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)
-
+ addAction(Intent.ACTION_MANAGED_PROFILE_ADDED)
addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)
addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)
}
@@ -129,6 +129,7 @@ class UserTrackerImpl internal constructor(
Intent.ACTION_USER_INFO_CHANGED,
Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_ADDED,
Intent.ACTION_MANAGED_PROFILE_REMOVED,
Intent.ACTION_MANAGED_PROFILE_UNLOCKED -> {
handleProfilesChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
index 7fc0a5f6d4bf3..e406be1ea0a3d 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
@@ -175,9 +175,10 @@ class LargeScreenShadeHeaderController @Inject constructor(
*/
var shadeExpandedFraction = -1f
set(value) {
- if (visible && field != value) {
+ if (field != value) {
header.alpha = ShadeInterpolation.getContentAlpha(value)
field = value
+ updateVisibility()
}
}
@@ -331,6 +332,9 @@ class LargeScreenShadeHeaderController @Inject constructor(
.setDuration(duration)
.alpha(if (show) 0f else 1f)
.setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN)
+ .setUpdateListener {
+ updateVisibility()
+ }
.start()
}
@@ -414,7 +418,7 @@ class LargeScreenShadeHeaderController @Inject constructor(
private fun updateVisibility() {
val visibility = if (!largeScreenActive && !combinedHeaders || qsDisabled) {
View.GONE
- } else if (qsVisible) {
+ } else if (qsVisible && header.alpha > 0f) {
View.VISIBLE
} else {
View.INVISIBLE
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
index 662f70ef269ea..438b0f625fc5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedFrameLayout.java
@@ -36,10 +36,6 @@ public class AlphaOptimizedFrameLayout extends FrameLayout implements Launchable
visibility -> {
super.setVisibility(visibility);
return Unit.INSTANCE;
- },
- visibility -> {
- super.setTransitionVisibility(visibility);
- return Unit.INSTANCE;
});
public AlphaOptimizedFrameLayout(Context context) {
@@ -73,9 +69,4 @@ public class AlphaOptimizedFrameLayout extends FrameLayout implements Launchable
public void setVisibility(int visibility) {
mLaunchableViewDelegate.setVisibility(visibility);
}
-
- @Override
- public void setTransitionVisibility(int visibility) {
- mLaunchableViewDelegate.setTransitionVisibility(visibility);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 8d48d738f0f2e..9b93d7b9e1d0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -1431,6 +1431,22 @@ public class NotificationChildrenContainer extends ViewGroup
@Override
public void applyRoundnessAndInvalidate() {
boolean last = true;
+ if (mUseRoundnessSourceTypes) {
+ if (mNotificationHeaderWrapper != null) {
+ mNotificationHeaderWrapper.requestTopRoundness(
+ /* value = */ getTopRoundness(),
+ /* sourceType = */ FROM_PARENT,
+ /* animate = */ false
+ );
+ }
+ if (mNotificationHeaderWrapperLowPriority != null) {
+ mNotificationHeaderWrapperLowPriority.requestTopRoundness(
+ /* value = */ getTopRoundness(),
+ /* sourceType = */ FROM_PARENT,
+ /* animate = */ false
+ );
+ }
+ }
for (int i = mAttachedChildren.size() - 1; i >= 0; i--) {
ExpandableNotificationRow child = mAttachedChildren.get(i);
if (child.getVisibility() == View.GONE) {
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 ca1e397f930a4..2f543254786f5 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
@@ -5193,7 +5193,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
println(pw, "intrinsicPadding", mIntrinsicPadding);
println(pw, "topPadding", mTopPadding);
println(pw, "bottomPadding", mBottomPadding);
- mNotificationStackSizeCalculator.dump(pw, args);
});
pw.println();
pw.println("Contents:");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
index 25f99c69d4543..ae854e2df91ae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
@@ -30,7 +30,6 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.util.Compile
import com.android.systemui.util.children
-import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.max
import kotlin.math.min
@@ -54,8 +53,6 @@ constructor(
@Main private val resources: Resources
) {
- private lateinit var lastComputeHeightLog : String
-
/**
* Maximum # notifications to show on Keyguard; extras will be collapsed in an overflow shelf.
* If there are exactly 1 + mMaxKeyguardNotifications, and they fit in the available space
@@ -117,9 +114,7 @@ constructor(
shelfIntrinsicHeight: Float
): Int {
log { "\n" }
-
- val stackHeightSequence = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight,
- /* computeHeight= */ false)
+ val stackHeightSequence = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight)
var maxNotifications =
stackHeightSequence.lastIndexWhile { heightResult ->
@@ -162,21 +157,18 @@ constructor(
shelfIntrinsicHeight: Float
): Float {
log { "\n" }
- lastComputeHeightLog = ""
val heightPerMaxNotifications =
- computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight,
- /* computeHeight= */ true)
+ computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight)
val (notificationsHeight, shelfHeightWithSpaceBefore) =
heightPerMaxNotifications.elementAtOrElse(maxNotifications) {
heightPerMaxNotifications.last() // Height with all notifications visible.
}
- lastComputeHeightLog += "\ncomputeHeight(maxNotifications=$maxNotifications," +
+ log {
+ "computeHeight(maxNotifications=$maxNotifications," +
"shelfIntrinsicHeight=$shelfIntrinsicHeight) -> " +
"${notificationsHeight + shelfHeightWithSpaceBefore}" +
" = ($notificationsHeight + $shelfHeightWithSpaceBefore)"
- log {
- lastComputeHeightLog
}
return notificationsHeight + shelfHeightWithSpaceBefore
}
@@ -192,8 +184,7 @@ constructor(
private fun computeHeightPerNotificationLimit(
stack: NotificationStackScrollLayout,
- shelfHeight: Float,
- computeHeight: Boolean
+ shelfHeight: Float
): Sequence = sequence {
log { "computeHeightPerNotificationLimit" }
@@ -222,14 +213,9 @@ constructor(
currentIndex = firstViewInShelfIndex)
spaceBeforeShelf + shelfHeight
}
-
- val currentLog = "computeHeight | i=$i notificationsHeight=$notifications " +
- "shelfHeightWithSpaceBefore=$shelfWithSpaceBefore"
- if (computeHeight) {
- lastComputeHeightLog += "\n" + currentLog
- }
log {
- currentLog
+ "i=$i notificationsHeight=$notifications " +
+ "shelfHeightWithSpaceBefore=$shelfWithSpaceBefore"
}
yield(
StackHeight(
@@ -274,10 +260,6 @@ constructor(
return size
}
- fun dump(pw: PrintWriter, args: Array) {
- pw.println("NotificationStackSizeCalculator lastComputeHeightLog = $lastComputeHeightLog")
- }
-
private fun ExpandableView.isShowable(onLockscreen: Boolean): Boolean {
if (visibility == GONE || hasNoContentHeight()) return false
if (onLockscreen) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 9070eadd9944f..149ec545dfa73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -154,9 +154,7 @@ public class AutoTileManager implements UserAwareController {
if (!mAutoTracker.isAdded(SAVER)) {
mDataSaverController.addCallback(mDataSaverListener);
}
- if (!mAutoTracker.isAdded(WORK)) {
- mManagedProfileController.addCallback(mProfileCallback);
- }
+ mManagedProfileController.addCallback(mProfileCallback);
if (!mAutoTracker.isAdded(NIGHT)
&& ColorDisplayManager.isNightDisplayAvailable(mContext)) {
mNightDisplayListener.setCallback(mNightDisplayCallback);
@@ -275,18 +273,18 @@ public class AutoTileManager implements UserAwareController {
return mCurrentUser.getIdentifier();
}
- public void unmarkTileAsAutoAdded(String tabSpec) {
- mAutoTracker.setTileRemoved(tabSpec);
- }
-
private final ManagedProfileController.Callback mProfileCallback =
new ManagedProfileController.Callback() {
@Override
public void onManagedProfileChanged() {
- if (mAutoTracker.isAdded(WORK)) return;
if (mManagedProfileController.hasActiveProfile()) {
+ if (mAutoTracker.isAdded(WORK)) return;
mHost.addTile(WORK);
mAutoTracker.setTileAdded(WORK);
+ } else {
+ if (!mAutoTracker.isAdded(WORK)) return;
+ mHost.removeTile(WORK);
+ mAutoTracker.setTileRemoved(WORK);
}
}
@@ -429,7 +427,7 @@ public class AutoTileManager implements UserAwareController {
initSafetyTile();
} else if (!isSafetyCenterEnabled && mAutoTracker.isAdded(mSafetySpec)) {
mHost.removeTile(mSafetySpec);
- mHost.unmarkTileAsAutoAdded(mSafetySpec);
+ mAutoTracker.setTileRemoved(mSafetySpec);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 1a14a03637630..24ad55d67bb09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -79,12 +79,30 @@ public interface StatusBarIconController {
/** Refresh the state of an IconManager by recreating the views */
void refreshIconGroup(IconManager iconManager);
- /** */
+
+ /**
+ * Adds or updates an icon for a given slot for a **tile service icon**.
+ *
+ * TODO(b/265307726): Merge with {@link #setIcon(String, StatusBarIcon)} or make this method
+ * much more clearly distinct from that method.
+ */
void setExternalIcon(String slot);
- /** */
+
+ /**
+ * Adds or updates an icon for the given slot for **internal system icons**.
+ *
+ * TODO(b/265307726): Rename to `setInternalIcon`, or merge this appropriately with the
+ * {@link #setIcon(String, StatusBarIcon)} method.
+ */
void setIcon(String slot, int resourceId, CharSequence contentDescription);
- /** */
+
+ /**
+ * Adds or updates an icon for the given slot for an **externally-provided icon**.
+ *
+ * TODO(b/265307726): Rename to `setExternalIcon` or something similar.
+ */
void setIcon(String slot, StatusBarIcon icon);
+
/** */
void setWifiIcon(String slot, WifiIconState state);
@@ -133,9 +151,17 @@ public interface StatusBarIconController {
* TAG_PRIMARY to refer to the first icon at a given slot.
*/
void removeIcon(String slot, int tag);
+
/** */
void removeAllIconsForSlot(String slot);
+ /**
+ * Removes all the icons for the given slot.
+ *
+ * Only use this for icons that have come from **an external process**.
+ */
+ void removeAllIconsForExternalSlot(String slot);
+
// TODO: See if we can rename this tunable name.
String ICON_HIDE_LIST = "icon_blacklist";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 9fbe6cbc0e326..416bc7141eebf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -28,6 +28,8 @@ import android.util.ArraySet;
import android.util.Log;
import android.view.ViewGroup;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
@@ -63,6 +65,10 @@ public class StatusBarIconControllerImpl implements Tunable,
ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController, DemoMode {
private static final String TAG = "StatusBarIconController";
+ // Use this suffix to prevent external icon slot names from unintentionally overriding our
+ // internal, system-level slot names. See b/255428281.
+ @VisibleForTesting
+ protected static final String EXTERNAL_SLOT_SUFFIX = "__external";
private final StatusBarIconList mStatusBarIconList;
private final ArrayList mIconGroups = new ArrayList<>();
@@ -346,21 +352,26 @@ public class StatusBarIconControllerImpl implements Tunable,
@Override
public void setExternalIcon(String slot) {
- int viewIndex = mStatusBarIconList.getViewIndex(slot, 0);
+ String slotName = createExternalSlotName(slot);
+ int viewIndex = mStatusBarIconList.getViewIndex(slotName, 0);
int height = mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_icon_drawing_size);
mIconGroups.forEach(l -> l.onIconExternal(viewIndex, height));
}
- //TODO: remove this (used in command queue and for 3rd party tiles?)
+ // Override for *both* CommandQueue.Callbacks AND StatusBarIconController.
+ // TODO(b/265307726): Pull out the CommandQueue callbacks into a member variable to
+ // differentiate between those callback methods and StatusBarIconController methods.
+ @Override
public void setIcon(String slot, StatusBarIcon icon) {
+ String slotName = createExternalSlotName(slot);
if (icon == null) {
- removeAllIconsForSlot(slot);
+ removeAllIconsForSlot(slotName);
return;
}
StatusBarIconHolder holder = StatusBarIconHolder.fromIcon(icon);
- setIcon(slot, holder);
+ setIcon(slotName, holder);
}
private void setIcon(String slot, @NonNull StatusBarIconHolder holder) {
@@ -406,10 +417,12 @@ public class StatusBarIconControllerImpl implements Tunable,
}
}
- /** */
+ // CommandQueue.Callbacks override
+ // TODO(b/265307726): Pull out the CommandQueue callbacks into a member variable to
+ // differentiate between those callback methods and StatusBarIconController methods.
@Override
public void removeIcon(String slot) {
- removeAllIconsForSlot(slot);
+ removeAllIconsForExternalSlot(slot);
}
/** */
@@ -423,6 +436,11 @@ public class StatusBarIconControllerImpl implements Tunable,
mIconGroups.forEach(l -> l.onRemoveIcon(viewIndex));
}
+ @Override
+ public void removeAllIconsForExternalSlot(String slotName) {
+ removeAllIconsForSlot(createExternalSlotName(slotName));
+ }
+
/** */
@Override
public void removeAllIconsForSlot(String slotName) {
@@ -506,4 +524,12 @@ public class StatusBarIconControllerImpl implements Tunable,
public void onDensityOrFontScaleChanged() {
refreshIconGroups();
}
+
+ private String createExternalSlotName(String slot) {
+ if (slot.endsWith(EXTERNAL_SLOT_SUFFIX)) {
+ return slot;
+ } else {
+ return slot + EXTERNAL_SLOT_SUFFIX;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index d04bef87db982..5641237bf0d0a 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -72,7 +72,6 @@ import android.os.Message;
import android.os.SystemClock;
import android.os.Trace;
import android.os.VibrationEffect;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.text.InputFilter;
@@ -109,8 +108,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.graphics.drawable.BackgroundBlurDrawable;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.view.RotationPolicy;
@@ -130,15 +127,11 @@ import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.AlphaTintDrawableWrapper;
-import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.RoundedCornerProgressDrawable;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
@@ -195,9 +188,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
private ViewGroup mDialogRowsView;
private ViewGroup mRinger;
- private DeviceConfigProxy mDeviceConfigProxy;
- private Executor mExecutor;
-
/**
* Container for the top part of the dialog, which contains the ringer, the ringer drawer, the
* volume rows, and the ellipsis button. This does not include the live caption button.
@@ -286,13 +276,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
private BackgroundBlurDrawable mDialogRowsViewBackground;
private final InteractionJankMonitor mInteractionJankMonitor;
- private boolean mSeparateNotification;
-
- @VisibleForTesting
- int mVolumeRingerIconDrawableId;
- @VisibleForTesting
- int mVolumeRingerMuteIconDrawableId;
-
public VolumeDialogImpl(
Context context,
VolumeDialogController volumeDialogController,
@@ -303,8 +286,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
VolumePanelFactory volumePanelFactory,
ActivityStarter activityStarter,
InteractionJankMonitor interactionJankMonitor,
- DeviceConfigProxy deviceConfigProxy,
- Executor executor,
DumpManager dumpManager) {
mContext =
new ContextThemeWrapper(context, R.style.volume_dialog_theme);
@@ -347,50 +328,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
}
initDimens();
-
- mDeviceConfigProxy = deviceConfigProxy;
- mExecutor = executor;
- mSeparateNotification = mDeviceConfigProxy.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false);
- updateRingerModeIconSet();
- }
-
- /**
- * If ringer and notification are the same stream (T and earlier), use notification-like bell
- * icon set.
- * If ringer and notification are separated, then use generic speaker icons.
- */
- private void updateRingerModeIconSet() {
- if (mSeparateNotification) {
- mVolumeRingerIconDrawableId = R.drawable.ic_speaker_on;
- mVolumeRingerMuteIconDrawableId = R.drawable.ic_speaker_mute;
- } else {
- mVolumeRingerIconDrawableId = R.drawable.ic_volume_ringer;
- mVolumeRingerMuteIconDrawableId = R.drawable.ic_volume_ringer_mute;
- }
-
- if (mRingerDrawerMuteIcon != null) {
- mRingerDrawerMuteIcon.setImageResource(mVolumeRingerMuteIconDrawableId);
- }
- if (mRingerDrawerNormalIcon != null) {
- mRingerDrawerNormalIcon.setImageResource(mVolumeRingerIconDrawableId);
- }
- }
-
- /**
- * Change icon for ring stream (not ringer mode icon)
- */
- private void updateRingRowIcon() {
- Optional volumeRow = mRows.stream().filter(row -> row.stream == STREAM_RING)
- .findFirst();
- if (volumeRow.isPresent()) {
- VolumeRow volRow = volumeRow.get();
- volRow.iconRes = mSeparateNotification ? R.drawable.ic_ring_volume
- : R.drawable.ic_volume_ringer;
- volRow.iconMuteRes = mSeparateNotification ? R.drawable.ic_ring_volume_off
- : R.drawable.ic_volume_ringer_mute;
- volRow.setIcon(volRow.iconRes, mContext.getTheme());
- }
}
@Override
@@ -407,9 +344,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mController.getState();
mConfigurationController.addCallback(this);
-
- mDeviceConfigProxy.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_SYSTEMUI,
- mExecutor, this::onDeviceConfigChange);
}
@Override
@@ -417,24 +351,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mController.removeCallback(mControllerCallbackH);
mHandler.removeCallbacksAndMessages(null);
mConfigurationController.removeCallback(this);
- mDeviceConfigProxy.removeOnPropertiesChangedListener(this::onDeviceConfigChange);
- }
-
- /**
- * Update ringer mode icon based on the config
- */
- private void onDeviceConfigChange(DeviceConfig.Properties properties) {
- Set changeSet = properties.getKeyset();
- if (changeSet.contains(SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION)) {
- boolean newVal = properties.getBoolean(
- SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, false);
- if (newVal != mSeparateNotification) {
- mSeparateNotification = newVal;
- updateRingerModeIconSet();
- updateRingRowIcon();
-
- }
- }
}
@Override
@@ -643,8 +559,6 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mRingerDrawerNormalIcon = mDialog.findViewById(R.id.volume_drawer_normal_icon);
mRingerDrawerNewSelectionBg = mDialog.findViewById(R.id.volume_drawer_selection_background);
- updateRingerModeIconSet();
-
setupRingerDrawer();
mODICaptionsView = mDialog.findViewById(R.id.odi_captions);
@@ -668,14 +582,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
addRow(AudioManager.STREAM_MUSIC,
R.drawable.ic_volume_media, R.drawable.ic_volume_media_mute, true, true);
if (!AudioSystem.isSingleVolume(mContext)) {
- if (mSeparateNotification) {
- addRow(AudioManager.STREAM_RING, R.drawable.ic_ring_volume,
- R.drawable.ic_ring_volume_off, true, false);
- } else {
- addRow(AudioManager.STREAM_RING, R.drawable.ic_volume_ringer,
- R.drawable.ic_volume_ringer, true, false);
- }
-
+ addRow(AudioManager.STREAM_RING,
+ R.drawable.ic_volume_ringer, R.drawable.ic_volume_ringer_mute, true, false);
addRow(STREAM_ALARM,
R.drawable.ic_alarm, R.drawable.ic_volume_alarm_mute, true, false);
addRow(AudioManager.STREAM_VOICE_CALL,
@@ -1634,8 +1542,8 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mRingerIcon.setTag(Events.ICON_STATE_VIBRATE);
break;
case AudioManager.RINGER_MODE_SILENT:
- mRingerIcon.setImageResource(mVolumeRingerMuteIconDrawableId);
- mSelectedRingerIcon.setImageResource(mVolumeRingerMuteIconDrawableId);
+ mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
+ mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
mRingerIcon.setTag(Events.ICON_STATE_MUTE);
addAccessibilityDescription(mRingerIcon, RINGER_MODE_SILENT,
mContext.getString(R.string.volume_ringer_hint_unmute));
@@ -1644,14 +1552,14 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
default:
boolean muted = (mAutomute && ss.level == 0) || ss.muted;
if (!isZenMuted && muted) {
- mRingerIcon.setImageResource(mVolumeRingerMuteIconDrawableId);
- mSelectedRingerIcon.setImageResource(mVolumeRingerMuteIconDrawableId);
+ mRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
+ mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
addAccessibilityDescription(mRingerIcon, RINGER_MODE_NORMAL,
mContext.getString(R.string.volume_ringer_hint_unmute));
mRingerIcon.setTag(Events.ICON_STATE_MUTE);
} else {
- mRingerIcon.setImageResource(mVolumeRingerIconDrawableId);
- mSelectedRingerIcon.setImageResource(mVolumeRingerIconDrawableId);
+ mRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
+ mSelectedRingerIcon.setImageResource(R.drawable.ic_volume_ringer);
if (mController.hasVibrator()) {
addAccessibilityDescription(mRingerIcon, RINGER_MODE_NORMAL,
mContext.getString(R.string.volume_ringer_hint_vibrate));
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
index 0ab6c690e1e14..bd420339b948b 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -20,7 +20,6 @@ import android.content.Context;
import android.media.AudioManager;
import com.android.internal.jank.InteractionJankMonitor;
-import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.dialog.MediaOutputDialogFactory;
import com.android.systemui.plugins.ActivityStarter;
@@ -29,14 +28,11 @@ import com.android.systemui.plugins.VolumeDialogController;
import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.volume.VolumeComponent;
import com.android.systemui.volume.VolumeDialogComponent;
import com.android.systemui.volume.VolumeDialogImpl;
import com.android.systemui.volume.VolumePanelFactory;
-import java.util.concurrent.Executor;
-
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
@@ -61,8 +57,6 @@ public interface VolumeModule {
VolumePanelFactory volumePanelFactory,
ActivityStarter activityStarter,
InteractionJankMonitor interactionJankMonitor,
- DeviceConfigProxy deviceConfigProxy,
- @Main Executor executor,
DumpManager dumpManager) {
VolumeDialogImpl impl = new VolumeDialogImpl(
context,
@@ -74,8 +68,6 @@ public interface VolumeModule {
volumePanelFactory,
activityStarter,
interactionJankMonitor,
- deviceConfigProxy,
- executor,
dumpManager);
impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
impl.setAutomute(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index 7c1e384f8c305..cac4a0e5432c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -12,11 +12,13 @@ import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
import android.view.WindowManager
+import android.widget.FrameLayout
import android.widget.LinearLayout
import androidx.test.filters.SmallTest
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.policy.DecorView
import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertNotNull
@@ -205,25 +207,74 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
verify(interactionJankMonitor).end(InteractionJankMonitor.CUJ_USER_DIALOG_OPEN)
}
+ @Test
+ fun testAnimationDoesNotChangeLaunchableViewVisibility_viewVisible() {
+ val touchSurface = createTouchSurface()
+
+ // View is VISIBLE when starting the animation.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.VISIBLE }
+
+ // View is invisible while the dialog is shown.
+ val dialog = showDialogFromView(touchSurface)
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // View is visible again when the dialog is dismissed.
+ runOnMainThreadAndWaitForIdleSync { dialog.dismiss() }
+ assertThat(touchSurface.visibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun testAnimationDoesNotChangeLaunchableViewVisibility_viewInvisible() {
+ val touchSurface = createTouchSurface()
+
+ // View is INVISIBLE when starting the animation.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.INVISIBLE }
+
+ // View is INVISIBLE while the dialog is shown.
+ val dialog = showDialogFromView(touchSurface)
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // View is invisible like it was before showing the dialog.
+ runOnMainThreadAndWaitForIdleSync { dialog.dismiss() }
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+ }
+
+ @Test
+ fun testAnimationDoesNotChangeLaunchableViewVisibility_viewVisibleThenGone() {
+ val touchSurface = createTouchSurface()
+
+ // View is VISIBLE when starting the animation.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.VISIBLE }
+
+ // View is INVISIBLE while the dialog is shown.
+ val dialog = showDialogFromView(touchSurface)
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // Some external call makes the View GONE. It remains INVISIBLE while the dialog is shown,
+ // as all visibility changes should be blocked.
+ runOnMainThreadAndWaitForIdleSync { touchSurface.visibility = View.GONE }
+ assertThat(touchSurface.visibility).isEqualTo(View.INVISIBLE)
+
+ // View is restored to GONE once the dialog is dismissed.
+ runOnMainThreadAndWaitForIdleSync { dialog.dismiss() }
+ assertThat(touchSurface.visibility).isEqualTo(View.GONE)
+ }
+
private fun createAndShowDialog(
animator: DialogLaunchAnimator = dialogLaunchAnimator,
): TestDialog {
val touchSurface = createTouchSurface()
- return runOnMainThreadAndWaitForIdleSync {
- val dialog = TestDialog(context)
- animator.showFromView(dialog, touchSurface)
- dialog
- }
+ return showDialogFromView(touchSurface, animator)
}
private fun createTouchSurface(): View {
return runOnMainThreadAndWaitForIdleSync {
val touchSurfaceRoot = LinearLayout(context)
- val touchSurface = View(context)
+ val touchSurface = TouchSurfaceView(context)
touchSurfaceRoot.addView(touchSurface)
// We need to attach the root to the window manager otherwise the exit animation will
- // be skipped
+ // be skipped.
ViewUtils.attachView(touchSurfaceRoot)
attachedViews.add(touchSurfaceRoot)
@@ -231,6 +282,17 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
}
}
+ private fun showDialogFromView(
+ touchSurface: View,
+ animator: DialogLaunchAnimator = dialogLaunchAnimator,
+ ): TestDialog {
+ return runOnMainThreadAndWaitForIdleSync {
+ val dialog = TestDialog(context)
+ animator.showFromView(dialog, touchSurface)
+ dialog
+ }
+ }
+
private fun createDialogAndShowFromDialog(animateFrom: Dialog): TestDialog {
return runOnMainThreadAndWaitForIdleSync {
val dialog = TestDialog(context)
@@ -248,6 +310,22 @@ class DialogLaunchAnimatorTest : SysuiTestCase() {
return result
}
+ private class TouchSurfaceView(context: Context) : FrameLayout(context), LaunchableView {
+ private val delegate =
+ LaunchableViewDelegate(
+ this,
+ superSetVisibility = { super.setVisibility(it) },
+ )
+
+ override fun setShouldBlockVisibilityChanges(block: Boolean) {
+ delegate.setShouldBlockVisibilityChanges(block)
+ }
+
+ override fun setVisibility(visibility: Int) {
+ delegate.setVisibility(visibility)
+ }
+ }
+
private class TestDialog(context: Context) : Dialog(context) {
companion object {
const val DIALOG_WIDTH = 100
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
new file mode 100644
index 0000000000000..3710281499b30
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplReceiveTest.kt
@@ -0,0 +1,100 @@
+package com.android.systemui.settings
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.UserInfo
+import android.os.Handler
+import android.os.UserHandle
+import android.os.UserManager
+import androidx.concurrent.futures.DirectExecutor
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.Executor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(Parameterized::class)
+class UserTrackerImplReceiveTest : SysuiTestCase() {
+
+ companion object {
+
+ @JvmStatic
+ @Parameterized.Parameters
+ fun data(): Iterable =
+ listOf(
+ Intent.ACTION_USER_INFO_CHANGED,
+ Intent.ACTION_MANAGED_PROFILE_AVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE,
+ Intent.ACTION_MANAGED_PROFILE_ADDED,
+ Intent.ACTION_MANAGED_PROFILE_REMOVED,
+ Intent.ACTION_MANAGED_PROFILE_UNLOCKED
+ )
+ }
+
+ private val executor: Executor = DirectExecutor.INSTANCE
+
+ @Mock private lateinit var context: Context
+ @Mock private lateinit var userManager: UserManager
+ @Mock(stubOnly = true) private lateinit var dumpManager: DumpManager
+ @Mock(stubOnly = true) private lateinit var handler: Handler
+
+ @Parameterized.Parameter lateinit var intentAction: String
+ @Mock private lateinit var callback: UserTracker.Callback
+ @Captor private lateinit var captor: ArgumentCaptor>
+
+ private lateinit var tracker: UserTrackerImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ `when`(context.user).thenReturn(UserHandle.SYSTEM)
+ `when`(context.createContextAsUser(ArgumentMatchers.any(), anyInt())).thenReturn(context)
+
+ tracker = UserTrackerImpl(context, userManager, dumpManager, handler)
+ }
+
+ @Test
+ fun `calls callback and updates profiles when an intent received`() {
+ tracker.initialize(0)
+ tracker.addCallback(callback, executor)
+ val profileID = tracker.userId + 10
+
+ `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
+ val id = invocation.getArgument(0)
+ val info = UserInfo(id, "", UserInfo.FLAG_FULL)
+ val infoProfile =
+ UserInfo(
+ id + 10,
+ "",
+ "",
+ UserInfo.FLAG_MANAGED_PROFILE,
+ UserManager.USER_TYPE_PROFILE_MANAGED
+ )
+ infoProfile.profileGroupId = id
+ listOf(info, infoProfile)
+ }
+
+ tracker.onReceive(context, Intent(intentAction))
+
+ verify(callback, times(0)).onUserChanged(anyInt(), any())
+ verify(callback, times(1)).onProfilesChanged(capture(captor))
+ assertThat(captor.value.map { it.id }).containsExactly(0, profileID)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
index 52462c7186d4a..e65bbb1bea086 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
@@ -124,6 +124,16 @@ class UserTrackerImplTest : SysuiTestCase() {
verify(context).registerReceiverForAllUsers(
eq(tracker), capture(captor), isNull(), eq(handler))
+ with(captor.value) {
+ assertThat(countActions()).isEqualTo(7)
+ assertThat(hasAction(Intent.ACTION_USER_SWITCHED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_USER_INFO_CHANGED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_ADDED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_REMOVED)).isTrue()
+ assertThat(hasAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED)).isTrue()
+ }
}
@Test
@@ -279,37 +289,6 @@ class UserTrackerImplTest : SysuiTestCase() {
assertThat(callback.lastUserProfiles.map { it.id }).containsExactly(newID)
}
- @Test
- fun testCallbackCalledOnProfileChanged() {
- tracker.initialize(0)
- val callback = TestCallback()
- tracker.addCallback(callback, executor)
- val profileID = tracker.userId + 10
-
- `when`(userManager.getProfiles(anyInt())).thenAnswer { invocation ->
- val id = invocation.getArgument(0)
- val info = UserInfo(id, "", UserInfo.FLAG_FULL)
- val infoProfile = UserInfo(
- id + 10,
- "",
- "",
- UserInfo.FLAG_MANAGED_PROFILE,
- UserManager.USER_TYPE_PROFILE_MANAGED
- )
- infoProfile.profileGroupId = id
- listOf(info, infoProfile)
- }
-
- val intent = Intent(Intent.ACTION_MANAGED_PROFILE_AVAILABLE)
- .putExtra(Intent.EXTRA_USER, UserHandle.of(profileID))
-
- tracker.onReceive(context, intent)
-
- assertThat(callback.calledOnUserChanged).isEqualTo(0)
- assertThat(callback.calledOnProfilesChanged).isEqualTo(1)
- assertThat(callback.lastUserProfiles.map { it.id }).containsExactly(0, profileID)
- }
-
@Test
fun testCallbackCalledOnUserInfoChanged() {
tracker.initialize(0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
index 88651c1292c34..f802a5e09228f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.shade
import android.testing.AndroidTestingRunner
+import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintSet
import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID
import androidx.constraintlayout.widget.ConstraintSet.START
@@ -92,12 +93,12 @@ class CombinedShadeHeaderConstraintsTest : SysuiTestCase() {
assertThat(getConstraint(R.id.clock).layout.horizontalBias).isEqualTo(0f)
assertThat(getConstraint(R.id.date).layout.startToStart).isEqualTo(PARENT_ID)
- assertThat(getConstraint(R.id.date).layout.horizontalBias).isEqualTo(0f)
+ assertThat(getConstraint(R.id.date).layout.horizontalBias).isEqualTo(0.5f)
assertThat(getConstraint(R.id.batteryRemainingIcon).layout.endToEnd)
.isEqualTo(PARENT_ID)
assertThat(getConstraint(R.id.batteryRemainingIcon).layout.horizontalBias)
- .isEqualTo(1f)
+ .isEqualTo(0.5f)
assertThat(getConstraint(R.id.privacy_container).layout.endToEnd)
.isEqualTo(R.id.end_guide)
@@ -331,10 +332,8 @@ class CombinedShadeHeaderConstraintsTest : SysuiTestCase() {
val views = mapOf(
R.id.clock to "clock",
R.id.date to "date",
- R.id.statusIcons to "icons",
R.id.privacy_container to "privacy",
R.id.carrier_group to "carriers",
- R.id.batteryRemainingIcon to "battery",
)
views.forEach { (id, name) ->
assertWithMessage("$name has 0 height in qqs")
@@ -352,11 +351,8 @@ class CombinedShadeHeaderConstraintsTest : SysuiTestCase() {
fun testCheckViewsDontChangeSizeBetweenAnimationConstraints() {
val views = mapOf(
R.id.clock to "clock",
- R.id.date to "date",
- R.id.statusIcons to "icons",
R.id.privacy_container to "privacy",
R.id.carrier_group to "carriers",
- R.id.batteryRemainingIcon to "battery",
)
views.forEach { (id, name) ->
expect.withMessage("$name changes height")
@@ -369,8 +365,8 @@ class CombinedShadeHeaderConstraintsTest : SysuiTestCase() {
}
private fun Int.fromConstraint() = when (this) {
- -1 -> "MATCH_PARENT"
- -2 -> "WRAP_CONTENT"
+ ViewGroup.LayoutParams.MATCH_PARENT -> "MATCH_PARENT"
+ ViewGroup.LayoutParams.WRAP_CONTENT -> "WRAP_CONTENT"
else -> toString()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
index 1d30ad9293a04..f580f5e00f678 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
@@ -182,6 +182,7 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() {
null
}
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
+ whenever(view.alpha).thenReturn(1f)
whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
index b4c8f981b7605..b568122d3fed0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
@@ -1,5 +1,6 @@
package com.android.systemui.shade
+import android.animation.ValueAnimator
import android.app.StatusBarManager
import android.content.Context
import android.testing.AndroidTestingRunner
@@ -30,6 +31,7 @@ import com.android.systemui.statusbar.policy.VariableDateViewController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -37,6 +39,7 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Answers
+import org.mockito.ArgumentMatchers.anyFloat
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.mock
@@ -75,6 +78,7 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
@JvmField @Rule val mockitoRule = MockitoJUnit.rule()
var viewVisibility = View.GONE
+ var viewAlpha = 1f
private lateinit var mLargeScreenShadeHeaderController: LargeScreenShadeHeaderController
private lateinit var carrierIconSlots: List
@@ -101,6 +105,13 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
null
}
whenever(view.visibility).thenAnswer { _ -> viewVisibility }
+
+ whenever(view.setAlpha(anyFloat())).then {
+ viewAlpha = it.arguments[0] as Float
+ null
+ }
+ whenever(view.alpha).thenAnswer { _ -> viewAlpha }
+
whenever(variableDateViewControllerFactory.create(any()))
.thenReturn(variableDateViewController)
whenever(iconManagerFactory.create(any(), any())).thenReturn(iconManager)
@@ -154,6 +165,16 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
}
+ @Test
+ fun alphaChangesUpdateVisibility() {
+ makeShadeVisible()
+ mLargeScreenShadeHeaderController.shadeExpandedFraction = 0f
+ assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
+
+ mLargeScreenShadeHeaderController.shadeExpandedFraction = 1f
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+ }
+
@Test
fun singleCarrier_enablesCarrierIconsInStatusIcons() {
whenever(qsCarrierGroupController.isSingleCarrier).thenReturn(true)
@@ -238,6 +259,39 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() {
verify(animator).start()
}
+ @Test
+ fun testShadeExpanded_true_alpha_zero_invisible() {
+ view.alpha = 0f
+ mLargeScreenShadeHeaderController.largeScreenActive = true
+ mLargeScreenShadeHeaderController.qsVisible = true
+
+ assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
+ }
+
+ @Test
+ fun animatorCallsUpdateVisibilityOnUpdate() {
+ val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF)
+ whenever(view.animate()).thenReturn(animator)
+
+ mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, 0L)
+
+ val updateCaptor = argumentCaptor()
+ verify(animator).setUpdateListener(capture(updateCaptor))
+
+ mLargeScreenShadeHeaderController.largeScreenActive = true
+ mLargeScreenShadeHeaderController.qsVisible = true
+
+ view.alpha = 1f
+ updateCaptor.value.onAnimationUpdate(mock())
+
+ assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+
+ view.alpha = 0f
+ updateCaptor.value.onAnimationUpdate(mock())
+
+ assertThat(viewVisibility).isEqualTo(View.INVISIBLE)
+ }
+
@Test
fun demoMode_attachDemoMode() {
val cb = argumentCaptor()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index ca99e24fc105a..e41929f7d5789 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -29,6 +29,7 @@ import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper;
import org.junit.Assert;
import org.junit.Before;
@@ -216,4 +217,29 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
Assert.assertEquals(1f, mChildrenContainer.getBottomRoundness(), 0.001f);
Assert.assertEquals(1f, notificationRow.getBottomRoundness(), 0.001f);
}
+
+ @Test
+ public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_header() {
+ mChildrenContainer.useRoundnessSourceTypes(true);
+
+ NotificationHeaderViewWrapper header = mChildrenContainer.getNotificationHeaderWrapper();
+ Assert.assertEquals(0f, header.getTopRoundness(), 0.001f);
+
+ mChildrenContainer.requestTopRoundness(1f, SourceType.from(""), false);
+
+ Assert.assertEquals(1f, header.getTopRoundness(), 0.001f);
+ }
+
+ @Test
+ public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_headerLowPriority() {
+ mChildrenContainer.useRoundnessSourceTypes(true);
+ mChildrenContainer.setIsLowPriority(true);
+
+ NotificationHeaderViewWrapper header = mChildrenContainer.getNotificationHeaderWrapper();
+ Assert.assertEquals(0f, header.getTopRoundness(), 0.001f);
+
+ mChildrenContainer.requestTopRoundness(1f, SourceType.from(""), false);
+
+ Assert.assertEquals(1f, header.getTopRoundness(), 0.001f);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 4ccbc6d45e638..091bb5455d93f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
@@ -74,6 +75,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.stubbing.Answer;
import java.util.Collections;
import java.util.List;
@@ -115,8 +117,10 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Spy private PackageManager mPackageManager;
private final boolean mIsReduceBrightColorsAvailable = true;
- private AutoTileManager mAutoTileManager;
+ private AutoTileManager mAutoTileManager; // under test
+
private SecureSettings mSecureSettings;
+ private ManagedProfileController.Callback mManagedProfileCallback;
@Before
public void setUp() throws Exception {
@@ -303,7 +307,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
InOrder inOrderManagedProfile = inOrder(mManagedProfileController);
inOrderManagedProfile.verify(mManagedProfileController).removeCallback(any());
- inOrderManagedProfile.verify(mManagedProfileController, never()).addCallback(any());
+ inOrderManagedProfile.verify(mManagedProfileController).addCallback(any());
if (ColorDisplayManager.isNightDisplayAvailable(mContext)) {
InOrder inOrderNightDisplay = inOrder(mNightDisplayListener);
@@ -503,6 +507,40 @@ public class AutoTileManagerTest extends SysuiTestCase {
verify(mQsTileHost, times(2)).addTile(safetyComponent, true);
}
+ @Test
+ public void managedProfileAdded_tileAdded() {
+ when(mAutoAddTracker.isAdded(eq("work"))).thenReturn(false);
+ mAutoTileManager = createAutoTileManager(mContext);
+ Mockito.doAnswer((Answer