1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.network.telephony
18 
19 import android.content.Context
20 import android.content.IntentFilter
21 import android.telephony.SubscriptionManager
22 import android.telephony.TelephonyCallback
23 import android.telephony.TelephonyManager
24 import android.util.Log
25 import androidx.annotation.VisibleForTesting
26 import com.android.settings.R
27 import com.android.settings.network.SubscriptionUtil
28 import com.android.settingslib.spaprivileged.framework.common.broadcastReceiverFlow
29 import kotlinx.coroutines.Dispatchers
30 import kotlinx.coroutines.flow.Flow
31 import kotlinx.coroutines.flow.combine
32 import kotlinx.coroutines.flow.conflate
33 import kotlinx.coroutines.flow.distinctUntilChanged
34 import kotlinx.coroutines.flow.flowOn
35 import kotlinx.coroutines.flow.map
36 import kotlinx.coroutines.flow.onStart
37 
38 class DataSubscriptionRepository(
39     private val context: Context,
40     private val getDisplayName: (subId: Int) -> String = { subId ->
41         SubscriptionUtil.getUniqueSubscriptionDisplayName(subId, context).toString()
42     },
43 ) {
44     private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
45     private val subscriptionManager = context.requireSubscriptionManager()
46 
defaultDataSubscriptionIdFlownull47     fun defaultDataSubscriptionIdFlow(): Flow<Int> =
48         context
49             .broadcastReceiverFlow(
50                 IntentFilter(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)
51             )
52             .map { it.getIntExtra(SUBSCRIPTION_KEY, SubscriptionManager.INVALID_SUBSCRIPTION_ID) }
<lambda>null53             .onStart { emit(SubscriptionManager.getDefaultDataSubscriptionId()) }
54             .conflate()
55             .flowOn(Dispatchers.Default)
56 
activeDataSubscriptionIdFlownull57     fun activeDataSubscriptionIdFlow(): Flow<Int> =
58         telephonyManager.telephonyCallbackFlow {
59             object : TelephonyCallback(), TelephonyCallback.ActiveDataSubscriptionIdListener {
60                 override fun onActiveDataSubscriptionIdChanged(subId: Int) {
61                     trySend(subId)
62                     Log.d(TAG, "activeDataSubscriptionIdFlow: $subId")
63                 }
64             }
65         }
66 
dataSummaryFlownull67     fun dataSummaryFlow(): Flow<String> =
68         combine(defaultDataSubscriptionIdFlow(), activeDataSubscriptionIdFlow()) {
69                 defaultSubId,
70                 activeSubId ->
71                 DataSubscriptionIds(defaultSubId, activeSubId)
72             }
73             .distinctUntilChanged()
<lambda>null74             .map { it.getDataSummary() }
75             .conflate()
76             .flowOn(Dispatchers.Default)
77 
78     private data class DataSubscriptionIds(
79         val defaultSubId: Int,
80         val activeSubId: Int,
81     )
82 
getDataSummarynull83     private fun DataSubscriptionIds.getDataSummary(): String {
84         val activeSubInfo = subscriptionManager.getActiveSubscriptionInfo(activeSubId) ?: return ""
85         if (!SubscriptionUtil.isSubscriptionVisible(subscriptionManager, context, activeSubInfo)) {
86             return getDisplayName(defaultSubId)
87         }
88         val uniqueName = getDisplayName(activeSubId)
89         return if (activeSubId == defaultSubId) {
90             uniqueName
91         } else {
92             context.getString(R.string.mobile_data_temp_using, uniqueName)
93         }
94     }
95 
96     companion object {
97         private const val TAG = "DataSubscriptionRepo"
98 
99         @VisibleForTesting const val SUBSCRIPTION_KEY = "subscription"
100     }
101 }
102