• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright 2023 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 package com.android.contacts.sdn
17 
18 import android.Manifest.permission
19 import android.annotation.SuppressLint
20 import android.content.Context
21 import android.content.pm.PackageManager
22 import android.telephony.CarrierConfigManager
23 import android.telephony.SubscriptionManager
24 import android.util.Log
25 import com.android.contacts.model.SimCard
26 import com.android.contacts.util.PermissionsUtil
27 import com.android.contacts.util.PhoneNumberHelper
28 
29 /** Repository to fetch Sdn data from [CarrierConfigManager]. */
30 class SdnRepository constructor(private val context: Context) {
31 
32   fun isSdnPresent(): Boolean {
33     if (
34       !hasTelephony() ||
35       !PermissionsUtil.hasPermission(context, permission.READ_PHONE_STATE) ||
36       !PermissionsUtil.hasPermission(context, permission.READ_PHONE_NUMBERS) ||
37       !PermissionsUtil.hasPermission(context, permission.READ_CALL_LOG)
38     ) {
39       return false
40     }
41 
42     val simCardList = getSimCardInformation()
43 
44     for (simCard in simCardList) {
45       if (fetchSdnFromCarrierConfig(simCard).isNotEmpty()) {
46         Log.i(TAG, "Found SDN list from CarrierConfig")
47         return true
48       }
49     }
50     return false
51   }
52 
53   fun fetchSdn(): List<Sdn> {
54     val simCardList = getSimCardInformation()
55 
56     return simCardList
57       .flatMap { fetchSdnFromCarrierConfig(it) }
58       .distinct()
59       .sortedBy { it.serviceName }
60   }
61 
62   // Permission check isn't recognized by the linter.
63   @SuppressLint("MissingPermission")
64   fun getSimCardInformation(): List<SimCard> {
65     val subscriptionManager = context.getSystemService(SubscriptionManager::class.java)
66     return subscriptionManager?.activeSubscriptionInfoList?.filterNotNull()?.mapNotNull {
67       if (it.subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
68         null
69       } else {
70         SimCard.create(it)
71       }
72     }
73       ?: emptyList()
74   }
75 
76   @Suppress("Deprecation", "MissingPermission")
77   private fun fetchSdnFromCarrierConfig(simCard: SimCard): List<Sdn> {
78     val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)
79     val carrierConfig =
80       carrierConfigManager?.getConfigForSubId(simCard.subscriptionId) ?: return emptyList()
81     val nameList: List<String> =
82       carrierConfig
83         .getStringArray(CarrierConfigManager.KEY_CARRIER_SERVICE_NAME_STRING_ARRAY)
84         ?.map { it?.trim() ?: "" }
85         ?: return emptyList()
86     val numberList: List<String> =
87       carrierConfig
88         .getStringArray(CarrierConfigManager.KEY_CARRIER_SERVICE_NUMBER_STRING_ARRAY)
89         ?.map { it?.trim() ?: "" }
90         ?: return emptyList()
91     if (nameList.isEmpty() || nameList.size != numberList.size) return emptyList()
92 
93     val sdnList = mutableListOf<Sdn>()
94     nameList.zip(numberList).forEach { (sdnServiceName, sdnNumber) ->
95       if (sdnServiceName.isNotBlank() && PhoneNumberHelper.isDialablePhoneNumber(sdnNumber)) {
96         sdnList.add(Sdn(sdnServiceName, sdnNumber))
97       }
98     }
99     return sdnList
100   }
101 
102   private fun hasTelephony(): Boolean {
103     return context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
104   }
105 
106   companion object {
107     private val TAG = SdnRepository::class.java.simpleName
108   }
109 }
110 
111 /** Hold the Service dialing number information to be displayed in SdnActivity. */
112 data class Sdn(
113   val serviceName: String,
114   val serviceNumber: String,
115 ) {
116 
117   /** Generate lookup key that will help identify SDN when Opening QuickContact. */
lookupKeynull118   fun lookupKey(): String {
119     return "non-sim-sdn-" + hashCode()
120   }
121 }
122