New QS Flashlight Tile Animated Icons
Fixes: 245549760 Test: atest FlashlightTileTest Change-Id: I7f6c9efe904fa217c08242e0fa8019875a40fdf5
This commit is contained in:
84
packages/SystemUI/res/drawable/qs_flashlight_icon_off.xml
Normal file
84
packages/SystemUI/res/drawable/qs_flashlight_icon_off.xml
Normal 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>
|
||||
84
packages/SystemUI/res/drawable/qs_flashlight_icon_on.xml
Normal file
84
packages/SystemUI/res/drawable/qs_flashlight_icon_on.xml
Normal 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>
|
||||
@@ -43,11 +43,12 @@ import com.android.systemui.statusbar.policy.FlashlightController;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/** Quick settings tile: Control flashlight **/
|
||||
/**
|
||||
* Quick settings tile: Control flashlight
|
||||
**/
|
||||
public class FlashlightTile extends QSTileImpl<BooleanState> implements
|
||||
FlashlightController.FlashlightListener {
|
||||
|
||||
private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_flashlight);
|
||||
private final FlashlightController mFlashlightController;
|
||||
|
||||
@Inject
|
||||
@@ -116,19 +117,15 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
|
||||
|
||||
@Override
|
||||
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.secondaryLabel = "";
|
||||
state.stateDescription = "";
|
||||
if (!mFlashlightController.isAvailable()) {
|
||||
state.icon = mIcon;
|
||||
state.slash.isSlashed = true;
|
||||
state.secondaryLabel = mContext.getString(
|
||||
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);
|
||||
return;
|
||||
}
|
||||
if (arg instanceof Boolean) {
|
||||
@@ -140,11 +137,11 @@ public class FlashlightTile extends QSTileImpl<BooleanState> implements
|
||||
} else {
|
||||
state.value = mFlashlightController.isEnabled();
|
||||
}
|
||||
state.icon = mIcon;
|
||||
state.slash.isSlashed = !state.value;
|
||||
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
|
||||
? R.drawable.qs_flashlight_icon_on : R.drawable.qs_flashlight_icon_off);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user