diff options
10 files changed, 243 insertions, 48 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingFooterPreference.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingFooterPreference.java new file mode 100644 index 000000000000..2099b33b78b5 --- /dev/null +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingFooterPreference.java @@ -0,0 +1,134 @@ +/* + * 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.settingslib.bluetooth.devicesettings; + +import android.os.Bundle; +import android.os.Parcel; +import android.os.Parcelable; + +import androidx.annotation.NonNull; + +/** A data class representing a footer preference. */ +public class DeviceSettingFooterPreference extends DeviceSettingPreference implements Parcelable { + + private final String mFooterText; + private final Bundle mExtras; + + DeviceSettingFooterPreference( + @NonNull String footerText, + Bundle extras) { + super(DeviceSettingType.DEVICE_SETTING_TYPE_MULTI_TOGGLE); + mFooterText = footerText; + mExtras = extras; + } + + /** Read a {@link DeviceSettingFooterPreference} from {@link Parcel}. */ + @NonNull + public static DeviceSettingFooterPreference readFromParcel(@NonNull Parcel in) { + String footerText = in.readString(); + Bundle extras = in.readBundle(Bundle.class.getClassLoader()); + return new DeviceSettingFooterPreference(footerText, extras); + } + + public static final Creator<DeviceSettingFooterPreference> CREATOR = + new Creator<>() { + @Override + @NonNull + public DeviceSettingFooterPreference createFromParcel(@NonNull Parcel in) { + in.readInt(); + return readFromParcel(in); + } + + @Override + @NonNull + public DeviceSettingFooterPreference[] newArray(int size) { + return new DeviceSettingFooterPreference[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString(mFooterText); + dest.writeBundle(mExtras); + } + + /** Builder class for {@link DeviceSettingFooterPreference}. */ + public static final class Builder { + private String mFooterText = ""; + private Bundle mExtras = Bundle.EMPTY; + + /** + * Sets the footer text of the preference. + * + * @param footerText The footer text of the preference. + * @return Returns the Builder object. + */ + @NonNull + public DeviceSettingFooterPreference.Builder setFooterText(@NonNull String footerText) { + mFooterText = footerText; + return this; + } + + /** + * Sets the extras bundle. + * + * @return Returns the Builder object. + */ + @NonNull + public DeviceSettingFooterPreference.Builder setExtras(@NonNull Bundle extras) { + mExtras = extras; + return this; + } + + /** + * Builds the {@link DeviceSettingFooterPreference} object. + * + * @return Returns the built {@link DeviceSettingFooterPreference} object. + */ + @NonNull + public DeviceSettingFooterPreference build() { + return new DeviceSettingFooterPreference( + mFooterText, mExtras); + } + } + + /** + * Gets the footer text of the preference. + * + * @return The footer text. + */ + @NonNull + public String getFooterText() { + return mFooterText; + } + + /** + * Gets the extras Bundle. + * + * @return Returns a Bundle object. + */ + @NonNull + public Bundle getExtras() { + return mExtras; + } +} diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPreference.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPreference.java index 790939a18a0c..4b67ef78c014 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingPreference.java @@ -40,6 +40,8 @@ public abstract class DeviceSettingPreference { return ActionSwitchPreference.readFromParcel(in); case DeviceSettingType.DEVICE_SETTING_TYPE_MULTI_TOGGLE: return MultiTogglePreference.readFromParcel(in); + case DeviceSettingType.DEVICE_SETTING_TYPE_FOOTER: + return DeviceSettingFooterPreference.readFromParcel(in); default: return UNKNOWN; } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java index ee4d90fe4171..441e3f86708d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingType.java @@ -27,6 +27,7 @@ import java.lang.annotation.RetentionPolicy; DeviceSettingType.DEVICE_SETTING_TYPE_UNKNOWN, DeviceSettingType.DEVICE_SETTING_TYPE_ACTION_SWITCH, DeviceSettingType.DEVICE_SETTING_TYPE_MULTI_TOGGLE, + DeviceSettingType.DEVICE_SETTING_TYPE_FOOTER, }, open = true) public @interface DeviceSettingType { @@ -38,4 +39,7 @@ public @interface DeviceSettingType { /** Device setting type is multi-toggle preference. */ int DEVICE_SETTING_TYPE_MULTI_TOGGLE = 2; + + /** Device setting type is footer preference. */ + int DEVICE_SETTING_TYPE_FOOTER = 3; } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfig.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfig.kt index c8a2e9ca3af1..127275fe28d2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfig.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfig.kt @@ -31,7 +31,6 @@ import android.os.Parcelable data class DeviceSettingsConfig( val mainContentItems: List<DeviceSettingItem>, val moreSettingsItems: List<DeviceSettingItem>, - val moreSettingsFooter: String, val extras: Bundle = Bundle.EMPTY, ) : Parcelable { @@ -41,7 +40,6 @@ data class DeviceSettingsConfig( parcel.run { writeTypedList(mainContentItems) writeTypedList(moreSettingsItems) - writeString(moreSettingsFooter) writeBundle(extras) } } @@ -61,7 +59,6 @@ data class DeviceSettingsConfig( arrayListOf<DeviceSettingItem>().also { readTypedList(it, DeviceSettingItem.CREATOR) }, - moreSettingsFooter = readString()!!, extras = readBundle((Bundle::class.java.classLoader))!!, ) } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt index ce7064c9d781..cded014feda1 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepository.kt @@ -25,6 +25,7 @@ import com.android.settingslib.bluetooth.devicesettings.DeviceSetting import com.android.settingslib.bluetooth.devicesettings.DeviceSettingId import com.android.settingslib.bluetooth.devicesettings.DeviceSettingItem import com.android.settingslib.bluetooth.devicesettings.DeviceSettingsConfig +import com.android.settingslib.bluetooth.devicesettings.DeviceSettingFooterPreference import com.android.settingslib.bluetooth.devicesettings.MultiTogglePreference import com.android.settingslib.bluetooth.devicesettings.ToggleInfo import com.android.settingslib.bluetooth.devicesettings.shared.model.DeviceSettingConfigItemModel @@ -96,8 +97,7 @@ class DeviceSettingRepositoryImpl( private fun DeviceSettingsConfig.toModel(): DeviceSettingConfigModel = DeviceSettingConfigModel( mainItems = mainContentItems.map { it.toModel() }, - moreSettingsItems = moreSettingsItems.map { it.toModel() }, - moreSettingsPageFooter = moreSettingsFooter) + moreSettingsItems = moreSettingsItems.map { it.toModel() }) private fun DeviceSettingItem.toModel(): DeviceSettingConfigItemModel { return if (!TextUtils.isEmpty(preferenceKey)) { @@ -151,6 +151,9 @@ class DeviceSettingRepositoryImpl( } }, ) + is DeviceSettingFooterPreference -> DeviceSettingModel.FooterPreference( + cachedDevice = cachedDevice, + id = settingId, footerText = pref.footerText) else -> DeviceSettingModel.Unknown(cachedDevice, settingId) } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt index e97f76cca3a9..406246246e7e 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingConfigModel.kt @@ -24,8 +24,6 @@ data class DeviceSettingConfigModel( val mainItems: List<DeviceSettingConfigItemModel>, /** Items need to be shown in device details more settings page. */ val moreSettingsItems: List<DeviceSettingConfigItemModel>, - /** Footer text in more settings page. */ - val moreSettingsPageFooter: String ) /** Models a device setting item in config. */ diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt index 2a6321704a1a..5fd4d06872c8 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/devicesettings/shared/model/DeviceSettingModel.kt @@ -52,6 +52,13 @@ sealed interface DeviceSettingModel { val updateState: (DeviceSettingStateModel.MultiTogglePreferenceState) -> Unit ) : DeviceSettingModel + /** Models a footer preference. */ + data class FooterPreference( + override val cachedDevice: CachedBluetoothDevice, + @DeviceSettingId override val id: Int, + val footerText: String, + ) : DeviceSettingModel + /** Models an unknown preference. */ data class Unknown( override val cachedDevice: CachedBluetoothDevice, diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingFooterPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingFooterPreferenceTest.java new file mode 100644 index 000000000000..cc2f7885e3d4 --- /dev/null +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingFooterPreferenceTest.java @@ -0,0 +1,72 @@ +/* + * 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.settingslib.bluetooth.devicesettings; + +import static com.google.common.truth.Truth.assertThat; + +import android.os.Bundle; +import android.os.Parcel; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public final class DeviceSettingFooterPreferenceTest { + + @Test + public void getMethods() { + DeviceSettingFooterPreference preference = + new DeviceSettingFooterPreference.Builder() + .setFooterText("footer_text") + .setExtras(buildBundle("key1", "value1")) + .build(); + + assertThat(preference.getFooterText()).isEqualTo("footer_text"); + assertThat(preference.getExtras().getString("key1")).isEqualTo("value1"); + } + + @Test + public void parcelOperation() { + DeviceSettingFooterPreference preference = + new DeviceSettingFooterPreference.Builder() + .setFooterText("footer_text") + .setExtras(buildBundle("key1", "value1")) + .build(); + + DeviceSettingFooterPreference fromParcel = writeAndRead(preference); + + assertThat(fromParcel.getFooterText()).isEqualTo(preference.getFooterText()); + assertThat(fromParcel.getExtras().getString("key1")) + .isEqualTo(preference.getExtras().getString("key1")); + } + + private Bundle buildBundle(String key, String value) { + Bundle bundle = new Bundle(); + bundle.putString(key, value); + return bundle; + } + + private DeviceSettingFooterPreference writeAndRead(DeviceSettingFooterPreference preference) { + Parcel parcel = Parcel.obtain(); + preference.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + DeviceSettingFooterPreference fromParcel = + DeviceSettingFooterPreference.CREATOR.createFromParcel(parcel); + return fromParcel; + } +} diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt index 9568d66ac7db..7223e9032648 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/DeviceSettingsConfigTest.kt @@ -50,7 +50,6 @@ class DeviceSettingsConfigTest { null, Bundle(), )), - moreSettingsFooter = "footer", extras = Bundle().apply { putString("key1", "value1") }, ) @@ -72,7 +71,6 @@ class DeviceSettingsConfigTest { .containsExactly("class_name_2") assertThat(fromParcel.moreSettingsItems.stream().map { it.intentAction }.toList()) .containsExactly("intent_action_2") - assertThat(fromParcel.moreSettingsFooter).isEqualTo(config.moreSettingsFooter) } private fun writeAndRead(item: DeviceSettingsConfig): DeviceSettingsConfig { diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt index 4c5ee9e4ee4c..061d5150f60a 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/devicesettings/data/repository/DeviceSettingRepositoryTest.kt @@ -97,9 +97,7 @@ class DeviceSettingRepositoryTest { `when`(cachedDevice.address).thenReturn(BLUETOOTH_ADDRESS) `when`( bluetoothDevice.getMetadata( - DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS - ) - ) + DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)) .thenReturn(BLUETOOTH_DEVICE_METADATA.toByteArray()) `when`(configService.queryLocalInterface(anyString())).thenReturn(configService) @@ -122,8 +120,7 @@ class DeviceSettingRepositoryTest { connection.onServiceConnected( ComponentName( SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1, - SETTING_PROVIDER_SERVICE_CLASS_NAME_1 - ), + SETTING_PROVIDER_SERVICE_CLASS_NAME_1), settingProviderService1, ) SETTING_PROVIDER_SERVICE_INTENT_ACTION_2 -> @@ -168,9 +165,7 @@ class DeviceSettingRepositoryTest { `when`(configService.getDeviceSettingsConfig(any())).thenReturn(DEVICE_SETTING_CONFIG) `when`( bluetoothDevice.getMetadata( - DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS - ) - ) + DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)) .thenReturn("".toByteArray()) var config: DeviceSettingConfigModel? = null @@ -178,10 +173,7 @@ class DeviceSettingRepositoryTest { delay(1000) verify(bluetoothAdapter) .addOnMetadataChangedListener( - eq(bluetoothDevice), - any(), - metadataChangeCaptor.capture() - ) + eq(bluetoothDevice), any(), metadataChangeCaptor.capture()) metadataChangeCaptor.value.onMetadataChanged( bluetoothDevice, DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS, @@ -189,9 +181,7 @@ class DeviceSettingRepositoryTest { ) `when`( bluetoothDevice.getMetadata( - DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS - ) - ) + DeviceSettingServiceConnection.METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)) .thenReturn(BLUETOOTH_DEVICE_METADATA.toByteArray()) job.join() @@ -303,10 +293,8 @@ class DeviceSettingRepositoryTest { DeviceSettingState.Builder() .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER) .setPreferenceState( - ActionSwitchPreferenceState.Builder().setChecked(false).build() - ) - .build() - ) + ActionSwitchPreferenceState.Builder().setChecked(false).build()) + .build()) } } @@ -337,10 +325,8 @@ class DeviceSettingRepositoryTest { DeviceSettingState.Builder() .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_ANC) .setPreferenceState( - MultiTogglePreferenceState.Builder().setState(2).build() - ) - .build() - ) + MultiTogglePreferenceState.Builder().setState(2).build()) + .build()) } } @@ -353,7 +339,8 @@ class DeviceSettingRepositoryTest { val pref = serviceResponse.preference as ActionSwitchPreference assertThat(actual.title).isEqualTo(pref.title) assertThat(actual.summary).isEqualTo(pref.summary) - assertThat(actual.icon).isEqualTo(DeviceSettingIcon.BitmapIcon(pref.icon!!)) + assertThat(actual.icon) + .isEqualTo(pref.icon?.let { DeviceSettingIcon.BitmapIcon(it) }) assertThat(actual.isAllowedChangingState).isEqualTo(pref.isAllowedChangingState) if (pref.hasSwitch()) { assertThat(actual.switchState!!.checked).isEqualTo(pref.checked) @@ -378,7 +365,8 @@ class DeviceSettingRepositoryTest { private fun assertToggle(actual: ToggleModel, serviceResponse: ToggleInfo) { assertThat(actual.label).isEqualTo(serviceResponse.label) - assertThat(actual.icon).isEqualTo(serviceResponse.icon) + assertThat((actual.icon as DeviceSettingIcon.BitmapIcon).bitmap) + .isEqualTo(serviceResponse.icon) } private fun assertConfig( @@ -393,7 +381,6 @@ class DeviceSettingRepositoryTest { for (i in 0..<actual.moreSettingsItems.size) { assertConfigItem(actual.moreSettingsItems[i], serviceResponse.moreSettingsItems[i]) } - assertThat(actual.moreSettingsPageFooter).isEqualTo(serviceResponse.moreSettingsFooter) } private fun assertConfigItem( @@ -437,15 +424,13 @@ class DeviceSettingRepositoryTest { DeviceSettingId.DEVICE_SETTING_ID_HEADER, SETTING_PROVIDER_SERVICE_PACKAGE_NAME_1, SETTING_PROVIDER_SERVICE_CLASS_NAME_1, - SETTING_PROVIDER_SERVICE_INTENT_ACTION_1 - ) + SETTING_PROVIDER_SERVICE_INTENT_ACTION_1) val DEVICE_SETTING_ITEM_2 = DeviceSettingItem( DeviceSettingId.DEVICE_SETTING_ID_ANC, SETTING_PROVIDER_SERVICE_PACKAGE_NAME_2, SETTING_PROVIDER_SERVICE_CLASS_NAME_2, - SETTING_PROVIDER_SERVICE_INTENT_ACTION_2 - ) + SETTING_PROVIDER_SERVICE_INTENT_ACTION_2) val DEVICE_SETTING_1 = DeviceSetting.Builder() .setSettingId(DeviceSettingId.DEVICE_SETTING_ID_HEADER) @@ -454,8 +439,7 @@ class DeviceSettingRepositoryTest { .setTitle("title1") .setHasSwitch(true) .setAllowedChangingState(true) - .build() - ) + .build()) .build() val DEVICE_SETTING_2 = DeviceSetting.Builder() @@ -468,22 +452,18 @@ class DeviceSettingRepositoryTest { ToggleInfo.Builder() .setLabel("label1") .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)) - .build() - ) + .build()) .addToggleInfo( ToggleInfo.Builder() .setLabel("label2") .setIcon(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)) - .build() - ) - .build() - ) + .build()) + .build()) .build() val DEVICE_SETTING_CONFIG = DeviceSettingsConfig( listOf(DEVICE_SETTING_ITEM_1), listOf(DEVICE_SETTING_ITEM_2), - "footer" ) } } |