Merge "New QS Flashlight Tile Animated Icons" into tm-qpr-dev

This commit is contained in:
Rasheed Lewis
2022-09-20 00:08:59 +00:00
committed by Android (Google) Code Review
4 changed files with 282 additions and 9 deletions

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator
android:duration="417"
android:propertyName="pathData"
android:startOffset="0"
android:valueFrom="M0 2.02 C0.42,2.02 0.77,1.88 1.05,1.59 C1.35,1.29 1.5,0.94 1.5,0.52 C1.5,0.1 1.35,-0.25 1.05,-0.53 C0.77,-0.83 0.42,-0.98 0,-0.98 C-0.42,-0.98 -0.78,-0.83 -1.08,-0.53 C-1.36,-0.25 -1.5,0.1 -1.5,0.52 C-1.5,0.94 -1.36,1.29 -1.08,1.59 C-0.78,1.88 -0.42,2.02 0,2.02c M0 8.62 C-0.42,8.62 -2.78,8.82 -3.07,8.54 C-3.36,8.24 -3.37,-1.87 -3.37,-2.28 C-4.25,-2.69 -4.29,-5.2 -4.01,-5.48 C-3.71,-5.78 -0.42,-5.75 0,-5.75 C0.42,-5.75 4.39,-5.78 4.36,-5.36 C4.22,-2.97 4.47,-3.03 3.34,-1.78 C3.07,-1.48 3.32,8.21 3.02,8.51 C2.74,8.79 0.42,8.62 0,8.62c "
android:valueTo="M0 3 C0.42,3 0.77,2.86 1.05,2.58 C1.35,2.28 1.5,1.92 1.5,1.5 C1.5,1.08 1.35,0.73 1.05,0.45 C0.77,0.15 0.42,0 0,0 C-0.42,0 -0.78,0.15 -1.08,0.45 C-1.36,0.73 -1.5,1.08 -1.5,1.5 C-1.5,1.92 -1.36,2.28 -1.08,2.58 C-0.78,2.86 -0.42,3 0,3c M0 8.62 C-0.42,8.62 -2.24,8.83 -2.54,8.55 C-2.83,8.25 -2.86,9.1 -2.86,8.69 C-2.86,8.27 -3.02,8.85 -2.74,8.57 C-2.44,8.26 -0.43,8.31 -0.02,8.31 C0.4,8.31 2.4,8.17 2.68,8.47 C2.98,8.75 2.93,8.33 2.93,8.75 C2.93,9.17 3.32,8.21 3.02,8.51 C2.74,8.79 0.42,8.62 0,8.62c "
android:valueType="pathType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.1,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator
android:duration="1000"
android:propertyName="translateX"
android:startOffset="0"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
</aapt:attr>
</target>
<aapt:attr name="android:drawable">
<vector
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<group android:name="_R_G">
<group
android:name="_R_G_L_1_G"
android:pivotY="24"
android:scaleX="0.33332999999999996"
android:scaleY="0.33332999999999996"
android:translateX="12"
android:translateY="-4">
<path
android:name="_R_G_L_1_G_D_0_P_0"
android:fillAlpha="1"
android:fillColor="#1f1f1f"
android:fillType="nonZero"
android:pathData=" M-12 -15 C-12,-15 12,-15 12,-15 C12,-15 12,-13.8 12,-13.8 C12,-13.8 6,-4.8 6,-4.8 C6,-4.8 6,24 6,24 C6,24 -6,24 -6,24 C-6,24 -6,-4.8 -6,-4.8 C-6,-4.8 -12,-13.8 -12,-13.8 C-12,-13.8 -12,-15 -12,-15c M12 -21 C12,-21 -12,-21 -12,-21 C-12,-21 -12,-24 -12,-24 C-12,-24 12,-24 12,-24 C12,-24 12,-21 12,-21c M-12 -3 C-12,-3 -12,30 -12,30 C-12,30 12,30 12,30 C12,30 12,-3 12,-3 C12,-3 18,-12 18,-12 C18,-12 18,-30 18,-30 C18,-30 -18,-30 -18,-30 C-18,-30 -18,-12 -18,-12 C-18,-12 -12,-3 -12,-3c " />
</group>
<group
android:name="_R_G_L_0_G"
android:translateX="12"
android:translateY="12">
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="1"
android:fillColor="#1f1f1f"
android:fillType="nonZero"
android:pathData=" M0 2.02 C0.42,2.02 0.77,1.88 1.05,1.59 C1.35,1.29 1.5,0.94 1.5,0.52 C1.5,0.1 1.35,-0.25 1.05,-0.53 C0.77,-0.83 0.42,-0.98 0,-0.98 C-0.42,-0.98 -0.78,-0.83 -1.08,-0.53 C-1.36,-0.25 -1.5,0.1 -1.5,0.52 C-1.5,0.94 -1.36,1.29 -1.08,1.59 C-0.78,1.88 -0.42,2.02 0,2.02c " />
</group>
</group>
<group android:name="time_group" />
</vector>
</aapt:attr>
</animated-vector>

