diff options
9 files changed, 285 insertions, 1 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 5bb490336f5d..fca1fa576f55 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -997,6 +997,21 @@ public final class Settings { "android.settings.BLUETOOTH_SETTINGS"; /** + * Activity Action: Show settings to allow configuration of Hearing Devices. + * <p> + * In some cases, a matching Activity may not exist, so ensure you + * safeguard against this. + * <p> + * Input: Nothing. + * <p> + * Output: Nothing. + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_HEARING_DEVICES_SETTINGS = + "android.settings.HEARING_DEVICES_SETTINGS"; + + /** * Activity action: Show Settings app search UI when this action is available for device. * <p> * Input: Nothing. diff --git a/packages/SystemUI/res/drawable/qs_hearing_devices_icon.xml b/packages/SystemUI/res/drawable/qs_hearing_devices_icon.xml new file mode 100644 index 000000000000..c1573a3ae5ac --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_hearing_devices_icon.xml @@ -0,0 +1,25 @@ +<!-- + Copyright (C) 2024 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. +--> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18dp" + android:height="18dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#ffffff" + android:pathData="M17,20c-0.29,0 -0.56,-0.06 -0.76,-0.15 -0.71,-0.37 -1.21,-0.88 -1.71,-2.38 -0.51,-1.56 -1.47,-2.29 -2.39,-3 -0.79,-0.61 -1.61,-1.24 -2.32,-2.53C9.29,10.98 9,9.93 9,9c0,-2.8 2.2,-5 5,-5s5,2.2 5,5h2c0,-3.93 -3.07,-7 -7,-7S7,5.07 7,9c0,1.26 0.38,2.65 1.07,3.9 0.91,1.65 1.98,2.48 2.85,3.15 0.81,0.62 1.39,1.07 1.71,2.05 0.6,1.82 1.37,2.84 2.73,3.55 0.51,0.23 1.07,0.35 1.64,0.35 2.21,0 4,-1.79 4,-4h-2c0,1.1 -0.9,2 -2,2zM7.64,2.64L6.22,1.22C4.23,3.21 3,5.96 3,9s1.23,5.79 3.22,7.78l1.41,-1.41C6.01,13.74 5,11.49 5,9s1.01,-4.74 2.64,-6.36zM11.5,9c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5 -2.5,1.12 -2.5,2.5z"/> +</vector>
\ No newline at end of file diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 35f6a08795bc..a6f6d4dcf2f9 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -101,7 +101,7 @@ <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" --> <string name="quick_settings_tiles_stock" translatable="false"> - internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream,font_scaling,record_issue + internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,color_correction,dream,font_scaling,record_issue,hearing_devices </string> <!-- The tiles to display in QuickSettings --> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index a9151e88facc..71679f9e6f96 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -899,6 +899,9 @@ <!-- QuickSettings: Contrast tile description: high [CHAR LIMIT=NONE] --> <string name="quick_settings_contrast_high">High</string> + <!-- QuickSettings: Hearing devices [CHAR LIMIT=NONE] --> + <string name="quick_settings_hearing_devices_label">Hearing devices</string> + <!--- Title of dialog triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=150] --> <string name="sensor_privacy_start_use_mic_dialog_title">Unblock device microphone?</string> <!--- Title of dialog triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=150] --> diff --git a/packages/SystemUI/res/values/tiles_states_strings.xml b/packages/SystemUI/res/values/tiles_states_strings.xml index 9036a35846af..ad09b466dd3e 100644 --- a/packages/SystemUI/res/values/tiles_states_strings.xml +++ b/packages/SystemUI/res/values/tiles_states_strings.xml @@ -338,4 +338,14 @@ <item>Off</item> <item>On</item> </string-array> + + <!-- State names for hearing devices tile: unavailable, off, on. + This subtitle is shown when the tile is in that particular state but does not set its own + subtitle, so some of these may never appear on screen. They should still be translated as + if they could appear. [CHAR LIMIT=32] --> + <string-array name="tile_states_hearing_devices"> + <item>Unavailable</item> + <item>Off</item> + <item>On</item> + </string-array> </resources>
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt index 4047623a4b2f..7cb028abba60 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt +++ b/packages/SystemUI/src/com/android/systemui/accessibility/qs/QSAccessibilityModule.kt @@ -23,6 +23,7 @@ import com.android.systemui.qs.tiles.ColorCorrectionTile import com.android.systemui.qs.tiles.ColorInversionTile import com.android.systemui.qs.tiles.DreamTile import com.android.systemui.qs.tiles.FontScalingTile +import com.android.systemui.qs.tiles.HearingDevicesTile import com.android.systemui.qs.tiles.NightDisplayTile import com.android.systemui.qs.tiles.OneHandedModeTile import com.android.systemui.qs.tiles.ReduceBrightColorsTile @@ -94,6 +95,12 @@ interface QSAccessibilityModule { @StringKey(FontScalingTile.TILE_SPEC) fun bindFontScalingTile(fontScalingTile: FontScalingTile): QSTileImpl<*> + /** Inject HearingDevicesTile into tileMap in QSModule */ + @Binds + @IntoMap + @StringKey(HearingDevicesTile.TILE_SPEC) + fun bindHearingDevicesTile(hearingDevicesTile: HearingDevicesTile): QSTileImpl<*> + companion object { const val COLOR_CORRECTION_TILE_SPEC = "color_correction" const val COLOR_INVERSION_TILE_SPEC = "inversion" diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt index 15b8cfb3834d..f34389ec8cb5 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/SubtitleArrayMapping.kt @@ -52,6 +52,7 @@ object SubtitleArrayMapping { subtitleIdsMap["color_correction"] = R.array.tile_states_color_correction subtitleIdsMap["dream"] = R.array.tile_states_dream subtitleIdsMap["font_scaling"] = R.array.tile_states_font_scaling + subtitleIdsMap["hearing_devices"] = R.array.tile_states_hearing_devices } /** Get the subtitle resource id of the given tile */ diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java new file mode 100644 index 000000000000..1fb701e95b85 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HearingDevicesTile.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2024 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. + */ + +package com.android.systemui.qs.tiles; + +import android.content.Intent; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.view.View; + +import androidx.annotation.Nullable; + +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.Flags; +import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.plugins.qs.QSTile.State; +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 javax.inject.Inject; + +/** Quick settings tile: Hearing Devices **/ +public class HearingDevicesTile extends QSTileImpl<State> { + + public static final String TILE_SPEC = "hearing_devices"; + + @Inject + public HearingDevicesTile( + QSHost host, + QsEventLogger uiEventLogger, + @Background Looper backgroundLooper, + @Main Handler mainHandler, + FalsingManager falsingManager, + MetricsLogger metricsLogger, + StatusBarStateController statusBarStateController, + ActivityStarter activityStarter, + QSLogger qsLogger + ) { + super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger, + statusBarStateController, activityStarter, qsLogger); + } + + @Override + public State newTileState() { + return new State(); + } + + @Override + protected void handleClick(@Nullable View view) { + + } + + @Override + protected void handleUpdateState(State state, Object arg) { + state.label = mContext.getString(R.string.quick_settings_hearing_devices_label); + state.icon = ResourceIcon.get(R.drawable.qs_hearing_devices_icon); + } + + @Nullable + @Override + public Intent getLongClickIntent() { + return new Intent(Settings.ACTION_HEARING_DEVICES_SETTINGS); + } + + @Override + public CharSequence getTileLabel() { + return mContext.getString(R.string.quick_settings_hearing_devices_label); + } + + @Override + public boolean isAvailable() { + return Flags.hearingAidsQsTileDialog(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java new file mode 100644 index 000000000000..326df5c07b85 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/HearingDevicesTileTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2024 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. + */ + +package com.android.systemui.qs.tiles; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.verify; + +import android.content.Intent; +import android.os.Handler; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.provider.Settings; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import com.android.internal.logging.MetricsLogger; +import com.android.systemui.Flags; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.classifier.FalsingManagerFake; +import com.android.systemui.plugins.ActivityStarter; +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 org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +/** Tests for {@link HearingDevicesTile}. */ +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +public class HearingDevicesTileTest extends SysuiTestCase { + + @Rule + public MockitoRule mockito = MockitoJUnit.rule(); + + @Mock + private QSHost mHost; + @Mock + private QsEventLogger mUiEventLogger; + @Mock + private MetricsLogger mMetricsLogger; + @Mock + private StatusBarStateController mStatusBarStateController; + @Mock + private ActivityStarter mActivityStarter; + @Mock + private QSLogger mQSLogger; + + private TestableLooper mTestableLooper; + private HearingDevicesTile mTile; + + @Before + public void setUp() throws Exception { + mTestableLooper = TestableLooper.get(this); + + mTile = new HearingDevicesTile( + mHost, + mUiEventLogger, + mTestableLooper.getLooper(), + new Handler(mTestableLooper.getLooper()), + new FalsingManagerFake(), + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQSLogger); + + mTile.initialize(); + mTestableLooper.processAllMessages(); + } + + @After + public void tearDown() { + mTile.destroy(); + mTestableLooper.processAllMessages(); + } + + @Test + @EnableFlags(Flags.FLAG_HEARING_AIDS_QS_TILE_DIALOG) + public void isAvailable_flagEnabled_true() { + assertThat(mTile.isAvailable()).isTrue(); + } + + @Test + @DisableFlags(Flags.FLAG_HEARING_AIDS_QS_TILE_DIALOG) + public void isAvailable_flagDisabled_false() { + assertThat(mTile.isAvailable()).isFalse(); + } + + @Test + public void longClick_expectedAction() { + mTile.longClick(null); + mTestableLooper.processAllMessages(); + + ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mActivityStarter).postStartActivityDismissingKeyguard(IntentCaptor.capture(), + anyInt(), any()); + assertThat(IntentCaptor.getValue().getAction()).isEqualTo( + Settings.ACTION_HEARING_DEVICES_SETTINGS); + } +} |