Adds telephony repository and interactor.

This is needed for downstream dependencies to observe the call state.

Bug: 246631653
Test: Unit test included
Change-Id: If7f213dea82581e04620189ca3b13dea3295d9ae
This commit is contained in:
Alejandro Nijamkin
2022-09-21 18:22:10 -07:00
parent 963f710d4c
commit cd00a5dbc8
6 changed files with 232 additions and 0 deletions

View File

@@ -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,

View File

@@ -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<Int>
}
/**
* 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<Int> = conflatedCallbackFlow {
val listener = TelephonyCallback.CallStateListener { state -> trySend(state) }
manager.addCallStateListener(listener)
awaitClose { manager.removeCallStateListener(listener) }
}
}

View File

@@ -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
}

View File

@@ -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<Int> = repository.callState
}

View File

@@ -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<TelephonyCallback.CallStateListener>()
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
}
}

View File

@@ -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<Int> = _callState.asStateFlow()
fun setCallState(value: Int) {
_callState.value = value
}
}