blob: 19a508c88cb6a8a68bbf77683840f0a1e9e96837 [file] [log] [blame]
/*
* Copyright (C) 2016 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.internal.telephony;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import com.android.internal.util.ArrayUtils;
import java.util.HashMap;
import java.util.Map;
/**
* This class act as an CarrierSignalling Agent.
* it load registered carrier signalling receivers from Carrier Config and cache the result to avoid
* repeated polling and send the intent to the interested receivers.
* each CarrierSignalAgent is associated with a phone object.
*/
public class CarrierSignalAgent {
private static final String LOG_TAG = "CarrierSignalAgent";
private static final boolean DBG = true;
/** Member variables */
private final Phone mPhone;
/**
* This is a map of intent action -> string array of carrier signal receiver names which are
* interested in this intent action
*/
private final HashMap<String, String[]> mCachedCarrierSignalReceiverNames =
new HashMap<>();
/**
* This is a map of intent action -> carrier config key of signal receiver names which are
* interested in this intent action
*/
private final Map<String, String> mIntentToCarrierConfigKeyMap =
new HashMap<String, String>() {{
put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED,
CarrierConfigManager.KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY);
put(TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE,
CarrierConfigManager.KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY);
put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
CarrierConfigManager.KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY);
}};
/** Constructor */
public CarrierSignalAgent(Phone phone) {
mPhone = phone;
}
/**
* Read carrier signalling receiver name from CarrierConfig based on the intent type
* @return array of receiver Name: the package (a String) name / the class (a String) name
*/
private String[] getCarrierSignalReceiverName(String intentAction) {
String receiverType = mIntentToCarrierConfigKeyMap.get(intentAction);
if(receiverType == null) {
return null;
}
String[] receiverNames = mCachedCarrierSignalReceiverNames.get(intentAction);
// In case of cache miss, we need to look up/load from carrier config.
if (!mCachedCarrierSignalReceiverNames.containsKey(intentAction)) {
CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
.getSystemService(Context.CARRIER_CONFIG_SERVICE);
PersistableBundle b = null;
if (configManager != null) {
b = configManager.getConfig();
}
if (b != null) {
receiverNames = b.getStringArray(receiverType);
if(receiverNames!=null) {
for(String name: receiverNames) {
Rlog.d("loadCarrierSignalReceiverNames: ", name);
}
}
}
mCachedCarrierSignalReceiverNames.put(intentAction, receiverNames);
}
return receiverNames;
}
/**
* Check if there are registered carrier broadcast receivers to handle any registered intents.
*/
public boolean hasRegisteredCarrierSignalReceivers() {
for(String intent : mIntentToCarrierConfigKeyMap.keySet()) {
if(!ArrayUtils.isEmpty(getCarrierSignalReceiverName(intent))) {
return true;
}
}
return false;
}
public boolean notifyCarrierSignalReceivers(Intent intent) {
// Read a list of broadcast receivers from carrier config manager
// which are interested on certain intent type
String[] receiverName = getCarrierSignalReceiverName(intent.getAction());
if (receiverName == null) {
loge("Carrier receiver name is null");
return false;
}
final PackageManager packageManager = mPhone.getContext().getPackageManager();
boolean ret = false;
for(String name : receiverName) {
ComponentName componentName = ComponentName.unflattenFromString(name);
if (componentName == null) {
loge("Carrier receiver name could not be parsed");
return false;
}
intent.setComponent(componentName);
// Check if broadcast receiver is available
if (packageManager.queryBroadcastReceivers(intent,
PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
loge("Carrier signal receiver is configured, but not available: " + name);
break;
}
intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mPhone.getSubId());
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
try {
mPhone.getContext().sendBroadcast(intent);
if (DBG) log("send Intent to carrier signal receiver with action: " +
intent.getAction());
ret = true;
} catch (ActivityNotFoundException e) {
loge("sendBroadcast failed: " + e);
}
}
return ret;
}
/* Clear cached receiver names */
public void reset() {
mCachedCarrierSignalReceiverNames.clear();
}
private void log(String s) {
Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
}
private void loge(String s) {
Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
}
}