1 /* 2 * Copyright (C) 2016 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.internal.telephony; 17 18 import android.content.ActivityNotFoundException; 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.pm.PackageManager; 23 import android.os.PersistableBundle; 24 import android.telephony.CarrierConfigManager; 25 import android.telephony.Rlog; 26 27 import com.android.internal.util.ArrayUtils; 28 29 import java.util.HashMap; 30 import java.util.Map; 31 32 /** 33 * This class act as an CarrierSignalling Agent. 34 * it load registered carrier signalling receivers from Carrier Config and cache the result to avoid 35 * repeated polling and send the intent to the interested receivers. 36 * each CarrierSignalAgent is associated with a phone object. 37 */ 38 public class CarrierSignalAgent { 39 40 private static final String LOG_TAG = "CarrierSignalAgent"; 41 private static final boolean DBG = true; 42 43 /** Member variables */ 44 private final Phone mPhone; 45 /** 46 * This is a map of intent action -> string array of carrier signal receiver names which are 47 * interested in this intent action 48 */ 49 private final HashMap<String, String[]> mCachedCarrierSignalReceiverNames = 50 new HashMap<>(); 51 /** 52 * This is a map of intent action -> carrier config key of signal receiver names which are 53 * interested in this intent action 54 */ 55 private final Map<String, String> mIntentToCarrierConfigKeyMap = 56 new HashMap<String, String>() {{ 57 put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED, 58 CarrierConfigManager.KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY); 59 put(TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE, 60 CarrierConfigManager.KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY); 61 put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED, 62 CarrierConfigManager.KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY); 63 }}; 64 65 /** Constructor */ CarrierSignalAgent(Phone phone)66 public CarrierSignalAgent(Phone phone) { 67 mPhone = phone; 68 } 69 70 /** 71 * Read carrier signalling receiver name from CarrierConfig based on the intent type 72 * @return array of receiver Name: the package (a String) name / the class (a String) name 73 */ getCarrierSignalReceiverName(String intentAction)74 private String[] getCarrierSignalReceiverName(String intentAction) { 75 String receiverType = mIntentToCarrierConfigKeyMap.get(intentAction); 76 if(receiverType == null) { 77 return null; 78 } 79 String[] receiverNames = mCachedCarrierSignalReceiverNames.get(intentAction); 80 // In case of cache miss, we need to look up/load from carrier config. 81 if (!mCachedCarrierSignalReceiverNames.containsKey(intentAction)) { 82 CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext() 83 .getSystemService(Context.CARRIER_CONFIG_SERVICE); 84 PersistableBundle b = null; 85 if (configManager != null) { 86 b = configManager.getConfig(); 87 } 88 if (b != null) { 89 receiverNames = b.getStringArray(receiverType); 90 if(receiverNames!=null) { 91 for(String name: receiverNames) { 92 Rlog.d("loadCarrierSignalReceiverNames: ", name); 93 } 94 } 95 } 96 mCachedCarrierSignalReceiverNames.put(intentAction, receiverNames); 97 } 98 return receiverNames; 99 } 100 101 /** 102 * Check if there are registered carrier broadcast receivers to handle any registered intents. 103 */ hasRegisteredCarrierSignalReceivers()104 public boolean hasRegisteredCarrierSignalReceivers() { 105 for(String intent : mIntentToCarrierConfigKeyMap.keySet()) { 106 if(!ArrayUtils.isEmpty(getCarrierSignalReceiverName(intent))) { 107 return true; 108 } 109 } 110 return false; 111 } 112 notifyCarrierSignalReceivers(Intent intent)113 public boolean notifyCarrierSignalReceivers(Intent intent) { 114 // Read a list of broadcast receivers from carrier config manager 115 // which are interested on certain intent type 116 String[] receiverName = getCarrierSignalReceiverName(intent.getAction()); 117 if (receiverName == null) { 118 loge("Carrier receiver name is null"); 119 return false; 120 } 121 final PackageManager packageManager = mPhone.getContext().getPackageManager(); 122 boolean ret = false; 123 124 for(String name : receiverName) { 125 ComponentName componentName = ComponentName.unflattenFromString(name); 126 if (componentName == null) { 127 loge("Carrier receiver name could not be parsed"); 128 return false; 129 } 130 intent.setComponent(componentName); 131 // Check if broadcast receiver is available 132 if (packageManager.queryBroadcastReceivers(intent, 133 PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { 134 loge("Carrier signal receiver is configured, but not available: " + name); 135 break; 136 } 137 138 intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mPhone.getSubId()); 139 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 140 141 try { 142 mPhone.getContext().sendBroadcast(intent); 143 if (DBG) log("send Intent to carrier signal receiver with action: " + 144 intent.getAction()); 145 ret = true; 146 } catch (ActivityNotFoundException e) { 147 loge("sendBroadcast failed: " + e); 148 } 149 } 150 151 return ret; 152 } 153 154 /* Clear cached receiver names */ reset()155 public void reset() { 156 mCachedCarrierSignalReceiverNames.clear(); 157 } 158 log(String s)159 private void log(String s) { 160 Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); 161 } 162 loge(String s)163 private void loge(String s) { 164 Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s); 165 } 166 } 167