diff options
35 files changed, 286 insertions, 251 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt index 940da9967a68..33748b973f1c 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt @@ -27,7 +27,6 @@ import androidx.lifecycle.LifecycleOwner import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.internal.logging.MetricsLogger -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.classifier.FalsingManagerFake @@ -45,13 +44,14 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger -import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.res.R import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.SecureSettings import com.google.common.truth.Truth.assertThat +import java.util.Optional import org.junit.After import org.junit.Before import org.junit.Test @@ -67,40 +67,27 @@ import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations -import java.util.Optional @SmallTest @RunWith(AndroidJUnit4::class) @TestableLooper.RunWithLooper(setAsMainLooper = true) class DeviceControlsTileTest : SysuiTestCase() { - @Mock - private lateinit var qsHost: QSHost - @Mock - private lateinit var metricsLogger: MetricsLogger - @Mock - private lateinit var statusBarStateController: StatusBarStateController - @Mock - private lateinit var activityStarter: ActivityStarter - @Mock - private lateinit var qsLogger: QSLogger - @Mock - private lateinit var controlsComponent: ControlsComponent - @Mock - private lateinit var controlsUiController: ControlsUiController - @Mock - private lateinit var controlsListingController: ControlsListingController - @Mock - private lateinit var controlsController: ControlsController - @Mock - private lateinit var serviceInfo: ControlsServiceInfo - @Mock - private lateinit var uiEventLogger: QsEventLogger + @Mock private lateinit var qsHost: QSHost + @Mock private lateinit var metricsLogger: MetricsLogger + @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var qsLogger: QSLogger + @Mock private lateinit var controlsComponent: ControlsComponent + @Mock private lateinit var controlsUiController: ControlsUiController + @Mock private lateinit var controlsListingController: ControlsListingController + @Mock private lateinit var controlsController: ControlsController + @Mock private lateinit var serviceInfo: ControlsServiceInfo + @Mock private lateinit var uiEventLogger: QsEventLogger @Captor private lateinit var listingCallbackCaptor: - ArgumentCaptor<ControlsListingController.ControlsListingCallback> - @Captor - private lateinit var intentCaptor: ArgumentCaptor<Intent> + ArgumentCaptor<ControlsListingController.ControlsListingCallback> + @Captor private lateinit var intentCaptor: ArgumentCaptor<Intent> private lateinit var testableLooper: TestableLooper private lateinit var tile: DeviceControlsTile @@ -120,8 +107,11 @@ class DeviceControlsTileTest : SysuiTestCase() { `when`(qsHost.context).thenReturn(spiedContext) `when`(controlsComponent.isEnabled()).thenReturn(true) `when`(controlsController.getPreferredSelection()) - .thenReturn(SelectedItem.StructureItem( - StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()))) + .thenReturn( + SelectedItem.StructureItem( + StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()) + ) + ) secureSettings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 1) setupControlsComponent() @@ -182,10 +172,11 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testObservingCallback() { - verify(controlsListingController).observe( + verify(controlsListingController) + .observe( any(LifecycleOwner::class.java), - any(ControlsListingController.ControlsListingCallback::class.java) - ) + any(ControlsListingController.ControlsListingCallback::class.java), + ) } @Test @@ -205,10 +196,8 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testStateUnavailableIfNoListings() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) listingCallbackCaptor.value.onServicesUpdated(emptyList()) testableLooper.processAllMessages() @@ -218,10 +207,8 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testStateUnavailableIfNotEnabled() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.isEnabled()).thenReturn(false) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) @@ -232,18 +219,19 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testStateActiveIfListingsHasControlsFavorited() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) - `when`(controlsController.getPreferredSelection()).thenReturn( - SelectedItem.StructureItem(StructureInfo( - ComponentName("pkg", "cls"), - "structure", - listOf(ControlInfo("id", "title", "subtitle", 1)) - )) - ) + `when`(controlsController.getPreferredSelection()) + .thenReturn( + SelectedItem.StructureItem( + StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)), + ) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -253,14 +241,15 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testStateInactiveIfListingsHasNoControlsFavorited() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(controlsController.getPreferredSelection()) - .thenReturn(SelectedItem.StructureItem( - StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()))) + .thenReturn( + SelectedItem.StructureItem( + StructureInfo(ComponentName("pkg", "cls"), "structure", listOf()) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -270,13 +259,11 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testStateActiveIfPreferredIsPanel() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(controlsController.getPreferredSelection()) - .thenReturn(SelectedItem.PanelItem("appName", ComponentName("pkg", "cls"))) + .thenReturn(SelectedItem.PanelItem("appName", ComponentName("pkg", "cls"))) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -286,10 +273,8 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testStateInactiveIfLocked() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) @@ -301,10 +286,8 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun testMoveBetweenStates() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -325,19 +308,20 @@ class DeviceControlsTileTest : SysuiTestCase() { @Test fun handleClick_available_shownOverLockscreenWhenLocked() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java) - `when`(controlsController.getPreferredSelection()).thenReturn( - SelectedItem.StructureItem(StructureInfo( - ComponentName("pkg", "cls"), - "structure", - listOf(ControlInfo("id", "title", "subtitle", 1)) - )) - ) + `when`(controlsController.getPreferredSelection()) + .thenReturn( + SelectedItem.StructureItem( + StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)), + ) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -345,30 +329,33 @@ class DeviceControlsTileTest : SysuiTestCase() { tile.click(null /* view */) testableLooper.processAllMessages() - verify(activityStarter).startActivity( + verify(activityStarter) + .startActivity( intentCaptor.capture(), eq(true) /* dismissShade */, nullable(ActivityTransitionAnimator.Controller::class.java), - eq(true) /* showOverLockscreenWhenLocked */) + eq(true), /* showOverLockscreenWhenLocked */ + ) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun handleClick_availableAfterUnlock_notShownOverLockscreenWhenLocked() { - verify(controlsListingController).observe( - any(LifecycleOwner::class.java), - capture(listingCallbackCaptor) - ) + verify(controlsListingController) + .observe(any(LifecycleOwner::class.java), capture(listingCallbackCaptor)) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java) - `when`(controlsController.getPreferredSelection()).thenReturn( - SelectedItem.StructureItem(StructureInfo( - ComponentName("pkg", "cls"), - "structure", - listOf(ControlInfo("id", "title", "subtitle", 1)) - )) - ) + `when`(controlsController.getPreferredSelection()) + .thenReturn( + SelectedItem.StructureItem( + StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)), + ) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -376,26 +363,19 @@ class DeviceControlsTileTest : SysuiTestCase() { tile.click(null /* view */) testableLooper.processAllMessages() - verify(activityStarter).startActivity( + verify(activityStarter) + .startActivity( intentCaptor.capture(), anyBoolean() /* dismissShade */, nullable(ActivityTransitionAnimator.Controller::class.java), - eq(false) /* showOverLockscreenWhenLocked */) + eq(false), /* showOverLockscreenWhenLocked */ + ) assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME) } @Test fun verifyTileEqualsResourceFromComponent() { - assertThat(tile.tileLabel) - .isEqualTo( - context.getText( - controlsComponent.getTileTitleId())) - } - - @Test - fun verifyTileImageEqualsResourceFromComponent() { - assertThat(tile.icon) - .isEqualTo(QSTileImpl.ResourceIcon.get(controlsComponent.getTileImageId())) + assertThat(tile.tileLabel).isEqualTo(context.getText(controlsComponent.getTileTitleId())) } private fun createTile(): DeviceControlsTile { @@ -409,11 +389,12 @@ class DeviceControlsTileTest : SysuiTestCase() { statusBarStateController, activityStarter, qsLogger, - controlsComponent - ).also { - it.initialize() - testableLooper.processAllMessages() - } + controlsComponent, + ) + .also { + it.initialize() + testableLooper.processAllMessages() + } } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt index dbad60265645..d72d5f127bba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt @@ -21,7 +21,6 @@ import android.graphics.drawable.AnimatedVectorDrawable import android.graphics.drawable.Drawable import android.text.TextUtils import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi import androidx.compose.animation.graphics.res.animatedVectorResource import androidx.compose.animation.graphics.res.rememberAnimatedVectorPainter import androidx.compose.animation.graphics.vector.AnimatedImageVector @@ -192,7 +191,6 @@ fun LargeTileLabels( } } -@OptIn(ExperimentalAnimationGraphicsApi::class) @Composable fun SmallTileContent( modifier: Modifier = Modifier, @@ -229,6 +227,7 @@ fun SmallTileContent( } } } + is Icon.Loaded -> { LaunchedEffect(loadedDrawable) { if (loadedDrawable is AnimatedVectorDrawable) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java index 9abc494e56e6..464eeda6a0a8 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileImpl.java @@ -31,6 +31,7 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; import android.annotation.CallSuper; import android.annotation.NonNull; +import android.annotation.SuppressLint; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; @@ -68,6 +69,7 @@ import com.android.systemui.qs.QSEvent; import com.android.systemui.qs.QSHost; import com.android.systemui.qs.QsEventLogger; import com.android.systemui.qs.SideLabelTileLayout; +import com.android.systemui.qs.flags.QsInCompose; import com.android.systemui.qs.logging.QSLogger; import java.io.PrintWriter; @@ -535,6 +537,23 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy } } + protected Icon maybeLoadResourceIcon(int id) { + return maybeLoadResourceIcon(id, mContext); + } + + /** + * Returns the {@link QSTile.Icon} for the resource ID, optionally loading the drawable if + * {@link QsInCompose#isEnabled()} is true. + */ + @SuppressLint("UseCompatLoadingForDrawables") + public static Icon maybeLoadResourceIcon(int id, Context context) { + if (QsInCompose.isEnabled()) { + return new DrawableIconWithRes(context.getDrawable(id), id); + } else { + return ResourceIcon.get(id); + } + } + @Override public String getMetricsSpec() { return mTileSpec; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java index 71b69c92b87d..bb818fa5e164 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java @@ -160,7 +160,7 @@ public class AirplaneModeTile extends QSTileImpl<BooleanState> { final boolean airplaneMode = value != 0; state.value = airplaneMode; state.label = mContext.getString(R.string.airplane_mode); - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_airplane_icon_on : R.drawable.qs_airplane_icon_off); state.state = airplaneMode ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.contentDescription = state.label; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt index 73d991f6efe7..75debb6c4032 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt @@ -42,35 +42,35 @@ constructor( activityStarter: ActivityStarter, qsLogger: QSLogger, private val userTracker: UserTracker, - nextAlarmController: NextAlarmController -) : QSTileImpl<QSTile.State>( - host, - uiEventLogger, - backgroundLooper, - mainHandler, - falsingManager, - metricsLogger, - statusBarStateController, - activityStarter, - qsLogger -) { + nextAlarmController: NextAlarmController, +) : + QSTileImpl<QSTile.State>( + host, + uiEventLogger, + backgroundLooper, + mainHandler, + falsingManager, + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger, + ) { private var lastAlarmInfo: AlarmManager.AlarmClockInfo? = null - private val icon = ResourceIcon.get(R.drawable.ic_alarm) + private var icon: QSTile.Icon? = null @VisibleForTesting internal val defaultIntent = Intent(AlarmClock.ACTION_SHOW_ALARMS) - private val callback = NextAlarmController.NextAlarmChangeCallback { nextAlarm -> - lastAlarmInfo = nextAlarm - refreshState() - } + private val callback = + NextAlarmController.NextAlarmChangeCallback { nextAlarm -> + lastAlarmInfo = nextAlarm + refreshState() + } init { nextAlarmController.observe(this, callback) } override fun newTileState(): QSTile.State { - return QSTile.State().apply { - handlesLongClick = false - } + return QSTile.State().apply { handlesLongClick = false } } override fun handleClick(expandable: Expandable?) { @@ -82,21 +82,28 @@ constructor( if (pendingIntent != null) { mActivityStarter.postStartActivityDismissingKeyguard(pendingIntent, animationController) } else { - mActivityStarter.postStartActivityDismissingKeyguard(defaultIntent, 0, - animationController) + mActivityStarter.postStartActivityDismissingKeyguard( + defaultIntent, + 0, + animationController, + ) } } override fun handleUpdateState(state: QSTile.State, arg: Any?) { + if (icon == null) { + icon = maybeLoadResourceIcon(R.drawable.ic_alarm) + } state.icon = icon state.label = tileLabel lastAlarmInfo?.let { state.secondaryLabel = formatNextAlarm(it) state.state = Tile.STATE_ACTIVE - } ?: run { - state.secondaryLabel = mContext.getString(R.string.qs_alarm_tile_no_alarm) - state.state = Tile.STATE_INACTIVE } + ?: run { + state.secondaryLabel = mContext.getString(R.string.qs_alarm_tile_no_alarm) + state.state = Tile.STATE_INACTIVE + } state.contentDescription = TextUtils.concat(state.label, ", ", state.secondaryLabel) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java index 7c0ce4cc75a9..9df4e42d1898 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java @@ -147,9 +147,8 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements protected void handleUpdateState(BooleanState state, Object arg) { state.state = mPluggedIn ? Tile.STATE_UNAVAILABLE : mPowerSave ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(mPowerSave - ? R.drawable.qs_battery_saver_icon_on - : R.drawable.qs_battery_saver_icon_off); + state.icon = maybeLoadResourceIcon(mPowerSave + ? R.drawable.qs_battery_saver_icon_on : R.drawable.qs_battery_saver_icon_off); state.label = mContext.getString(R.string.battery_detail_switch_title); state.secondaryLabel = ""; state.contentDescription = state.label; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java index 7bff827dee03..7eb0aaabb7e1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java @@ -59,13 +59,13 @@ import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.res.R; import com.android.systemui.statusbar.policy.BluetoothController; +import kotlinx.coroutines.Job; + import java.util.List; import java.util.concurrent.Executor; import javax.inject.Inject; -import kotlinx.coroutines.Job; - /** Quick settings tile: Bluetooth **/ public class BluetoothTile extends QSTileImpl<BooleanState> { @@ -201,7 +201,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { if (enabled) { if (connected) { - state.icon = ResourceIcon.get(R.drawable.qs_bluetooth_icon_on); + state.icon = maybeLoadResourceIcon(R.drawable.qs_bluetooth_icon_on); if (!TextUtils.isEmpty(mController.getConnectedDeviceName())) { state.label = mController.getConnectedDeviceName(); } @@ -209,17 +209,15 @@ public class BluetoothTile extends QSTileImpl<BooleanState> { mContext.getString(R.string.accessibility_bluetooth_name, state.label) + ", " + state.secondaryLabel; } else if (state.isTransient) { - state.icon = ResourceIcon.get( - R.drawable.qs_bluetooth_icon_search); + state.icon = maybeLoadResourceIcon(R.drawable.qs_bluetooth_icon_search); state.stateDescription = state.secondaryLabel; } else { - state.icon = - ResourceIcon.get(R.drawable.qs_bluetooth_icon_off); + state.icon = maybeLoadResourceIcon(R.drawable.qs_bluetooth_icon_off); state.stateDescription = mContext.getString(R.string.accessibility_not_connected); } state.state = Tile.STATE_ACTIVE; } else { - state.icon = ResourceIcon.get(R.drawable.qs_bluetooth_icon_off); + state.icon = maybeLoadResourceIcon(R.drawable.qs_bluetooth_icon_off); state.state = Tile.STATE_INACTIVE; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java index 8a72e8db7216..ad027b4346d0 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java @@ -290,8 +290,8 @@ public class CastTile extends QSTileImpl<BooleanState> { if (connecting && !state.value) { state.secondaryLabel = mContext.getString(R.string.quick_settings_connecting); } - state.icon = ResourceIcon.get(state.value ? R.drawable.ic_cast_connected - : R.drawable.ic_cast); + state.icon = maybeLoadResourceIcon(state.value + ? R.drawable.ic_cast_connected : R.drawable.ic_cast); if (canCastToNetwork() || state.value) { state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; if (!state.value) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java index 871973dfcb7f..c2e609ddfc3a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorCorrectionTile.java @@ -50,7 +50,8 @@ public class ColorCorrectionTile extends QSTileImpl<BooleanState> { public static final String TILE_SPEC = "color_correction"; - private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_color_correction); + @Nullable + private Icon mIcon = null; private final UserSettingObserver mSetting; @Inject @@ -122,6 +123,9 @@ public class ColorCorrectionTile extends QSTileImpl<BooleanState> { protected void handleUpdateState(BooleanState state, Object arg) { final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue(); final boolean enabled = value != 0; + if (mIcon == null) { + mIcon = maybeLoadResourceIcon(R.drawable.ic_qs_color_correction); + } state.value = enabled; state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.quick_settings_color_correction_label); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index 58969107ad22..ce80133e67a2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -124,7 +124,7 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { state.value = enabled; state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.quick_settings_inversion_label); - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_invert_colors_icon_on : R.drawable.qs_invert_colors_icon_off); state.expandedAccessibilityClassName = Switch.class.getName(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index 7760943476bf..deeef550b33f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -147,7 +147,7 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.data_saver); state.contentDescription = state.label; - state.icon = ResourceIcon.get(state.value ? R.drawable.qs_data_saver_icon_on + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_data_saver_icon_on : R.drawable.qs_data_saver_icon_off); state.expandedAccessibilityClassName = Switch.class.getName(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index cc8a73423174..404ace18d0f9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -1,4 +1,3 @@ - /* * Copyright (C) 2021 The Android Open Source Project * @@ -22,10 +21,8 @@ import android.content.Intent import android.os.Handler import android.os.Looper import android.service.quicksettings.Tile -import androidx.annotation.VisibleForTesting import com.android.internal.jank.InteractionJankMonitor import com.android.internal.logging.MetricsLogger -import com.android.systemui.res.R import com.android.systemui.animation.Expandable import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.dagger.ControlsComponent @@ -43,10 +40,13 @@ import com.android.systemui.qs.QSHost import com.android.systemui.qs.QsEventLogger import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.res.R import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject -class DeviceControlsTile @Inject constructor( +class DeviceControlsTile +@Inject +constructor( host: QSHost, uiEventLogger: QsEventLogger, @Background backgroundLooper: Looper, @@ -56,32 +56,34 @@ class DeviceControlsTile @Inject constructor( statusBarStateController: StatusBarStateController, activityStarter: ActivityStarter, qsLogger: QSLogger, - private val controlsComponent: ControlsComponent -) : QSTileImpl<QSTile.State>( - host, - uiEventLogger, - backgroundLooper, - mainHandler, - falsingManager, - metricsLogger, - statusBarStateController, - activityStarter, - qsLogger -) { + private val controlsComponent: ControlsComponent, +) : + QSTileImpl<QSTile.State>( + host, + uiEventLogger, + backgroundLooper, + mainHandler, + falsingManager, + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger, + ) { private var hasControlsApps = AtomicBoolean(false) - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - val icon: QSTile.Icon - get() = ResourceIcon.get(controlsComponent.getTileImageId()) + private var icon: QSTile.Icon? = null - private val listingCallback = object : ControlsListingController.ControlsListingCallback { - override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) { - if (hasControlsApps.compareAndSet(serviceInfos.isEmpty(), serviceInfos.isNotEmpty())) { - refreshState() + private val listingCallback = + object : ControlsListingController.ControlsListingCallback { + override fun onServicesUpdated(serviceInfos: List<ControlsServiceInfo>) { + if ( + hasControlsApps.compareAndSet(serviceInfos.isEmpty(), serviceInfos.isNotEmpty()) + ) { + refreshState() + } } } - } init { controlsComponent.getControlsListingController().ifPresent { @@ -105,15 +107,19 @@ class DeviceControlsTile @Inject constructor( return } - val intent = Intent().apply { - component = ComponentName(mContext, controlsComponent.getControlsUiController().get() - .resolveActivity()) - addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) - putExtra(ControlsUiController.EXTRA_ANIMATE, true) - } + val intent = + Intent().apply { + component = + ComponentName( + mContext, + controlsComponent.getControlsUiController().get().resolveActivity(), + ) + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) + putExtra(ControlsUiController.EXTRA_ANIMATE, true) + } val animationController = expandable?.activityTransitionController( - InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE + InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_QS_TILE ) mUiHandler.post { @@ -130,17 +136,23 @@ class DeviceControlsTile @Inject constructor( override fun handleUpdateState(state: QSTile.State, arg: Any?) { state.label = tileLabel state.contentDescription = state.label + if (icon == null) { + icon = maybeLoadResourceIcon(controlsComponent.getTileImageId()) + } state.icon = icon if (controlsComponent.isEnabled() && hasControlsApps.get()) { if (controlsComponent.getVisibility() == AVAILABLE) { - val selection = controlsComponent - .getControlsController().get().getPreferredSelection() - state.state = if (selection is SelectedItem.StructureItem && - selection.structure.controls.isEmpty()) { - Tile.STATE_INACTIVE - } else { - Tile.STATE_ACTIVE - } + val selection = + controlsComponent.getControlsController().get().getPreferredSelection() + state.state = + if ( + selection is SelectedItem.StructureItem && + selection.structure.controls.isEmpty() + ) { + Tile.STATE_INACTIVE + } else { + Tile.STATE_ACTIVE + } val label = selection.name state.secondaryLabel = if (label == tileLabel) null else label } else { @@ -170,4 +182,4 @@ class DeviceControlsTile @Inject constructor( companion object { const val TILE_SPEC = "controls" } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java index ad76b4f21bfb..04f0b8736598 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java @@ -229,7 +229,7 @@ public class DndTile extends QSTileImpl<BooleanState> { state.dualTarget = true; state.value = newValue; state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_dnd_icon_on : R.drawable.qs_dnd_icon_off); state.label = getTileLabel(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java index 0d3d980f71f4..374bcda5f46a 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DreamTile.java @@ -64,9 +64,6 @@ public class DreamTile extends QSTileImpl<QSTile.BooleanState> { public static final String TILE_SPEC = "dream"; private static final String LOG_TAG = "QSDream"; - // TODO: consider 1 animated icon instead - private final Icon mIconDocked = ResourceIcon.get(R.drawable.ic_qs_screen_saver); - private final Icon mIconUndocked = ResourceIcon.get(R.drawable.ic_qs_screen_saver_undocked); private final IDreamManager mDreamManager; private final BroadcastDispatcher mBroadcastDispatcher; private final UserSettingObserver mEnabledSettingObserver; @@ -170,7 +167,9 @@ public class DreamTile extends QSTileImpl<QSTile.BooleanState> { state.label = getTileLabel(); state.secondaryLabel = getActiveDreamName(); state.contentDescription = getContentDescription(state.secondaryLabel); - state.icon = mIsDocked ? mIconDocked : mIconUndocked; + // TODO: consider 1 animated icon instead + state.icon = maybeLoadResourceIcon(mIsDocked + ? R.drawable.ic_qs_screen_saver : R.drawable.ic_qs_screen_saver_undocked); if (getActiveDream() == null || !isScreensaverEnabled()) { state.state = Tile.STATE_UNAVAILABLE; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java index 848ff3c533ba..2b127d60b2be 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java @@ -128,7 +128,7 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements R.string.quick_settings_flashlight_camera_in_use); state.stateDescription = state.secondaryLabel; state.state = Tile.STATE_UNAVAILABLE; - state.icon = ResourceIcon.get(R.drawable.qs_flashlight_icon_off); + state.icon = maybeLoadResourceIcon(R.drawable.qs_flashlight_icon_off); return; } if (arg instanceof Boolean) { @@ -143,7 +143,7 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements state.contentDescription = mContext.getString(R.string.quick_settings_flashlight_label); state.expandedAccessibilityClassName = Switch.class.getName(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_flashlight_icon_on : R.drawable.qs_flashlight_icon_off); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt index 7606293454f8..43e84a0ee2b4 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FontScalingTile.kt @@ -68,7 +68,7 @@ constructor( activityStarter, qsLogger, ) { - private val icon = ResourceIcon.get(R.drawable.ic_qs_font_scaling) + private var icon: QSTile.Icon? = null override fun newTileState(): QSTile.State { return QSTile.State() @@ -108,6 +108,9 @@ constructor( } override fun handleUpdateState(state: QSTile.State?, arg: Any?) { + if (icon == null) { + icon = maybeLoadResourceIcon(R.drawable.ic_qs_font_scaling) + } state?.label = mContext.getString(R.string.quick_settings_font_scaling_label) state?.icon = icon state?.contentDescription = state?.label diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java index f723ff264e0c..48b39dcf29ba 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java @@ -106,7 +106,7 @@ public class HearingDevicesTile extends QSTileImpl<BooleanState> { checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_BLUETOOTH); state.label = mContext.getString(R.string.quick_settings_hearing_devices_label); - state.icon = ResourceIcon.get(R.drawable.qs_hearing_devices_icon); + state.icon = maybeLoadResourceIcon(R.drawable.qs_hearing_devices_icon); state.forceExpandIcon = true; boolean isBonded = mDevicesChecker.isAnyPairedHearingDevice(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java index ea3993ea88a9..03bbbd7017ae 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java @@ -151,10 +151,10 @@ public class HotspotTile extends QSTileImpl<BooleanState> { state.label = mContext.getString(R.string.quick_settings_hotspot_label); state.isTransient = isTransient; if (state.isTransient) { - state.icon = ResourceIcon.get( + state.icon = maybeLoadResourceIcon( R.drawable.qs_hotspot_icon_search); } else { - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_hotspot_icon_on : R.drawable.qs_hotspot_icon_off); } state.expandedAccessibilityClassName = Switch.class.getName(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java index 02f6f80d7282..e9c5f4ae9b10 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java @@ -529,10 +529,10 @@ public class InternetTile extends QSTileImpl<QSTile.BooleanState> { if (cb.mAirplaneModeEnabled) { if (!state.value) { state.state = Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.status_bar_airplane); } else if (!wifiConnected) { - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_unavailable); if (cb.mNoNetworksAvailable) { state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable); @@ -541,28 +541,28 @@ public class InternetTile extends QSTileImpl<QSTile.BooleanState> { r.getString(R.string.quick_settings_networks_available); } } else { - state.icon = ResourceIcon.get(cb.mWifiSignalIconId); + state.icon = maybeLoadResourceIcon(cb.mWifiSignalIconId); } } else if (cb.mNoDefaultNetwork) { if (cb.mNoNetworksAvailable || !cb.mEnabled) { - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable); } else { - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_available); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_available); state.secondaryLabel = r.getString(R.string.quick_settings_networks_available); } } else if (cb.mIsTransient) { - state.icon = ResourceIcon.get( + state.icon = maybeLoadResourceIcon( com.android.internal.R.drawable.ic_signal_wifi_transient_animation); } else if (!state.value) { state.state = Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_DISABLED); + state.icon = maybeLoadResourceIcon(WifiIcons.QS_WIFI_DISABLED); } else if (wifiConnected) { - state.icon = ResourceIcon.get(cb.mWifiSignalIconId); + state.icon = maybeLoadResourceIcon(cb.mWifiSignalIconId); } else if (wifiNotConnected) { - state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK); + state.icon = maybeLoadResourceIcon(WifiIcons.QS_WIFI_NO_NETWORK); } else { - state.icon = ResourceIcon.get(WifiIcons.QS_WIFI_NO_NETWORK); + state.icon = maybeLoadResourceIcon(WifiIcons.QS_WIFI_NO_NETWORK); } minimalContentDescription.append( mContext.getString(R.string.quick_settings_internet_label)).append(","); @@ -598,14 +598,14 @@ public class InternetTile extends QSTileImpl<QSTile.BooleanState> { if (cb.mAirplaneModeEnabled && cb.mQsTypeIcon != TelephonyIcons.ICON_CWF) { state.state = Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.status_bar_airplane); } else if (cb.mNoDefaultNetwork) { if (cb.mNoNetworksAvailable || !mSignalCallback.mWifiInfo.mEnabled) { - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_unavailable); state.secondaryLabel = r.getString(R.string.quick_settings_networks_unavailable); } else { - state.icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_available); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qs_no_internet_available); state.secondaryLabel = r.getString(R.string.quick_settings_networks_available); } } else { @@ -637,7 +637,7 @@ public class InternetTile extends QSTileImpl<QSTile.BooleanState> { final Resources r = mContext.getResources(); state.label = r.getString(R.string.quick_settings_internet_label); state.state = Tile.STATE_ACTIVE; - state.icon = ResourceIcon.get(cb.mEthernetSignalIconId); + state.icon = maybeLoadResourceIcon(cb.mEthernetSignalIconId); state.secondaryLabel = cb.mEthernetContentDescription; if (DEBUG) { Log.d(TAG, "handleUpdateEthernetState: " + "BooleanState = " + state.toString()); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java index cad5c0d12d1d..f35c25f24162 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java @@ -122,7 +122,7 @@ public class LocationTile extends QSTileImpl<BooleanState> { if (state.disabledByPolicy == false) { checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_CONFIG_LOCATION); } - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_location_icon_on : R.drawable.qs_location_icon_off); state.label = mContext.getString(R.string.quick_settings_location_label); state.contentDescription = state.label; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt index fef5a745c1ca..9c6345666403 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ModesTile.kt @@ -120,7 +120,7 @@ constructor( tileState = tileMapper.map(config, model) state?.apply { this.state = tileState.activationState.legacyState - icon = tileState.icon?.asQSTileIcon() ?: ResourceIcon.get(ICON_RES_ID) + icon = tileState.icon?.asQSTileIcon() ?: maybeLoadResourceIcon(ICON_RES_ID) label = tileLabel secondaryLabel = tileState.secondaryLabel contentDescription = tileState.contentDescription diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java index 136eea8331df..683e4e93cf4b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java @@ -55,7 +55,8 @@ public class NfcTile extends QSTileImpl<BooleanState> { public static final String TILE_SPEC = "nfc"; private static final String NFC = TILE_SPEC; - private final Icon mIcon = ResourceIcon.get(R.drawable.ic_qs_nfc); + @Nullable + private Icon mIcon = null; @Nullable private NfcAdapter mAdapter; @@ -137,6 +138,10 @@ public class NfcTile extends QSTileImpl<BooleanState> { @Override protected void handleUpdateState(BooleanState state, Object arg) { + if (mIcon == null) { + mIcon = maybeLoadResourceIcon(R.drawable.ic_qs_nfc); + } + state.value = getAdapter() != null && getAdapter().isEnabled(); state.state = getAdapter() == null ? Tile.STATE_UNAVAILABLE diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index ac762de6d544..2f5908752111 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -150,7 +150,7 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements state.label = mContext.getString(R.string.quick_settings_night_display_label); state.expandedAccessibilityClassName = Switch.class.getName(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; - state.icon = ResourceIcon.get(state.value ? R.drawable.qs_nightlight_icon_on + state.icon = maybeLoadResourceIcon(state.value ? R.drawable.qs_nightlight_icon_on : R.drawable.qs_nightlight_icon_off); state.secondaryLabel = getSecondaryLabel(state.value); state.contentDescription = TextUtils.isEmpty(state.secondaryLabel) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt index 69df0961bf66..989fc0fd6f44 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotesTile.kt @@ -40,14 +40,14 @@ import com.android.systemui.qs.tiles.viewmodel.QSTileConfigProvider import com.android.systemui.qs.tiles.viewmodel.QSTileState import com.android.systemui.res.R import javax.inject.Inject -import kotlinx.coroutines.runBlocking /** Quick settings tile: Notes */ class NotesTile -@Inject constructor( +@Inject +constructor( private val host: QSHost, private val uiEventLogger: QsEventLogger, - @Background private val backgroundLooper: Looper, + @Background private val backgroundLooper: Looper, @Main private val mainHandler: Handler, private val falsingManager: FalsingManager, private val metricsLogger: MetricsLogger, @@ -74,8 +74,7 @@ class NotesTile private lateinit var tileState: QSTileState private val config = qsTileConfigProvider.getConfig(TILE_SPEC) - override fun getTileLabel(): CharSequence = - mContext.getString(config.uiConfig.labelRes) + override fun getTileLabel(): CharSequence = mContext.getString(config.uiConfig.labelRes) override fun newTileState(): QSTile.State? { return QSTile.State().apply { state = Tile.STATE_INACTIVE } @@ -88,13 +87,12 @@ class NotesTile override fun getLongClickIntent(): Intent = userActionInteractor.longClickIntent override fun handleUpdateState(state: QSTile.State?, arg: Any?) { - val model = - if (arg is NotesTileModel) arg else dataInteractor.getCurrentTileModel() + val model = if (arg is NotesTileModel) arg else dataInteractor.getCurrentTileModel() tileState = tileMapper.map(config, model) state?.apply { this.state = tileState.activationState.legacyState - icon = ResourceIcon.get(tileState.iconRes ?: R.drawable.ic_qs_notes) + icon = maybeLoadResourceIcon(tileState.iconRes ?: R.drawable.ic_qs_notes) label = tileState.label contentDescription = tileState.contentDescription expandedAccessibilityClassName = tileState.expandedAccessibilityClassName diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java index 450c95411c3f..c605ac8d80b1 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java @@ -51,8 +51,8 @@ public class OneHandedModeTile extends QSTileImpl<BooleanState> { public static final String TILE_SPEC = "onehanded"; - private final Icon mIcon = ResourceIcon.get( - com.android.internal.R.drawable.ic_qs_one_handed_mode); + @Nullable + private Icon mIcon = null; private final UserSettingObserver mSetting; @Inject @@ -125,6 +125,10 @@ public class OneHandedModeTile extends QSTileImpl<BooleanState> { @Override protected void handleUpdateState(BooleanState state, Object arg) { + if (mIcon == null) { + mIcon = maybeLoadResourceIcon(com.android.internal.R.drawable.ic_qs_one_handed_mode); + } + final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue(); final boolean enabled = value != 0; state.value = enabled; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java index 9766fac7965e..93a51cfacf02 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QRCodeScannerTile.java @@ -119,7 +119,7 @@ public class QRCodeScannerTile extends QSTileImpl<QSTile.State> { protected void handleUpdateState(State state, Object arg) { state.label = mContext.getString(R.string.qr_code_scanner_title); state.contentDescription = state.label; - state.icon = ResourceIcon.get(R.drawable.ic_qr_code_scanner); + state.icon = maybeLoadResourceIcon(R.drawable.ic_qr_code_scanner); state.state = mQRCodeScannerController.isAbleToLaunchScannerActivity() ? Tile.STATE_INACTIVE : Tile.STATE_UNAVAILABLE; // The assumption is that if the OEM has the QR code scanner module enabled then the scanner diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java index 37d24debe958..3d039e6ef824 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java @@ -154,7 +154,7 @@ public class QuickAccessWalletTile extends QSTileImpl<QSTile.State> { Drawable tileIcon = mController.getWalletClient().getTileIcon(); state.icon = tileIcon == null - ? ResourceIcon.get(R.drawable.ic_wallet_lockscreen) + ? maybeLoadResourceIcon(R.drawable.ic_wallet_lockscreen) : new DrawableIcon(tileIcon); boolean isDeviceLocked = !mKeyguardStateController.isUnlocked(); if (mController.getWalletClient().isWalletServiceAvailable() diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt index 028ac6f4ac18..ca9d96ebf3e3 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt @@ -221,13 +221,13 @@ constructor( state = Tile.STATE_ACTIVE forceExpandIcon = false secondaryLabel = mContext.getString(R.string.qs_record_issue_stop) - icon = ResourceIcon.get(R.drawable.qs_record_issue_icon_on) + icon = maybeLoadResourceIcon(R.drawable.qs_record_issue_icon_on) } else { value = false state = Tile.STATE_INACTIVE forceExpandIcon = true secondaryLabel = mContext.getString(R.string.qs_record_issue_start) - icon = ResourceIcon.get(R.drawable.qs_record_issue_icon_off) + icon = maybeLoadResourceIcon(R.drawable.qs_record_issue_icon_off) } label = tileLabel contentDescription = diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java index d624d989f42a..26d43ee92bbc 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ReduceBrightColorsTile.java @@ -141,7 +141,7 @@ public class ReduceBrightColorsTile extends QSTileImpl<QSTile.BooleanState> state.label = mContext.getString(R.string.reduce_bright_colors_feature_name); state.expandedAccessibilityClassName = Switch.class.getName(); state.contentDescription = state.label; - state.icon = ResourceIcon.get(state.value + state.icon = maybeLoadResourceIcon(state.value ? drawable.qs_extra_dim_icon_on : drawable.qs_extra_dim_icon_off); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java index 35e43b6fed9e..e361bb8ce883 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java @@ -63,7 +63,8 @@ public class RotationLockTile extends QSTileImpl<BooleanState> implements private static final String EMPTY_SECONDARY_STRING = ""; - private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_auto_rotate); + private final Icon mIcon = + maybeLoadResourceIcon(com.android.internal.R.drawable.ic_qs_auto_rotate); private final RotationLockController mController; private final SensorPrivacyManager mPrivacyManager; private final BatteryController mBatteryController; @@ -153,13 +154,13 @@ public class RotationLockTile extends QSTileImpl<BooleanState> implements && mController.isCameraRotationEnabled(); state.value = !rotationLocked; state.label = mContext.getString(R.string.quick_settings_rotation_unlocked_label); - state.icon = ResourceIcon.get(R.drawable.qs_auto_rotate_icon_off); + state.icon = maybeLoadResourceIcon(R.drawable.qs_auto_rotate_icon_off); state.contentDescription = getAccessibilityString(rotationLocked); if (!rotationLocked) { state.secondaryLabel = cameraRotation ? mContext.getResources().getString( R.string.rotation_lock_camera_rotation_on) : EMPTY_SECONDARY_STRING; - state.icon = ResourceIcon.get(R.drawable.qs_auto_rotate_icon_on); + state.icon = maybeLoadResourceIcon(R.drawable.qs_auto_rotate_icon_on); } else { state.secondaryLabel = EMPTY_SECONDARY_STRING; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java index f3be340f4951..6b0287ef6848 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java @@ -138,9 +138,8 @@ public class ScreenRecordTile extends QSTileImpl<QSTile.BooleanState> state.value = isRecording || isStarting; state.state = (isRecording || isStarting) ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.quick_settings_screen_record_label); - state.icon = ResourceIcon.get(state.value - ? R.drawable.qs_screen_record_icon_on - : R.drawable.qs_screen_record_icon_off); + state.icon = maybeLoadResourceIcon(state.value + ? R.drawable.qs_screen_record_icon_on : R.drawable.qs_screen_record_icon_off); // Show expand icon when clicking will open a dialog state.forceExpandIcon = state.state == Tile.STATE_INACTIVE; diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java index 036ce080c543..b62e858e6ade 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/SensorPrivacyToggleTile.java @@ -119,7 +119,7 @@ public abstract class SensorPrivacyToggleTile extends QSTileImpl<QSTile.BooleanS checkIfRestrictionEnforcedByAdminOnly(state, getRestriction()); - state.icon = ResourceIcon.get(getIconRes(isBlocked)); + state.icon = maybeLoadResourceIcon(getIconRes(isBlocked)); state.state = isBlocked ? Tile.STATE_INACTIVE : Tile.STATE_ACTIVE; state.value = !isBlocked; state.label = getTileLabel(); diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java index bec6581e54c9..410f0503ea1f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -166,7 +166,7 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements } else { state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } - state.icon = ResourceIcon.get(state.state == Tile.STATE_ACTIVE + state.icon = maybeLoadResourceIcon(state.state == Tile.STATE_ACTIVE ? R.drawable.qs_light_dark_theme_icon_on : R.drawable.qs_light_dark_theme_icon_off); state.expandedAccessibilityClassName = Switch.class.getName(); 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 1750347fd2ae..f6f89f759e0d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WorkModeTile.java @@ -53,8 +53,8 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements public static final String TILE_SPEC = "work"; - private final Icon mIcon = ResourceIcon.get( - com.android.internal.R.drawable.stat_sys_managed_profile_status); + @Nullable + private Icon mIcon = null; private final ManagedProfileController mProfileController; @@ -129,6 +129,11 @@ public class WorkModeTile extends QSTileImpl<BooleanState> implements state.value = mProfileController.isWorkModeEnabled(); } + if (mIcon == null) { + mIcon = maybeLoadResourceIcon( + com.android.internal.R.drawable.stat_sys_managed_profile_status); + } + state.icon = mIcon; state.label = getTileLabel(); state.contentDescription = state.label; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt index ed0eb6d44508..d3e37119fdcb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.model +import android.annotation.SuppressLint import android.content.Context import android.graphics.drawable.Drawable import android.service.quicksettings.Tile @@ -36,6 +37,7 @@ sealed interface InternetTileModel { val stateDescription: ContentDescription? val contentDescription: ContentDescription? + @SuppressLint("UseCompatLoadingForDrawables") fun applyTo(state: QSTile.BooleanState, context: Context) { if (secondaryLabel != null) { state.secondaryLabel = secondaryLabel.loadText(context) @@ -50,7 +52,7 @@ sealed interface InternetTileModel { if (icon != null) { state.icon = icon } else if (iconId != null) { - state.icon = QSTileImpl.ResourceIcon.get(iconId!!) + state.icon = QSTileImpl.maybeLoadResourceIcon(iconId!!, context) } state.state = |