diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 443d2774f0e0f..06dbab9807930 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -81,6 +81,7 @@ import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.dagger.SmartRepliesInflationModule; import com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule; import com.android.systemui.statusbar.window.StatusBarWindowModule; +import com.android.systemui.telephony.data.repository.TelephonyRepositoryModule; import com.android.systemui.tuner.dagger.TunerModule; import com.android.systemui.unfold.SysUIUnfoldModule; import com.android.systemui.user.UserModule; @@ -145,6 +146,7 @@ import dagger.Provides; StatusBarWindowModule.class, SysUIConcurrencyModule.class, SysUIUnfoldModule.class, + TelephonyRepositoryModule.class, TunerModule.class, UserModule.class, UtilModule.class, diff --git a/packages/SystemUI/src/com/android/systemui/telephony/data/repository/TelephonyRepository.kt b/packages/SystemUI/src/com/android/systemui/telephony/data/repository/TelephonyRepository.kt new file mode 100644 index 0000000000000..9c38dc0f88527 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/telephony/data/repository/TelephonyRepository.kt @@ -0,0 +1,56 @@ +/* + * 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. + * + */ + +package com.android.systemui.telephony.data.repository + +import android.telephony.Annotation +import android.telephony.TelephonyCallback +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.telephony.TelephonyListenerManager +import javax.inject.Inject +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow + +/** Defines interface for classes that encapsulate _some_ telephony-related state. */ +interface TelephonyRepository { + /** The state of the current call. */ + @Annotation.CallState val callState: Flow +} + +/** + * NOTE: This repository tracks only telephony-related state regarding the default mobile + * subscription. `TelephonyListenerManager` does not create new instances of `TelephonyManager` on a + * per-subscription basis and thus will always be tracking telephony information regarding + * `SubscriptionManager.getDefaultSubscriptionId`. See `TelephonyManager` and `SubscriptionManager` + * for more documentation. + */ +@SysUISingleton +class TelephonyRepositoryImpl +@Inject +constructor( + private val manager: TelephonyListenerManager, +) : TelephonyRepository { + @Annotation.CallState + override val callState: Flow = conflatedCallbackFlow { + val listener = TelephonyCallback.CallStateListener { state -> trySend(state) } + + manager.addCallStateListener(listener) + + awaitClose { manager.removeCallStateListener(listener) } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/telephony/data/repository/TelephonyRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/telephony/data/repository/TelephonyRepositoryModule.kt new file mode 100644 index 0000000000000..630fbf2d1a07a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/telephony/data/repository/TelephonyRepositoryModule.kt @@ -0,0 +1,26 @@ +/* + * 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. + * + */ + +package com.android.systemui.telephony.data.repository + +import dagger.Binds +import dagger.Module + +@Module +interface TelephonyRepositoryModule { + @Binds fun repository(impl: TelephonyRepositoryImpl): TelephonyRepository +} diff --git a/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt new file mode 100644 index 0000000000000..86ca33df24ddc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/telephony/domain/interactor/TelephonyInteractor.kt @@ -0,0 +1,34 @@ +/* + * 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. + * + */ + +package com.android.systemui.telephony.domain.interactor + +import android.telephony.Annotation +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.telephony.data.repository.TelephonyRepository +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +/** Hosts business logic related to telephony. */ +@SysUISingleton +class TelephonyInteractor +@Inject +constructor( + repository: TelephonyRepository, +) { + @Annotation.CallState val callState: Flow = repository.callState +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/telephony/data/repository/TelephonyRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/telephony/data/repository/TelephonyRepositoryImplTest.kt new file mode 100644 index 0000000000000..773a0d8ceb64f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/telephony/data/repository/TelephonyRepositoryImplTest.kt @@ -0,0 +1,82 @@ +/* + * 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. + * + */ + +package com.android.systemui.telephony.data.repository + +import android.telephony.TelephonyCallback +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.telephony.TelephonyListenerManager +import com.android.systemui.util.mockito.kotlinArgumentCaptor +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class TelephonyRepositoryImplTest : SysuiTestCase() { + + @Mock private lateinit var manager: TelephonyListenerManager + + private lateinit var underTest: TelephonyRepositoryImpl + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + underTest = + TelephonyRepositoryImpl( + manager = manager, + ) + } + + @Test + fun callState() = + runBlocking(IMMEDIATE) { + var callState: Int? = null + val job = underTest.callState.onEach { callState = it }.launchIn(this) + val listenerCaptor = kotlinArgumentCaptor() + verify(manager).addCallStateListener(listenerCaptor.capture()) + val listener = listenerCaptor.value + + listener.onCallStateChanged(0) + assertThat(callState).isEqualTo(0) + + listener.onCallStateChanged(1) + assertThat(callState).isEqualTo(1) + + listener.onCallStateChanged(2) + assertThat(callState).isEqualTo(2) + + job.cancel() + + verify(manager).removeCallStateListener(listener) + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/telephony/data/repository/FakeTelephonyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/telephony/data/repository/FakeTelephonyRepository.kt new file mode 100644 index 0000000000000..59f24ef2a7063 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/telephony/data/repository/FakeTelephonyRepository.kt @@ -0,0 +1,32 @@ +/* + * 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. + * + */ + +package com.android.systemui.telephony.data.repository + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class FakeTelephonyRepository : TelephonyRepository { + + private val _callState = MutableStateFlow(0) + override val callState: Flow = _callState.asStateFlow() + + fun setCallState(value: Int) { + _callState.value = value + } +}