View File

@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Copyright (C) 2022 The Android Open Source Project
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<target android:name="_R_G_L_0_G_D_0_P_0">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator
android:duration="417"
android:propertyName="pathData"
android:startOffset="0"
android:valueFrom="M0 3 C0.42,3 0.77,2.86 1.05,2.58 C1.35,2.28 1.5,1.92 1.5,1.5 C1.5,1.08 1.35,0.73 1.05,0.45 C0.77,0.15 0.42,0 0,0 C-0.42,0 -0.78,0.15 -1.08,0.45 C-1.36,0.73 -1.5,1.08 -1.5,1.5 C-1.5,1.92 -1.36,2.28 -1.08,2.58 C-0.78,2.86 -0.42,3 0,3c M0 8.62 C-0.42,8.62 -2.24,8.83 -2.54,8.55 C-2.83,8.25 -2.86,9.1 -2.86,8.69 C-2.86,8.27 -3.02,8.85 -2.74,8.57 C-2.44,8.26 -0.43,8.31 -0.02,8.31 C0.4,8.31 2.4,8.17 2.68,8.47 C2.98,8.75 2.93,8.33 2.93,8.75 C2.93,9.17 3.32,8.21 3.02,8.51 C2.74,8.79 0.42,8.62 0,8.62c "
android:valueTo="M0 2.02 C0.42,2.02 0.77,1.88 1.05,1.59 C1.35,1.29 1.5,0.94 1.5,0.52 C1.5,0.1 1.35,-0.25 1.05,-0.53 C0.77,-0.83 0.42,-0.98 0,-0.98 C-0.42,-0.98 -0.78,-0.83 -1.08,-0.53 C-1.36,-0.25 -1.5,0.1 -1.5,0.52 C-1.5,0.94 -1.36,1.29 -1.08,1.59 C-0.78,1.88 -0.42,2.02 0,2.02c M0 8.62 C-0.42,8.62 -2.78,8.82 -3.07,8.54 C-3.36,8.24 -3.37,-1.87 -3.37,-2.28 C-4.25,-2.69 -4.29,-5.2 -4.01,-5.48 C-3.71,-5.78 -0.42,-5.75 0,-5.75 C0.42,-5.75 4.39,-5.78 4.36,-5.36 C4.22,-2.97 4.47,-3.03 3.34,-1.78 C3.07,-1.48 3.32,8.21 3.02,8.51 C2.74,8.79 0.42,8.62 0,8.62c "
android:valueType="pathType">
<aapt:attr name="android:interpolator">
<pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.1,1 1.0,1.0" />
</aapt:attr>
</objectAnimator>
</set>
</aapt:attr>
</target>
<target android:name="time_group">
<aapt:attr name="android:animation">
<set android:ordering="together">
<objectAnimator
android:duration="1000"
android:propertyName="translateX"
android:startOffset="0"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
</set>
</aapt:attr>
</target>
<aapt:attr name="android:drawable">
<vector
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<group android:name="_R_G">
<group
android:name="_R_G_L_1_G"
android:pivotY="24"
android:scaleX="0.33332999999999996"
android:scaleY="0.33332999999999996"
android:translateX="12"
android:translateY="-4">
<path
android:name="_R_G_L_1_G_D_0_P_0"
android:fillAlpha="1"
android:fillColor="#1f1f1f"
android:fillType="nonZero"
android:pathData=" M-12 -15 C-12,-15 12,-15 12,-15 C12,-15 12,-13.8 12,-13.8 C12,-13.8 6,-4.8 6,-4.8 C6,-4.8 6,24 6,24 C6,24 -6,24 -6,24 C-6,24 -6,-4.8 -6,-4.8 C-6,-4.8 -12,-13.8 -12,-13.8 C-12,-13.8 -12,-15 -12,-15c M12 -21 C12,-21 -12,-21 -12,-21 C-12,-21 -12,-24 -12,-24 C-12,-24 12,-24 12,-24 C12,-24 12,-21 12,-21c M-12 -3 C-12,-3 -12,30 -12,30 C-12,30 12,30 12,30 C12,30 12,-3 12,-3 C12,-3 18,-12 18,-12 C18,-12 18,-30 18,-30 C18,-30 -18,-30 -18,-30 C-18,-30 -18,-12 -18,-12 C-18,-12 -12,-3 -12,-3c " />
</group>
<group
android:name="_R_G_L_0_G"
android:translateX="12"
android:translateY="12">
<path
android:name="_R_G_L_0_G_D_0_P_0"
android:fillAlpha="1"
android:fillColor="#1f1f1f"
android:fillType="nonZero"
android:pathData=" M0 3 C0.42,3 0.77,2.86 1.05,2.58 C1.35,2.28 1.5,1.92 1.5,1.5 C1.5,1.08 1.35,0.73 1.05,0.45 C0.77,0.15 0.42,0 0,0 C-0.42,0 -0.78,0.15 -1.08,0.45 C-1.36,0.73 -1.5,1.08 -1.5,1.5 C-1.5,1.92 -1.36,2.28 -1.08,2.58 C-0.78,2.86 -0.42,3 0,3c " />
</group>
</group>
<group android:name="time_group" />
</vector>
</aapt:attr>
</animated-vector>

