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;
196a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport android.content.BroadcastReceiver;
204c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.ComponentName;
214c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.Context;
224c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.Intent;
236a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport android.content.IntentFilter;
244c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.content.pm.PackageManager;
254c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.os.PersistableBundle;
264c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.telephony.CarrierConfigManager;
274c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport android.telephony.Rlog;
286a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport android.text.TextUtils;
296a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport android.util.LocalLog;
306a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport android.util.Log;
314c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
324c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport com.android.internal.util.ArrayUtils;
336a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport com.android.internal.util.IndentingPrintWriter;
344c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
356a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.io.FileDescriptor;
366a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.io.PrintWriter;
376a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.util.ArrayList;
386a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.util.Arrays;
394c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport java.util.HashMap;
406a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.util.HashSet;
416a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.util.List;
424c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxuimport java.util.Map;
436a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport java.util.Set;
446a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
456a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport static android.telephony.CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY;
466a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxuimport static android.telephony.CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY;
474c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
484c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu/**
494c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * This class act as an CarrierSignalling Agent.
506a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu * it load registered carrier signalling receivers from carrier config, cache the result to avoid
514c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu * repeated polling and send the intent to the interested receivers.
526a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu * Each CarrierSignalAgent is associated with a phone object.
534c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu */
544c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxupublic class CarrierSignalAgent {
554c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
566a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private static final String LOG_TAG = CarrierSignalAgent.class.getSimpleName();
574c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private static final boolean DBG = true;
586a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private static final boolean VDBG = Rlog.isLoggable(LOG_TAG, Log.VERBOSE);
596a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private static final boolean WAKE = true;
606a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private static final boolean NO_WAKE = false;
616a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
626a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    /** delimiters for parsing config of the form: pakName./receiverName : signal1, signal2,..*/
636a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private static final String COMPONENT_NAME_DELIMITER = "\\s*:\\s*";
646a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private static final String CARRIER_SIGNAL_DELIMITER = "\\s*,\\s*";
654c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
664c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /** Member variables */
674c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private final Phone mPhone;
686a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
694c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
706a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * This is a map of intent action -> array list of component name of statically registered
716a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * carrier signal receivers(wakeup receivers).
726a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Those intents are declared in the Manifest files, aiming to wakeup broadcast receivers.
736a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Carrier apps should be careful when configuring the wake signal list to avoid unnecessary
746a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * wakeup.
756a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @see CarrierConfigManager#KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY
764c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
776a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private final Map<String, List<ComponentName>> mCachedWakeSignalConfigs = new HashMap<>();
786a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
794c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
806a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * This is a map of intent action -> array list of component name of dynamically registered
816a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * carrier signal receivers(non-wakeup receivers). Those intents will not wake up the apps.
826a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Note Carrier apps should avoid configuring no wake signals in there Manifest files.
836a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @see CarrierConfigManager#KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY
844c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
856a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private final Map<String, List<ComponentName>> mCachedNoWakeSignalConfigs = new HashMap<>();
866a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
876a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    /**
886a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * This is a list of supported signals from CarrierSignalAgent
896a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     */
906a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private final Set<String> mCarrierSignalList = new HashSet<>(Arrays.asList(
914c9ca958d2ecb645d643d08c65f931e255138d71fionaxu            TelephonyIntents.ACTION_CARRIER_SIGNAL_PCO_VALUE,
924c9ca958d2ecb645d643d08c65f931e255138d71fionaxu            TelephonyIntents.ACTION_CARRIER_SIGNAL_REDIRECTED,
934c9ca958d2ecb645d643d08c65f931e255138d71fionaxu            TelephonyIntents.ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED,
944c9ca958d2ecb645d643d08c65f931e255138d71fionaxu            TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET));
956a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
966a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private final LocalLog mErrorLocalLog = new LocalLog(20);
976a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
986a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
996a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        public void onReceive(Context context, Intent intent) {
1006a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            String action = intent.getAction();
1016a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (DBG) log("CarrierSignalAgent receiver action: " + action);
1026a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
1034c9ca958d2ecb645d643d08c65f931e255138d71fionaxu                // notify carrier apps before cache get purged
104d2569726c9c5a93c852ec6ddd5ca80c760845061fionaxu                if (mPhone.getIccCard() != null
105d2569726c9c5a93c852ec6ddd5ca80c760845061fionaxu                        && IccCardConstants.State.ABSENT == mPhone.getIccCard().getState()) {
1064c9ca958d2ecb645d643d08c65f931e255138d71fionaxu                    notifyCarrierSignalReceivers(
1074c9ca958d2ecb645d643d08c65f931e255138d71fionaxu                            new Intent(TelephonyIntents.ACTION_CARRIER_SIGNAL_RESET));
1084c9ca958d2ecb645d643d08c65f931e255138d71fionaxu                }
1096a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                loadCarrierConfig();
1106a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            }
1116a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        }
1126a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    };
1134c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1144c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /** Constructor */
1154c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    public CarrierSignalAgent(Phone phone) {
1164c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        mPhone = phone;
1176a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        loadCarrierConfig();
1186a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        // reload configurations on CARRIER_CONFIG_CHANGED
1196a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        mPhone.getContext().registerReceiver(mReceiver,
1206a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
1214c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1224c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1234c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
1246a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * load carrier config and cached the results into a hashMap action -> array list of components.
1254c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
1266a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private void loadCarrierConfig() {
1276a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
1286a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
1296a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        PersistableBundle b = null;
1306a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        if (configManager != null) {
1316a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            b = configManager.getConfig();
1324c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
1336a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        if (b != null) {
1346a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            synchronized (mCachedWakeSignalConfigs) {
1356a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                mCachedWakeSignalConfigs.clear();
1366a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                log("Loading carrier config: " + KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY);
1376a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                parseAndCache(b.getStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY),
1386a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        mCachedWakeSignalConfigs);
1394c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1406a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
1416a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            synchronized (mCachedNoWakeSignalConfigs) {
1426a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                mCachedNoWakeSignalConfigs.clear();
1436a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                log("Loading carrier config: "
1446a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        + KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY);
1456a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                parseAndCache(b.getStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY),
1466a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        mCachedNoWakeSignalConfigs);
1474c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1484c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
1494c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1504c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1514c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    /**
1526a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Parse each config with the form {pakName./receiverName : signal1, signal2,.} and cached the
1536a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * result internally to avoid repeated polling
1546a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @see #CARRIER_SIGNAL_DELIMITER
1556a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @see #COMPONENT_NAME_DELIMITER
1566a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @param configs raw information from carrier config
1574c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu     */
1586a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private void parseAndCache(String[] configs,
1596a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                               Map<String, List<ComponentName>> cachedConfigs) {
1606a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        if (!ArrayUtils.isEmpty(configs)) {
1616a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            for (String config : configs) {
1626a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                if (!TextUtils.isEmpty(config)) {
1636a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                    String[] splitStr = config.trim().split(COMPONENT_NAME_DELIMITER, 2);
1646a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                    if (splitStr.length == 2) {
1656a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        ComponentName componentName = ComponentName
1666a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                .unflattenFromString(splitStr[0]);
1676a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        if (componentName == null) {
1686a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            loge("Invalid component name: " + splitStr[0]);
1696a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            continue;
1706a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        }
1716a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        String[] signals = splitStr[1].split(CARRIER_SIGNAL_DELIMITER);
1726a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        for (String s : signals) {
1736a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            if (!mCarrierSignalList.contains(s)) {
1746a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                loge("Invalid signal name: " + s);
1756a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                continue;
1766a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            }
1776a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            List<ComponentName> componentList = cachedConfigs.get(s);
1786a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            if (componentList == null) {
1796a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                componentList = new ArrayList<>();
1806a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                cachedConfigs.put(s, componentList);
1816a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            }
1826a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            componentList.add(componentName);
1836a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            if (VDBG) {
1846a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                logv("Add config " + "{signal: " + s
1856a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                                        + " componentName: " + componentName + "}");
1866a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            }
1876a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        }
1886a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                    } else {
1896a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        loge("invalid config format: " + config);
1906a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                    }
1916a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                }
1924c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
1934c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
1944c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
1954c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
1966a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    /**
1976a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Check if there are registered carrier broadcast receivers to handle the passing intent
1986a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     */
1996a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    public boolean hasRegisteredReceivers(String action) {
2004c9ca958d2ecb645d643d08c65f931e255138d71fionaxu        return mCachedWakeSignalConfigs.containsKey(action)
2014c9ca958d2ecb645d643d08c65f931e255138d71fionaxu                || mCachedNoWakeSignalConfigs.containsKey(action);
2026a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    }
2036a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
2046a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    /**
2056a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Broadcast the intents explicitly.
2066a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Some sanity check will be applied before broadcasting.
2076a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * - for non-wakeup(runtime) receivers, make sure the intent is not declared in their manifests
2086a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * and apply FLAG_EXCLUDE_STOPPED_PACKAGES to avoid wake-up
2096a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * - for wakeup(manifest) receivers, make sure there are matched receivers with registered
2106a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * intents.
2116a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     *
2126a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @param intent intent which signals carrier apps
2136a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @param receivers a list of component name for broadcast receivers.
2146a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     *                  Those receivers could either be statically declared in Manifest or
2156a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     *                  registered during run-time.
2166a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @param wakeup true indicate wakeup receivers otherwise non-wakeup receivers
2176a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     */
2186a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private void broadcast(Intent intent, List<ComponentName> receivers, boolean wakeup) {
2194c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        final PackageManager packageManager = mPhone.getContext().getPackageManager();
2206a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        for (ComponentName name : receivers) {
2216a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            Intent signal = new Intent(intent);
2226a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            signal.setComponent(name);
2234c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
2246a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (wakeup && packageManager.queryBroadcastReceivers(signal,
2256a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                    PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
2266a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                loge("Carrier signal receivers are configured but unavailable: "
2276a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        + signal.getComponent());
2286a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                return;
2294c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
2306a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (!wakeup && !packageManager.queryBroadcastReceivers(signal,
2314c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu                    PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
2326a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                loge("Runtime signals shouldn't be configured in Manifest: "
2336a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                        + signal.getComponent());
2346a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                return;
2354c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
2364c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
2376a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            signal.putExtra(PhoneConstants.SUBSCRIPTION_KEY, mPhone.getSubId());
2386a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            signal.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
2396a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (!wakeup) signal.setFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
2404c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
2414c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            try {
2426a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                mPhone.getContext().sendBroadcast(signal);
2436a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                if (DBG) {
2446a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                    log("Sending signal " + signal.getAction() + ((signal.getComponent() != null)
2456a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                            ? " to the carrier signal receiver: " + signal.getComponent() : ""));
2466a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                }
2474c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            } catch (ActivityNotFoundException e) {
2486a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                loge("Send broadcast failed: " + e);
2494c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu            }
2504c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        }
2514c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
2524c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
2536a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    /**
2546a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * Match the intent against cached tables to find a list of registered carrier signal
2556a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * receivers and broadcast the intent.
2566a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     * @param intent broadcasting intent, it could belong to wakeup, non-wakeup signal list or both
2576a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     *
2586a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu     */
2596a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    public void notifyCarrierSignalReceivers(Intent intent) {
2606a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        List<ComponentName> receiverList;
2616a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
2626a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        synchronized (mCachedWakeSignalConfigs) {
2634c9ca958d2ecb645d643d08c65f931e255138d71fionaxu            receiverList = mCachedWakeSignalConfigs.get(intent.getAction());
2646a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (!ArrayUtils.isEmpty(receiverList)) {
2656a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                broadcast(intent, receiverList, WAKE);
2666a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            }
2676a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        }
2686a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
2696a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        synchronized (mCachedNoWakeSignalConfigs) {
2704c9ca958d2ecb645d643d08c65f931e255138d71fionaxu            receiverList = mCachedNoWakeSignalConfigs.get(intent.getAction());
2716a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            if (!ArrayUtils.isEmpty(receiverList)) {
2726a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu                broadcast(intent, receiverList, NO_WAKE);
2736a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            }
2746a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        }
2754c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
2764c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
2774c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private void log(String s) {
2784c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
2794c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
2804c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu
2814c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    private void loge(String s) {
2826a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        mErrorLocalLog.log(s);
2834c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu        Rlog.e(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
2844c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu    }
2856a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
2866a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    private void logv(String s) {
2876a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        Rlog.v(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
2886a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    }
2896a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
2906a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2916a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
2926a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        pw.println("mCachedWakeSignalConfigs:");
2936a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        ipw.increaseIndent();
2946a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        for (Map.Entry<String, List<ComponentName>> entry : mCachedWakeSignalConfigs.entrySet()) {
2956a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            pw.println("signal: " + entry.getKey() + " componentName list: " + entry.getValue());
2966a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        }
2976a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        ipw.decreaseIndent();
2986a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
2996a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        pw.println("mCachedNoWakeSignalConfigs:");
3006a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        ipw.increaseIndent();
3016a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        for (Map.Entry<String, List<ComponentName>> entry : mCachedNoWakeSignalConfigs.entrySet()) {
3026a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu            pw.println("signal: " + entry.getKey() + " componentName list: " + entry.getValue());
3036a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        }
3046a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        ipw.decreaseIndent();
3056a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu
3066a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        pw.println("error log:");
3076a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        ipw.increaseIndent();
3086a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        mErrorLocalLog.dump(fd, pw, args);
3096a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu        ipw.decreaseIndent();
3106a7fb078d1cacba7cf2e83b71242bb5c4c27c975fionaxu    }
3114c31e4c0d2db31fe84081aa6f1e2bcc08b31f9d3fionaxu}
312