Merge cherrypicks of ['ag/20911782', 'ag/20911787', 'ag/20928109', 'ag/20931541', 'ag/20946106'] into tm-qpr2-release.
Change-Id: I3b539e4fe213b68109336c1ff1f69640e1dbd30e
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:");
|
||||
|
||||
@@ -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<StackHeight> = 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<out String>) {
|
||||
pw.println("NotificationStackSizeCalculator lastComputeHeightLog = $lastComputeHeightLog")
|
||||
}
|
||||
|
||||
private fun ExpandableView.isShowable(onLockscreen: Boolean): Boolean {
|
||||
if (visibility == GONE || hasNoContentHeight()) return false
|
||||
if (onLockscreen) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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<String>
|
||||
@@ -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<ValueAnimator.AnimatorUpdateListener>()
|
||||
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<DemoMode>()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,16 +379,11 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
|
||||
resolvedType = key.requestResolvedType;
|
||||
}
|
||||
|
||||
// Apply any launch flags from the ActivityOptions. This is used only by SystemUI
|
||||
// to ensure that we can launch the pending intent with a consistent launch mode even
|
||||
// if the provided PendingIntent is immutable (ie. to force an activity to launch into
|
||||
// a new task, or to launch multiple instances if supported by the app)
|
||||
// Apply any launch flags from the ActivityOptions. This is to ensure that the caller
|
||||
// can specify a consistent launch mode even if the PendingIntent is immutable
|
||||
final ActivityOptions opts = ActivityOptions.fromBundle(options);
|
||||
if (opts != null) {
|
||||
// TODO(b/254490217): Move this check into SafeActivityOptions
|
||||
if (controller.mAtmInternal.isCallerRecents(Binder.getCallingUid())) {
|
||||
finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
|
||||
}
|
||||
finalIntent.addFlags(opts.getPendingIntentLaunchFlags());
|
||||
}
|
||||
|
||||
// Extract options before clearing calling identity
|
||||
|
||||
@@ -817,9 +817,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mDisplayDeviceConfig = config;
|
||||
loadFromDisplayDeviceConfig(token, info);
|
||||
|
||||
// Since the underlying display-device changed, we really don't know the
|
||||
// last command that was sent to change it's state. Lets assume it is off and we
|
||||
// trigger a change immediately.
|
||||
/// Since the underlying display-device changed, we really don't know the
|
||||
// last command that was sent to change it's state. Lets assume it is unknown so
|
||||
// that we trigger a change immediately.
|
||||
mPowerState.resetScreenState();
|
||||
}
|
||||
if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) {
|
||||
|
||||
@@ -340,20 +340,12 @@ final class DisplayPowerState {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the screen state to {@link Display#STATE_OFF}. Even though we do not know the last
|
||||
* state that was sent to the underlying display-device, we assume it is off.
|
||||
*
|
||||
* We do not set the screen state to {@link Display#STATE_UNKNOWN} to avoid getting in the state
|
||||
* where PhotonicModulator holds onto the lock. This happens because we currently try to keep
|
||||
* the mScreenState and mPendingState in sync, however if the screenState is set to
|
||||
* {@link Display#STATE_UNKNOWN} here, mPendingState will get progressed to this, which will
|
||||
* force the PhotonicModulator thread to wait onto the lock to take it out of that state.
|
||||
* b/262294651 for more info.
|
||||
* Resets the screen state to unknown. Useful when the underlying display-device changes for the
|
||||
* LogicalDisplay and we do not know the last state that was sent to it.
|
||||
*/
|
||||
void resetScreenState() {
|
||||
mScreenState = Display.STATE_OFF;
|
||||
mScreenState = Display.STATE_UNKNOWN;
|
||||
mScreenReady = false;
|
||||
scheduleScreenUpdate();
|
||||
}
|
||||
|
||||
private void scheduleScreenUpdate() {
|
||||
@@ -514,6 +506,8 @@ final class DisplayPowerState {
|
||||
boolean valid = state != Display.STATE_UNKNOWN && !Float.isNaN(brightnessState);
|
||||
boolean changed = stateChanged || backlightChanged;
|
||||
if (!valid || !changed) {
|
||||
mStateChangeInProgress = false;
|
||||
mBacklightChangeInProgress = false;
|
||||
try {
|
||||
mLock.wait();
|
||||
} catch (InterruptedException ex) {
|
||||
|
||||
Reference in New Issue
Block a user