• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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