From d4774b37aae74e00f45ba37b34f2e95c5930a794 Mon Sep 17 00:00:00 2001 From: yqian Date: Mon, 17 Feb 2025 16:14:02 +0800 Subject: [PATCH] Update the audio sharing QR code logic to enable OEMs providing customized QR code image Test: atest AudioSharingFeatureProviderImplTest Bug: b/397137711 Flag: EXEMPT no-op Change-Id: I124d6ded50faf9fa0ca06bd5b34d72e9399f3e59 --- .../AudioSharingDialogFragment.java | 27 ++++-- .../AudioSharingFeatureProvider.java | 43 +++++++++ .../AudioSharingFeatureProviderImpl.java | 39 ++++++++ .../AudioStreamsQrCodeFragment.java | 85 ++++++++++------- .../settings/overlay/FeatureFactory.kt | 6 ++ .../settings/overlay/FeatureFactoryImpl.kt | 6 ++ .../AudioSharingFeatureProviderImplTest.java | 93 +++++++++++++++++++ .../testutils/FakeFeatureFactory.java | 10 +- .../settings/testutils/FakeFeatureFactory.kt | 3 + .../testutils/FakeFeatureFactory.java | 10 +- 10 files changed, 279 insertions(+), 43 deletions(-) create mode 100644 src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java create mode 100644 src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java index 14a559014cf..6f844813a76 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogFragment.java @@ -40,7 +40,9 @@ import com.android.settings.R; import com.android.settings.bluetooth.BluetoothPairingDetail; import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment; import com.android.settings.core.SubSettingLauncher; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.core.instrumentation.InstrumentedDialogFragment; +import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt; import com.android.settingslib.bluetooth.BluetoothUtils; import com.google.common.collect.Iterables; @@ -75,6 +77,9 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { private static Pair[] sEventData = new Pair[0]; @Nullable private static Fragment sHost; + AudioSharingFeatureProvider audioSharingFeatureProvider = + FeatureFactory.getFeatureFactory().getAudioSharingFeatureProvider(); + @Override public int getMetricsCategory() { return SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE; @@ -158,6 +163,9 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { Log.d(TAG, "Create dialog error: null deviceItems"); return builder.build(); } + BluetoothLeBroadcastMetadata metadata = arguments.getParcelable( + BUNDLE_KEY_BROADCAST_METADATA, BluetoothLeBroadcastMetadata.class); + Drawable qrCodeDrawable = null; if (deviceItems.isEmpty()) { builder.setTitle(R.string.audio_sharing_share_dialog_title) .setCustomPositiveButton( @@ -181,9 +189,7 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { } launcher.launch(); }); - BluetoothLeBroadcastMetadata metadata = arguments.getParcelable( - BUNDLE_KEY_BROADCAST_METADATA, BluetoothLeBroadcastMetadata.class); - Drawable qrCodeDrawable = metadata == null ? null : getQrCodeDrawable(metadata, + qrCodeDrawable = metadata == null ? null : getQrCodeDrawable(metadata, getContext()).orElse(null); if (qrCodeDrawable != null) { String broadcastName = @@ -195,8 +201,7 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { new String(metadata.getBroadcastCode(), StandardCharsets.UTF_8)) : getString(R.string.audio_sharing_dialog_qr_code_content_no_password, broadcastName); - builder.setCustomImage(qrCodeDrawable) - .setCustomMessage(message) + builder.setCustomMessage(message) .setCustomMessage2(R.string.audio_sharing_dialog_pair_new_device_content) .setCustomNegativeButton(R.string.audio_streams_dialog_close, v -> onCancelClick()); @@ -251,7 +256,17 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment { .setCustomNegativeButton( com.android.settings.R.string.cancel, v -> onCancelClick()); } - return builder.build(); + Dialog dialog = builder.build(); + dialog.show(); + if (deviceItems.isEmpty() && qrCodeDrawable != null) { + audioSharingFeatureProvider.setQrCode( + this, + dialog.getWindow().getDecorView(), + R.id.description_image, + qrCodeDrawable, + BluetoothLeBroadcastMetadataExt.INSTANCE.toQrCodeString(metadata)); + } + return dialog; } private void onCancelClick() { diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java new file mode 100644 index 00000000000..40183eb1d87 --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProvider.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2025 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.settings.connecteddevice.audiosharing; + +import android.annotation.IdRes; +import androidx.annotation.NonNull; +import android.graphics.drawable.Drawable; +import android.view.View; + +import androidx.fragment.app.Fragment; + +/** Feature provider for the audio sharing features. */ +public interface AudioSharingFeatureProvider { + /** + * Sets the QR code for audio sharing dialogs + * + * @param fragment the fragment to be updated + * @param qrcodeContainer the view to be updated + * @param qrCodeImageViewId the view ID to search for + * @param drawable the drawable asset of the QR code + * @param qrCode the value of the qrCode + */ + public void setQrCode( + @NonNull Fragment fragment, + @NonNull View qrcodeContainer, + @IdRes int qrCodeImageViewId, + @NonNull Drawable drawable, + @NonNull String qrCode); +} diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java new file mode 100644 index 00000000000..bb885a8f1a8 --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImpl.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2025 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.settings.connecteddevice.audiosharing; + +import android.annotation.IdRes; +import androidx.annotation.NonNull; +import android.graphics.drawable.Drawable; +import android.view.View; +import android.widget.ImageView; + +import androidx.fragment.app.Fragment; + +/** Default implementation for {@link AudioSharingFeatureProvider} */ +public class AudioSharingFeatureProviderImpl implements AudioSharingFeatureProvider { + public void setQrCode( + @NonNull Fragment fragment, + @NonNull View qrcodeContainer, + @IdRes int qrCodeImageViewId, + @NonNull Drawable drawable, + @NonNull String qrCode) { + ImageView imageView = ((ImageView) qrcodeContainer.requireViewById(qrCodeImageViewId)); + imageView.setImageDrawable(drawable); + imageView.setVisibility(View.VISIBLE); + } +} diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java index daa7a2e1c23..9968c87edff 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java +++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamsQrCodeFragment.java @@ -37,11 +37,13 @@ import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; import com.android.settings.R; import com.android.settings.bluetooth.Utils; +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider; import com.android.settings.core.InstrumentedFragment; import com.android.settingslib.bluetooth.BluetoothLeBroadcastMetadataExt; import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; import com.android.settingslib.qrcode.QrCodeGenerator; import com.android.settingslib.utils.ThreadUtils; +import com.android.settings.overlay.FeatureFactory; import com.google.zxing.WriterException; @@ -52,6 +54,9 @@ import java.util.Optional; public class AudioStreamsQrCodeFragment extends InstrumentedFragment { private static final String TAG = "AudioStreamsQrCodeFragment"; + AudioSharingFeatureProvider audioSharingFeatureProvider = + FeatureFactory.getFeatureFactory().getAudioSharingFeatureProvider(); + @Override public int getMetricsCategory() { return SettingsEnums.AUDIO_STREAM_QR_CODE; @@ -68,42 +73,52 @@ public class AudioStreamsQrCodeFragment extends InstrumentedFragment { super.onViewCreated(view, savedInstanceState); // Collapse or expand the app bar based on orientation for better display the qr code image. AudioStreamsHelper.configureAppBarByOrientation(getActivity()); - var unused = ThreadUtils.postOnBackgroundThread( - () -> { - BluetoothLeBroadcastMetadata broadcastMetadata = getBroadcastMetadata(); - if (broadcastMetadata == null) { - return; - } - Drawable drawable = getQrCodeDrawable(broadcastMetadata, getActivity()).orElse( - null); - if (drawable == null) { - return; - } + var unused = + ThreadUtils.postOnBackgroundThread( + () -> { + BluetoothLeBroadcastMetadata broadcastMetadata = getBroadcastMetadata(); + if (broadcastMetadata == null) { + return; + } + Drawable drawable = + getQrCodeDrawable(broadcastMetadata, getActivity()) + .orElse(null); + if (drawable == null) { + return; + } - ThreadUtils.postOnMainThread( - () -> { - ((ImageView) view.requireViewById(R.id.qrcode_view)) - .setImageDrawable(drawable); - if (broadcastMetadata.getBroadcastCode() != null) { - String password = - new String( - broadcastMetadata.getBroadcastCode(), - StandardCharsets.UTF_8); - String passwordText = - getString( - R.string.audio_streams_qr_code_page_password, - password); - ((TextView) view.requireViewById(R.id.password)) - .setText(passwordText); - } - TextView summaryView = view.requireViewById(android.R.id.summary); - String summary = - getString( - R.string.audio_streams_qr_code_page_description, - broadcastMetadata.getBroadcastName()); - summaryView.setText(summary); - }); - }); + ThreadUtils.postOnMainThread( + () -> { + audioSharingFeatureProvider.setQrCode( + this, + view, + R.id.qrcode_view, + drawable, + BluetoothLeBroadcastMetadataExt.INSTANCE + .toQrCodeString(broadcastMetadata)); + if (broadcastMetadata.getBroadcastCode() != null) { + String password = + new String( + broadcastMetadata.getBroadcastCode(), + StandardCharsets.UTF_8); + String passwordText = + getString( + R.string + .audio_streams_qr_code_page_password, + password); + ((TextView) view.requireViewById(R.id.password)) + .setText(passwordText); + } + TextView summaryView = + view.requireViewById(android.R.id.summary); + String summary = + getString( + R.string + .audio_streams_qr_code_page_description, + broadcastMetadata.getBroadcastName()); + summaryView.setText(summary); + }); + }); } /** Gets an optional drawable from metadata. */ diff --git a/src/com/android/settings/overlay/FeatureFactory.kt b/src/com/android/settings/overlay/FeatureFactory.kt index 7e04f0d4373..6c081c70fc5 100644 --- a/src/com/android/settings/overlay/FeatureFactory.kt +++ b/src/com/android/settings/overlay/FeatureFactory.kt @@ -25,6 +25,7 @@ import com.android.settings.biometrics.BiometricsFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProvider +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider import com.android.settings.connecteddevice.stylus.StylusFeatureProvider import com.android.settings.dashboard.DashboardFeatureProvider @@ -179,6 +180,11 @@ abstract class FeatureFactory { */ abstract val fastPairFeatureProvider: FastPairFeatureProvider + /** + * Gets implementation for audio sharing related feature. + */ + abstract val audioSharingFeatureProvider: AudioSharingFeatureProvider + /** * Gets implementation for Private Space account login feature. */ diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.kt b/src/com/android/settings/overlay/FeatureFactoryImpl.kt index 4949c3f7f0c..8442d0e90a4 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.kt +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.kt @@ -37,6 +37,8 @@ import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProviderImpl import com.android.settings.bluetooth.BluetoothFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProviderImpl +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProviderImpl import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProviderImpl @@ -194,6 +196,10 @@ open class FeatureFactoryImpl : FeatureFactory() { FastPairFeatureProviderImpl() } + override val audioSharingFeatureProvider: AudioSharingFeatureProvider by lazy { + AudioSharingFeatureProviderImpl() + } + override val privateSpaceLoginFeatureProvider: PrivateSpaceLoginFeatureProvider by lazy { PrivateSpaceLoginFeatureProviderImpl() } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java new file mode 100644 index 00000000000..3ffd7310822 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingFeatureProviderImplTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2025 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.settings.connecteddevice.audiosharing; + +import static com.google.common.truth.Truth.assertThat; + +import static junit.framework.Assert.assertEquals; + +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.robolectric.RobolectricTestRunner; + +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; + +import com.android.settings.R; +import com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamsQrCodeFragment; + +import androidx.fragment.app.Fragment; +import androidx.test.core.app.ApplicationProvider; + +@RunWith(RobolectricTestRunner.class) +public class AudioSharingFeatureProviderImplTest { + + private AudioSharingFeatureProvider mFeatureProvider; + @Mock private Fragment mFragment; + @Mock private View mockView; + private Context mContext; + @Mock private Drawable mDrawable; + + @Before + public void setup() { + mContext = ApplicationProvider.getApplicationContext(); + mFeatureProvider = new AudioSharingFeatureProviderImpl(); + } + + @Test + public void setQrCode_correctDialogLayout() { + mFragment = new AudioSharingDialogFragment(); + View view = + LayoutInflater.from(mContext) + .inflate(R.layout.dialog_custom_body_audio_sharing, null); + mFeatureProvider.setQrCode(mFragment, view, R.id.description_image, mDrawable, ""); + ImageView imageView = view.findViewById(R.id.description_image); + + assertThat(imageView.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(imageView.getDrawable()).isEqualTo(mDrawable); + } + + @Test + public void setQrCode_correctLayout() { + mFragment = new AudioStreamsQrCodeFragment(); + View view = + LayoutInflater.from(mContext) + .inflate(R.layout.bluetooth_audio_streams_qr_code, null); + mFeatureProvider.setQrCode(mFragment, view, R.id.qrcode_view, mDrawable, ""); + ImageView imageView = view.findViewById(R.id.qrcode_view); + + assertThat(imageView.getVisibility()).isEqualTo(View.VISIBLE); + assertThat(imageView.getDrawable()).isEqualTo(mDrawable); + } + + @Test(expected = IllegalArgumentException.class) + public void setQrCode_nonExistedViewId() { + mFragment = new AudioStreamsQrCodeFragment(); + View view = + LayoutInflater.from(mContext) + .inflate(R.layout.bluetooth_audio_streams_qr_code, null); + mFeatureProvider.setQrCode(mFragment, view, R.id.description_image, mDrawable, ""); + } +} diff --git a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java index e002de1e391..3a5682daea5 100644 --- a/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/robotests/testutils/com/android/settings/testutils/FakeFeatureFactory.java @@ -28,6 +28,7 @@ import com.android.settings.biometrics.BiometricsFeatureProvider; import com.android.settings.biometrics.face.FaceFeatureProvider; import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider; import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider; import com.android.settings.connecteddevice.stylus.StylusFeatureProvider; import com.android.settings.dashboard.DashboardFeatureProvider; @@ -105,6 +106,7 @@ public class FakeFeatureFactory extends FeatureFactory { public DisplayFeatureProvider mDisplayFeatureProvider; public SyncAcrossDevicesFeatureProvider mSyncAcrossDevicesFeatureProvider; public AccessibilityFeedbackFeatureProvider mAccessibilityFeedbackFeatureProvider; + public AudioSharingFeatureProvider mAudioSharingFeatureProvider; /** * Call this in {@code @Before} method of the test class to use fake factory. @@ -155,6 +157,7 @@ public class FakeFeatureFactory extends FeatureFactory { mPrivateSpaceLoginFeatureProvider = mock(PrivateSpaceLoginFeatureProvider.class); mDisplayFeatureProvider = mock(DisplayFeatureProvider.class); mSyncAcrossDevicesFeatureProvider = mock(SyncAcrossDevicesFeatureProvider.class); + mAudioSharingFeatureProvider = mock(AudioSharingFeatureProvider.class); } @Override @@ -347,4 +350,9 @@ public class FakeFeatureFactory extends FeatureFactory { public AccessibilityFeedbackFeatureProvider getAccessibilityFeedbackFeatureProvider() { return mAccessibilityFeedbackFeatureProvider; } -} + + @Override + public AudioSharingFeatureProvider getAudioSharingFeatureProvider() { + return mAudioSharingFeatureProvider; + } +} \ No newline at end of file diff --git a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt index 7b1bdc0ed9c..2a2ede1f4b1 100644 --- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt +++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt @@ -26,6 +26,7 @@ import com.android.settings.biometrics.BiometricsFeatureProvider import com.android.settings.biometrics.face.FaceFeatureProvider import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider import com.android.settings.bluetooth.BluetoothFeatureProvider +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider import com.android.settings.connecteddevice.stylus.StylusFeatureProvider import com.android.settings.dashboard.DashboardFeatureProvider @@ -148,4 +149,6 @@ class FakeFeatureFactory : FeatureFactory() { get() = TODO("Not yet implemented") override val syncAcrossDevicesFeatureProvider: SyncAcrossDevicesFeatureProvider get() = TODO("Not yet implemented") + override val audioSharingFeatureProvider: AudioSharingFeatureProvider + get() = TODO("Not yet implemented") } diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java index eda0aeb934c..6f3f8df4ecd 100644 --- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java +++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java @@ -28,6 +28,7 @@ import com.android.settings.biometrics.BiometricsFeatureProvider; import com.android.settings.biometrics.face.FaceFeatureProvider; import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider; import com.android.settings.bluetooth.BluetoothFeatureProvider; +import com.android.settings.connecteddevice.audiosharing.AudioSharingFeatureProvider; import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider; import com.android.settings.connecteddevice.stylus.StylusFeatureProvider; import com.android.settings.dashboard.DashboardFeatureProvider; @@ -104,6 +105,7 @@ public class FakeFeatureFactory extends FeatureFactory { public DisplayFeatureProvider mDisplayFeatureProvider; public SyncAcrossDevicesFeatureProvider mSyncAcrossDevicesFeatureProvider; public AccessibilityFeedbackFeatureProvider mAccessibilityFeedbackFeatureProvider; + public AudioSharingFeatureProvider mAudioSharingFeatureProvider; /** Call this in {@code @Before} method of the test class to use fake factory. */ public static FakeFeatureFactory setupForTest() { @@ -156,6 +158,7 @@ public class FakeFeatureFactory extends FeatureFactory { mPrivateSpaceLoginFeatureProvider = mock(PrivateSpaceLoginFeatureProvider.class); mDisplayFeatureProvider = mock(DisplayFeatureProvider.class); mSyncAcrossDevicesFeatureProvider = mock(SyncAcrossDevicesFeatureProvider.class); + mAudioSharingFeatureProvider = mock(AudioSharingFeatureProvider.class); } @Override @@ -348,4 +351,9 @@ public class FakeFeatureFactory extends FeatureFactory { public AccessibilityFeedbackFeatureProvider getAccessibilityFeedbackFeatureProvider() { return mAccessibilityFeedbackFeatureProvider; } -} + + @Override + public AudioSharingFeatureProvider getAudioSharingFeatureProvider() { + return mAudioSharingFeatureProvider; + } +} \ No newline at end of file