View File

@@ -43,11 +43,12 @@ import com.android.systemui.statusbar.policy.FlashlightController;
import javax.inject.Inject; import javax.inject.Inject;
/** Quick settings tile: Control flashlight **/ /**
* Quick settings tile: Control flashlight
**/
public class FlashlightTile extends QSTileImpl<BooleanState> implements public class FlashlightTile extends QSTileImpl<BooleanState> implements
FlashlightController.FlashlightListener { FlashlightController.FlashlightListener {
private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_flashlight);
private final FlashlightController mFlashlightController; private final FlashlightController mFlashlightController;
@Inject @Inject
@@ -116,19 +117,15 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
@Override @Override
protected void handleUpdateState(BooleanState state, Object arg) { protected void handleUpdateState(BooleanState state, Object arg) {
if (state.slash == null) {
state.slash = new SlashState();
}
state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label); state.label = mHost.getContext().getString(R.string.quick_settings_flashlight_label);
state.secondaryLabel = ""; state.secondaryLabel = "";
state.stateDescription = ""; state.stateDescription = "";
if (!mFlashlightController.isAvailable()) { if (!mFlashlightController.isAvailable()) {
state.icon = mIcon;
state.slash.isSlashed = true;
state.secondaryLabel = mContext.getString( state.secondaryLabel = mContext.getString(
R.string.quick_settings_flashlight_camera_in_use); R.string.quick_settings_flashlight_camera_in_use);
state.stateDescription = state.secondaryLabel; state.stateDescription = state.secondaryLabel;
state.state = Tile.STATE_UNAVAILABLE; state.state = Tile.STATE_UNAVAILABLE;
state.icon = ResourceIcon.get(R.drawable.qs_flashlight_icon_off);
return; return;
} }
if (arg instanceof Boolean) { if (arg instanceof Boolean) {
@@ -140,11 +137,11 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
} else { } else {
state.value = mFlashlightController.isEnabled(); state.value = mFlashlightController.isEnabled();
} }
state.icon = mIcon;
state.slash.isSlashed = !state.value;
state.contentDescription = mContext.getString(R.string.quick_settings_flashlight_label); state.contentDescription = mContext.getString(R.string.quick_settings_flashlight_label);
state.expandedAccessibilityClassName = Switch.class.getName(); state.expandedAccessibilityClassName = Switch.class.getName();
state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
state.icon = ResourceIcon.get(state.value
? R.drawable.qs_flashlight_icon_on : R.drawable.qs_flashlight_icon_off);
} }
@Override @Override

View File

@@ -0,0 +1,108 @@
package com.android.systemui.qs.tiles
import android.content.Context
import android.os.Handler
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSTileHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.qs.tileimpl.QSTileImpl
import com.android.systemui.statusbar.policy.FlashlightController
import com.google.common.truth.Truth
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
class FlashlightTileTest : SysuiTestCase() {
@Mock private lateinit var mockContext: Context
@Mock private lateinit var qsLogger: QSLogger
@Mock private lateinit var qsHost: QSTileHost
@Mock private lateinit var metricsLogger: MetricsLogger
@Mock private lateinit var statusBarStateController: StatusBarStateController
@Mock private lateinit var activityStarter: ActivityStarter
@Mock private lateinit var flashlightController: FlashlightController
private val uiEventLogger = UiEventLoggerFake()
private val falsingManager = FalsingManagerFake()
private lateinit var testableLooper: TestableLooper
private lateinit var tile: FlashlightTile
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
Mockito.`when`(qsHost.context).thenReturn(mockContext)
Mockito.`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
tile =
FlashlightTile(
qsHost,
testableLooper.looper,
Handler(testableLooper.looper),
falsingManager,
metricsLogger,
statusBarStateController,
activityStarter,
qsLogger,
flashlightController
)
}
@Test
fun testIcon_whenFlashlightEnabled_isOnState() {
Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
Mockito.`when`(flashlightController.isEnabled).thenReturn(true)
val state = QSTile.BooleanState()
tile.handleUpdateState(state, /* arg= */ null)
Truth.assertThat(state.icon)
.isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_flashlight_icon_on))
}
@Test
fun testIcon_whenFlashlightDisabled_isOffState() {
Mockito.`when`(flashlightController.isAvailable).thenReturn(true)
Mockito.`when`(flashlightController.isEnabled).thenReturn(false)
val state = QSTile.BooleanState()
tile.handleUpdateState(state, /* arg= */ null)
Truth.assertThat(state.icon)
.isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_flashlight_icon_off))
}
@Test
fun testIcon_whenFlashlightUnavailable_isOffState() {
Mockito.`when`(flashlightController.isAvailable).thenReturn(false)
val state = QSTile.BooleanState()
tile.handleUpdateState(state, /* arg= */ null)
Truth.assertThat(state.icon)
.isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_flashlight_icon_off))
}
}