14c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu/*
24c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * Copyright (C) 2016 The Android Open Source Project
34c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu *
44c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * Licensed under the Apache License, Version 2.0 (the "License");
54c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * you may not use this file except in compliance with the License.
64c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * You may obtain a copy of the License at
74c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu *
84c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu *      http://www.apache.org/licenses/LICENSE-2.0
94c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu *
104c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * Unless required by applicable law or agreed to in writing, software
114c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * distributed under the License is distributed on an "AS IS" BASIS,
124c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * See the License for the specific language governing permissions and
144c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * limitations under the License.
154c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu */
164c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxupackage com.android.internal.telephony;
174c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
184c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.ActivityNotFoundException;
194c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.ComponentName;
204c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.Context;
214c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.Intent;
224c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.pm.PackageManager;
234c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.os.PersistableBundle;
244c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.telephony.CarrierConfigManager;
254c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.telephony.Rlog;
264c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
274c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport com.android.internal.util.ArrayUtils;
284c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
294c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport java.util.HashMap;
304c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport java.util.Map;
314c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
324c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu/**
334c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * This class act as an CarrierSignalling Agent.
344c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * it load registered carrier signalling receivers from Carrier Config and cache the result to avoid
354c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * repeated polling and send the intent to the interested receivers.
364c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * each CarrierSignalAgent is associated with a phone object.
374c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu */
384c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxupublic class CarrierSignalAgent {
394c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
404c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private static final String LOG_TAG = "CarrierSignalAgent";
414c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private static final boolean DBG = true;
424c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
434c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /** Member variables */
444c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private final Phone mPhone;
454c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
464c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * This is a map of intent action -> string array of carrier signal receiver names which are
474c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * interested in this intent action
484c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
49c4ed983e8df098f4b3538e5114e8992f03cac095fionaxu    private final HashMap<String, String[]> mCachedCarrierSignalReceiverNames =
504c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            new HashMap<>();
514c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
524c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * This is a map of intent action -> carrier config key of signal receiver names which are
534c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * interested in this intent action
544c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
55c4ed983e8df098f4b3538e5114e8992f03cac095fionaxu    private final Map<String, String> mIntentToCarrierConfigKeyMap =
564c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            new HashMap<String, String>() {{
574c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED,
584c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                        CarrierConfigManager.KEY_SIGNAL_REDIRECTION_RECEIVER_STRING_ARRAY);
594c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                put(TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE,
604c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                        CarrierConfigManager.KEY_SIGNAL_PCO_RECEIVER_STRING_ARRAY);
614c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                put(TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
624c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                        CarrierConfigManager.KEY_SIGNAL_DCFAILURE_RECEIVER_STRING_ARRAY);
634c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }};
644c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
654c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /** Constructor */
664c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    public CarrierSignalAgent(Phone phone) {
674c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        mPhone = phone;
684c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
694c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
704c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
714c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * Read carrier signalling receiver name from CarrierConfig based on the intent type
724c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * @return array of receiver Name: the package (a String) name / the class (a String) name
734c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
744c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private String[] getCarrierSignalReceiverName(String intentAction) {
754c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        String receiverType = mIntentToCarrierConfigKeyMap.get(intentAction);
764c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        if(receiverType == null) {
774c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            return null;
784c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
794c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        String[] receiverNames = mCachedCarrierSignalReceiverNames.get(intentAction);
804c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        // In case of cache miss, we need to look up/load from carrier config.
814c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        if (!mCachedCarrierSignalReceiverNames.containsKey(intentAction)) {
824c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
834c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                    .getSystemService(Context.CARRIER_CONFIG_SERVICE);
844c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            PersistableBundle b = null;
854c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            if (configManager != null) {
864c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                b = configManager.getConfig();
874c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
884c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            if (b != null) {
894c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                receiverNames = b.getStringArray(receiverType);
904c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                if(receiverNames!=null) {
914c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                    for(String name: receiverNames) {
924c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                        Rlog.d("loadCarrierSignalReceiverNames: ", name);
934c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                    }
944c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                }
954c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
964c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            mCachedCarrierSignalReceiverNames.put(intentAction, receiverNames);
974c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
984c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        return receiverNames;
994c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1004c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1014c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
1024c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     * Check if there are registered carrier broadcast receivers to handle any registered intents.
1034c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
1044c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    public boolean hasRegisteredCarrierSignalReceivers() {
1054c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        for(String intent : mIntentToCarrierConfigKeyMap.keySet()) {
1064c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            if(!ArrayUtils.isEmpty(getCarrierSignalReceiverName(intent))) {
1074c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                return true;
1084c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1094c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
1104c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        return false;
1114c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1124c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1134c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    public boolean notifyCarrierSignalReceivers(Intent intent) {
1144c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        // Read a list of broadcast receivers from carrier config manager
1154c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        // which are interested on certain intent type
1164c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        String[] receiverName = getCarrierSignalReceiverName(intent.getAction());
1174c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        if (receiverName == null) {
1184c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            loge("Carrier receiver name is null");
1194c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            return false;
1204c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
1214c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        final PackageManager packageManager = mPhone.getContext().getPackageManager();
1224c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        boolean ret = false;
1234c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1244c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        for(String name : receiverName) {
1254c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            ComponentName componentName = ComponentName.unflattenFromString(name);
1264c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            if (componentName == null) {
1274c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                loge("Carrier receiver name could not be parsed");
1284c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                return false;
1294c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1304c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            intent.setComponent(componentName);
1314c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            // Check if broadcast receiver is available
1324c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            if (packageManager.queryBroadcastReceivers(intent,
1334c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                    PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
1344c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                loge("Carrier signal receiver is configured, but not available: " + name);
1354c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                break;
1364c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1374c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1384c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mPhone.getSubId());
1394c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
1404c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1414c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            try {
1424c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                mPhone.getContext().sendBroadcast(intent);
1434c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                if (DBG) log("send Intent to carrier signal receiver with action: " +
1444c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                        intent.getAction());
1454c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                ret = true;
1464c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            } catch (ActivityNotFoundException e) {
1474c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                loge("sendBroadcast failed: " + e);
1484c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1494c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
1504c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1514c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        return ret;
1524c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1534c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1544c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /* Clear cached receiver names */
1554c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    public void reset() {
1564c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        mCachedCarrierSignalReceiverNames.clear();
1574c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1584c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1594c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private void log(String s) {
1604c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
1614c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1624c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1634c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private void loge(String s) {
1644c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
1654c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1664c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu}
167