blob: 07591270cbf1e02c94754ce6b9fca2e0a132d41b [file] [log] [blame]
/*
* Copyright 2023 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.contacts.sdn
import android.Manifest.permission
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.telephony.CarrierConfigManager
import android.telephony.SubscriptionManager
import android.util.Log
import com.android.contacts.model.SimCard
import com.android.contacts.util.PermissionsUtil
import com.android.contacts.util.PhoneNumberHelper
/** Repository to fetch Sdn data from [CarrierConfigManager]. */
class SdnRepository constructor(private val context: Context) {
fun isSdnPresent(): Boolean {
if (
!hasTelephony() ||
!PermissionsUtil.hasPermission(context, permission.READ_PHONE_STATE) ||
!PermissionsUtil.hasPermission(context, permission.READ_PHONE_NUMBERS) ||
!PermissionsUtil.hasPermission(context, permission.READ_CALL_LOG)
) {
return false
}
val simCardList = getSimCardInformation()
for (simCard in simCardList) {
if (fetchSdnFromCarrierConfig(simCard).isNotEmpty()) {
Log.i(TAG, "Found SDN list from CarrierConfig")
return true
}
}
return false
}
fun fetchSdn(): List<Sdn> {
val simCardList = getSimCardInformation()
return simCardList
.flatMap { fetchSdnFromCarrierConfig(it) }
.distinct()
.sortedBy { it.serviceName }
}
// Permission check isn't recognized by the linter.
@SuppressLint("MissingPermission")
fun getSimCardInformation(): List<SimCard> {
val subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
return subscriptionManager?.activeSubscriptionInfoList?.filterNotNull()?.mapNotNull {
if (it.subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
null
} else {
SimCard.create(it)
}
}
?: emptyList()
}
@Suppress("Deprecation", "MissingPermission")
private fun fetchSdnFromCarrierConfig(simCard: SimCard): List<Sdn> {
val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)
val carrierConfig =
carrierConfigManager?.getConfigForSubId(simCard.subscriptionId) ?: return emptyList()
val nameList: List<String> =
carrierConfig
.getStringArray(CarrierConfigManager.KEY_CARRIER_SERVICE_NAME_STRING_ARRAY)
?.map { it?.trim() ?: "" }
?: return emptyList()
val numberList: List<String> =
carrierConfig
.getStringArray(CarrierConfigManager.KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY)
?.map { it?.trim() ?: "" }
?: return emptyList()
if (nameList.isEmpty() || nameList.size != numberList.size) return emptyList()
val sdnList = mutableListOf<Sdn>()
nameList.zip(numberList).forEach { (sdnServiceName, sdnNumber) ->
if (sdnServiceName.isNotBlank() && PhoneNumberHelper.isDialablePhoneNumber(sdnNumber)) {
sdnList.add(Sdn(sdnServiceName, sdnNumber))
}
}
return sdnList
}
private fun hasTelephony(): Boolean {
return context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
}
companion object {
private val TAG = SdnRepository::class.java.simpleName
}
}
/** Hold the Service dialing number information to be displayed in SdnActivity. */
data class Sdn(
val serviceName: String,
val serviceNumber: String,
) {
/** Generate lookup key that will help identify SDN when Opening QuickContact. */
fun lookupKey(): String {
return "non-sim-sdn-" + hashCode()
}
}