• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.server.telecom.callredirection;
18 
19 import android.Manifest;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.ResolveInfo;
24 import android.net.Uri;
25 import android.os.PersistableBundle;
26 import android.telecom.CallRedirectionService;
27 import android.telecom.GatewayInfo;
28 import android.telecom.Log;
29 import android.telecom.PhoneAccountHandle;
30 import android.telephony.CarrierConfigManager;
31 import android.telephony.PhoneNumberUtils;
32 import android.telephony.TelephonyManager;
33 import android.text.TextUtils;
34 import com.android.internal.annotations.VisibleForTesting;
35 import com.android.server.telecom.CallsManager;
36 import com.android.server.telecom.PhoneAccountRegistrar;
37 
38 import java.util.List;
39 
40 public class CallRedirectionProcessorHelper {
41 
42     private final Context mContext;
43     private final CallsManager mCallsManager;
44     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
45 
CallRedirectionProcessorHelper( Context context, CallsManager callsManager, PhoneAccountRegistrar phoneAccountRegistrar)46     public CallRedirectionProcessorHelper(
47             Context context,
48             CallsManager callsManager,
49             PhoneAccountRegistrar phoneAccountRegistrar) {
50         mContext = context;
51         mCallsManager = callsManager;
52         mPhoneAccountRegistrar = phoneAccountRegistrar;
53     }
54 
55     @VisibleForTesting
getUserDefinedCallRedirectionService()56     public ComponentName getUserDefinedCallRedirectionService() {
57         String packageName = mCallsManager.getRoleManagerAdapter().getDefaultCallRedirectionApp();
58         if (TextUtils.isEmpty(packageName)) {
59             Log.i(this, "PackageName is empty. Not performing user-defined call redirection.");
60             return null;
61         }
62         Intent intent = new Intent(CallRedirectionService.SERVICE_INTERFACE)
63                 .setPackage(packageName);
64         return getComponentName(intent, CallRedirectionProcessor.SERVICE_TYPE_USER_DEFINED);
65     }
66 
67     @VisibleForTesting
getCarrierCallRedirectionService( PhoneAccountHandle targetPhoneAccountHandle)68     public ComponentName getCarrierCallRedirectionService(
69             PhoneAccountHandle targetPhoneAccountHandle) {
70         CarrierConfigManager configManager = (CarrierConfigManager)
71                 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
72         if (configManager == null) {
73             Log.i(this, "Cannot get CarrierConfigManager.");
74             return null;
75         }
76         PersistableBundle pb = configManager.getConfigForSubId(mPhoneAccountRegistrar
77                 .getSubscriptionIdForPhoneAccount(targetPhoneAccountHandle));
78         if (pb == null) {
79             Log.i(this, "Cannot get PersistableBundle.");
80             return null;
81         }
82         String componentNameString = pb.getString(
83                 CarrierConfigManager.KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING);
84         if (componentNameString == null) {
85             Log.i(this, "Cannot get carrier componentNameString.");
86             return null;
87         }
88         ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
89         if (componentName == null) {
90             Log.w(this, "ComponentName is null from string: " + componentNameString);
91             return null;
92         }
93         Intent intent = new Intent(CallRedirectionService.SERVICE_INTERFACE);
94         intent.setComponent(componentName);
95         return getComponentName(intent, CallRedirectionProcessor.SERVICE_TYPE_CARRIER);
96     }
97 
getComponentName(Intent intent, String serviceType)98     protected ComponentName getComponentName(Intent intent, String serviceType) {
99         List<ResolveInfo> entries = mContext.getPackageManager().queryIntentServicesAsUser(
100                 intent, 0, mCallsManager.getCurrentUserHandle().getIdentifier());
101         if (entries.isEmpty()) {
102             Log.i(this, "There are no " + serviceType + " call redirection services installed" +
103                     " on this device.");
104             return null;
105         } else if (entries.size() != 1) {
106             Log.i(this, "There are multiple " + serviceType + " call redirection services" +
107                     " installed on this device.");
108             return null;
109         }
110         ResolveInfo entry = entries.get(0);
111         if (entry.serviceInfo == null) {
112             Log.w(this, "The " + serviceType + " call redirection service has invalid" +
113                     " service info");
114             return null;
115         }
116         if (entry.serviceInfo.permission == null || !entry.serviceInfo.permission.equals(
117                 Manifest.permission.BIND_CALL_REDIRECTION_SERVICE)) {
118             Log.w(this, "CallRedirectionService must require BIND_CALL_REDIRECTION_SERVICE"
119                     + " permission: " + entry.serviceInfo.packageName);
120             return null;
121         }
122         return new ComponentName(entry.serviceInfo.packageName, entry.serviceInfo.name);
123     }
124 
125     /**
126      * Format Number to E164, and remove post dial digits.
127      */
formatNumberForRedirection(Uri handle)128     protected Uri formatNumberForRedirection(Uri handle) {
129         return removePostDialDigits(formatNumberToE164(handle));
130     }
131 
formatNumberToE164(Uri handle)132     protected Uri formatNumberToE164(Uri handle) {
133         String number = handle.getSchemeSpecificPart();
134 
135         // Format number to E164
136         TelephonyManager tm = (TelephonyManager) mContext.getSystemService(
137                 Context.TELEPHONY_SERVICE);
138         Log.i(this, "formatNumberToE164, original number: " + Log.pii(number));
139         number = PhoneNumberUtils.formatNumberToE164(number, tm.getNetworkCountryIso());
140         Log.i(this, "formatNumberToE164, formatted E164 number: " + Log.pii(number));
141         // if there is a problem with parsing the phone number, formatNumberToE164 will return null;
142         // and should just use the original number in that case.
143         if (number == null) {
144             return handle;
145         } else {
146             return Uri.fromParts(handle.getScheme(), number, null);
147         }
148     }
149 
removePostDialDigits(Uri handle)150     protected Uri removePostDialDigits(Uri handle) {
151         String number = handle.getSchemeSpecificPart();
152 
153         // Extract the post dial portion
154         number = PhoneNumberUtils.extractNetworkPortionAlt(number);
155         Log.i(this, "removePostDialDigits, number after being extracted post dial digits: "
156                 + Log.pii(number));
157         // if there is a problem with parsing the phone number, removePostDialDigits will return
158         // null; and should just use the original number in that case.
159         if (number == null) {
160             return handle;
161         } else {
162             return Uri.fromParts(handle.getScheme(), number, null);
163         }
164     }
165 
getGatewayInfoFromGatewayUri( String gatewayPackageName, Uri gatewayUri, Uri destinationUri)166     protected GatewayInfo getGatewayInfoFromGatewayUri(
167             String gatewayPackageName, Uri gatewayUri, Uri destinationUri) {
168         if (!TextUtils.isEmpty(gatewayPackageName) && gatewayUri != null) {
169             return new GatewayInfo(gatewayPackageName, gatewayUri, destinationUri);
170         }
171         return null;
172     }
173 }
174