diff --git a/res/xml/bluetooth_le_audio_sharing_join_handler.xml b/res/xml/bluetooth_le_audio_sharing_join_handler.xml new file mode 100644 index 00000000000..eda29a6e62d --- /dev/null +++ b/res/xml/bluetooth_le_audio_sharing_join_handler.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerActivity.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerActivity.java new file mode 100644 index 00000000000..0e5297d09b7 --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerActivity.java @@ -0,0 +1,33 @@ +/* + * 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 com.android.settings.SettingsActivity; + +public class AudioSharingJoinHandlerActivity extends SettingsActivity { + private static final String TAG = "AudioSharingJoinHandlerActivity"; + + @Override + protected boolean isToolbarEnabled() { + return false; + } + + @Override + protected boolean isValidFragment(String fragmentName) { + return AudioSharingJoinHandlerDashboardFragment.class.getName().equals(fragmentName); + } +} diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerController.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerController.java new file mode 100644 index 00000000000..376675fa772 --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerController.java @@ -0,0 +1,55 @@ +/* + * 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.content.Context; + +import androidx.annotation.NonNull; +import androidx.lifecycle.DefaultLifecycleObserver; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.bluetooth.BluetoothUtils; +import com.android.settingslib.flags.Flags; + +public class AudioSharingJoinHandlerController extends BasePreferenceController + implements DefaultLifecycleObserver { + private static final String TAG = "AudioSharingJoinHandlerCtrl"; + private static final String KEY = "audio_sharing_join_handler"; + + public AudioSharingJoinHandlerController(@NonNull Context context, + @NonNull String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return (Flags.promoteAudioSharingForSecondAutoConnectedLeaDevice() + && BluetoothUtils.isAudioSharingUIAvailable(mContext)) + ? AVAILABLE_UNSEARCHABLE + : UNSUPPORTED_ON_DEVICE; + } + + @Override + public String getPreferenceKey() { + return KEY; + } + + @Override + public int getSliceHighlightMenuRes() { + return 0; + } +} diff --git a/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerDashboardFragment.java b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerDashboardFragment.java new file mode 100644 index 00000000000..6042e5558d2 --- /dev/null +++ b/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerDashboardFragment.java @@ -0,0 +1,48 @@ +/* + * 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.content.Context; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; + +public class AudioSharingJoinHandlerDashboardFragment extends DashboardFragment { + private static final String TAG = "AudioSharingJoinHandlerFrag"; + + @Override + public int getMetricsCategory() { + // TODO: use real enum + return 0; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.bluetooth_le_audio_sharing_join_handler; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + use(AudioSharingJoinHandlerController.class); + } +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerActivityTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerActivityTest.java new file mode 100644 index 00000000000..d72a9e06be7 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerActivityTest.java @@ -0,0 +1,54 @@ +/* + * 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 org.mockito.Mockito.spy; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class AudioSharingJoinHandlerActivityTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + + private AudioSharingJoinHandlerActivity mActivity; + + @Before + public void setUp() { + mActivity = spy(Robolectric.buildActivity(AudioSharingJoinHandlerActivity.class).get()); + } + + @Test + public void isValidFragment_returnsTrue() { + assertThat(mActivity.isValidFragment( + AudioSharingJoinHandlerDashboardFragment.class.getName())).isTrue(); + } + + @Test + public void isValidFragment_returnsFalse() { + assertThat(mActivity.isValidFragment("")).isFalse(); + } +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerControllerTest.java new file mode 100644 index 00000000000..51365e6d977 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerControllerTest.java @@ -0,0 +1,94 @@ +/* + * 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.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; +import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; + +import static com.google.common.truth.Truth.assertThat; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothStatusCodes; +import android.content.Context; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.shadow.ShadowBluetoothAdapter; +import com.android.settingslib.flags.Flags; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; + +@RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowBluetoothAdapter.class) +public class AudioSharingJoinHandlerControllerTest { + private static final String PREF_KEY = "audio_sharing_join_handler"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Spy + Context mContext = ApplicationProvider.getApplicationContext(); + private AudioSharingJoinHandlerController mController; + + @Before + public void setUp() { + ShadowBluetoothAdapter shadowBluetoothAdapter = + Shadow.extract(BluetoothAdapter.getDefaultAdapter()); + shadowBluetoothAdapter.setEnabled(true); + shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported( + BluetoothStatusCodes.FEATURE_SUPPORTED); + mController = new AudioSharingJoinHandlerController(mContext, PREF_KEY); + } + + @Test + @EnableFlags({Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE, + Flags.FLAG_ENABLE_LE_AUDIO_SHARING}) + public void getAvailabilityStatus_flagOn() { + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); + } + + @Test + @DisableFlags(Flags.FLAG_PROMOTE_AUDIO_SHARING_FOR_SECOND_AUTO_CONNECTED_LEA_DEVICE) + public void getAvailabilityStatus_flagOff() { + assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getPreferenceKey_returnsCorrectKey() { + assertThat(mController.getPreferenceKey()).isEqualTo(PREF_KEY); + } + + @Test + public void getSliceHighlightMenuRes_returnsZero() { + assertThat(mController.getSliceHighlightMenuRes()).isEqualTo(0); + } +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerDashboardFragmentTest.java new file mode 100644 index 00000000000..3fd27b10b11 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/audiosharing/AudioSharingJoinHandlerDashboardFragmentTest.java @@ -0,0 +1,52 @@ +/* + * 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 com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +@RunWith(RobolectricTestRunner.class) +public class AudioSharingJoinHandlerDashboardFragmentTest { + private AudioSharingJoinHandlerDashboardFragment mFragment; + + @Before + public void setUp() { + mFragment = new AudioSharingJoinHandlerDashboardFragment(); + } + + @Test + public void getPreferenceScreenResId_returnsCorrectXml() { + assertThat(mFragment.getPreferenceScreenResId()) + .isEqualTo(R.xml.bluetooth_le_audio_sharing_join_handler); + } + + @Test + public void getLogTag_returnsCorrectTag() { + assertThat(mFragment.getLogTag()).isEqualTo("AudioSharingJoinHandlerFrag"); + } + + @Test + public void getMetricsCategory_returnsCorrectCategory() { + assertThat(mFragment.getMetricsCategory()).isEqualTo(0); + } +}