1 /*
2  * Copyright (C) 2021 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 
17 package com.android.systemui.util;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.PersistableBundle;
24 import android.telephony.CarrierConfigManager;
25 import android.telephony.SubscriptionManager;
26 import android.util.ArraySet;
27 import android.util.SparseBooleanArray;
28 
29 import androidx.annotation.NonNull;
30 import androidx.annotation.Nullable;
31 
32 import com.android.internal.telephony.TelephonyIntents;
33 import com.android.systemui.broadcast.BroadcastDispatcher;
34 import com.android.systemui.dagger.SysUISingleton;
35 import com.android.systemui.statusbar.policy.CallbackController;
36 
37 import java.util.Set;
38 
39 import javax.inject.Inject;
40 
41 /**
42  * Tracks CarrierConfigs for each subId, as well as the default configuration. CarrierConfigurations
43  * do not trigger a device configuration event, so any UI that relies on carrier configurations must
44  * register with the tracker to get proper updates.
45  *
46  * The tracker also listens for `TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED`
47  *
48  * @see CarrierConfigChangedListener to listen for updates
49  */
50 @SysUISingleton
51 public class CarrierConfigTracker
52         extends BroadcastReceiver
53         implements CallbackController<CarrierConfigTracker.CarrierConfigChangedListener> {
54     private final SparseBooleanArray mCallStrengthConfigs = new SparseBooleanArray();
55     private final SparseBooleanArray mNoCallingConfigs = new SparseBooleanArray();
56     private final SparseBooleanArray mCarrierProvisionsWifiMergedNetworks =
57             new SparseBooleanArray();
58     private final SparseBooleanArray mShowOperatorNameConfigs = new SparseBooleanArray();
59     private final CarrierConfigManager mCarrierConfigManager;
60     private final Set<CarrierConfigChangedListener> mListeners = new ArraySet<>();
61     private final Set<DefaultDataSubscriptionChangedListener> mDataListeners =
62             new ArraySet<>();
63     private boolean mDefaultCallStrengthConfigLoaded;
64     private boolean mDefaultCallStrengthConfig;
65     private boolean mDefaultNoCallingConfigLoaded;
66     private boolean mDefaultNoCallingConfig;
67     private boolean mDefaultCarrierProvisionsWifiMergedNetworksLoaded;
68     private boolean mDefaultCarrierProvisionsWifiMergedNetworks;
69     private boolean mDefaultShowOperatorNameConfigLoaded;
70     private boolean mDefaultShowOperatorNameConfig;
71     private boolean mDefaultAlwaysShowPrimarySignalBarInOpportunisticNetworkConfigLoaded;
72     private boolean mDefaultAlwaysShowPrimarySignalBarInOpportunisticNetworkConfig;
73 
74     @Inject
CarrierConfigTracker( @ullable CarrierConfigManager carrierConfigManager, BroadcastDispatcher broadcastDispatcher)75     public CarrierConfigTracker(
76             @Nullable CarrierConfigManager carrierConfigManager,
77             BroadcastDispatcher broadcastDispatcher) {
78         mCarrierConfigManager = carrierConfigManager;
79         IntentFilter filter = new IntentFilter();
80         filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
81         filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
82         broadcastDispatcher.registerReceiver(this, filter);
83     }
84 
85     @Override
onReceive(Context context, Intent intent)86     public void onReceive(Context context, Intent intent) {
87         String action = intent.getAction();
88         if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) {
89             updateFromNewCarrierConfig(intent);
90         } else if (TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) {
91             updateDefaultDataSubscription(intent);
92         }
93     }
94 
updateFromNewCarrierConfig(Intent intent)95     private void updateFromNewCarrierConfig(Intent intent) {
96         final int subId = intent.getIntExtra(
97                 CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
98                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
99         if (mCarrierConfigManager == null) {
100             return;
101         }
102         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
103             return;
104         }
105 
106         final PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
107         if (config == null) {
108             return;
109         }
110 
111         synchronized (mCallStrengthConfigs) {
112             mCallStrengthConfigs.put(subId, config.getBoolean(
113                     CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL));
114         }
115         synchronized (mNoCallingConfigs) {
116             mNoCallingConfigs.put(subId, config.getBoolean(
117                     CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL));
118         }
119         synchronized (mCarrierProvisionsWifiMergedNetworks) {
120             mCarrierProvisionsWifiMergedNetworks.put(subId, config.getBoolean(
121                     CarrierConfigManager.KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL));
122         }
123         synchronized (mShowOperatorNameConfigs) {
124             mShowOperatorNameConfigs.put(subId, config.getBoolean(
125                     CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL));
126         }
127 
128         notifyCarrierConfigChanged();
129     }
130 
updateDefaultDataSubscription(Intent intent)131     private void updateDefaultDataSubscription(Intent intent) {
132         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, -1);
133         notifyDefaultDataSubscriptionChanged(subId);
134     }
135 
notifyCarrierConfigChanged()136     private void notifyCarrierConfigChanged() {
137         for (CarrierConfigChangedListener l : mListeners) {
138             l.onCarrierConfigChanged();
139         }
140     }
141 
notifyDefaultDataSubscriptionChanged(int subId)142     private void notifyDefaultDataSubscriptionChanged(int subId) {
143         for (DefaultDataSubscriptionChangedListener l : mDataListeners) {
144             l.onDefaultSubscriptionChanged(subId);
145         }
146     }
147 
148     /**
149      * Returns the KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL value for the given subId.
150      */
getCallStrengthConfig(int subId)151     public boolean getCallStrengthConfig(int subId) {
152         synchronized (mCallStrengthConfigs) {
153             if (mCallStrengthConfigs.indexOfKey(subId) >= 0) {
154                 return mCallStrengthConfigs.get(subId);
155             }
156         }
157         if (!mDefaultCallStrengthConfigLoaded) {
158             mDefaultCallStrengthConfig =
159                     CarrierConfigManager.getDefaultConfig().getBoolean(
160                             CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
161             mDefaultCallStrengthConfigLoaded = true;
162         }
163         return mDefaultCallStrengthConfig;
164     }
165 
166     /**
167      * Returns the KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL value for the given subId.
168      */
getNoCallingConfig(int subId)169     public boolean getNoCallingConfig(int subId) {
170         synchronized (mNoCallingConfigs) {
171             if (mNoCallingConfigs.indexOfKey(subId) >= 0) {
172                 return mNoCallingConfigs.get(subId);
173             }
174         }
175         if (!mDefaultNoCallingConfigLoaded) {
176             mDefaultNoCallingConfig =
177                     CarrierConfigManager.getDefaultConfig().getBoolean(
178                             CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
179             mDefaultNoCallingConfigLoaded = true;
180         }
181         return mDefaultNoCallingConfig;
182     }
183 
184     /**
185      * Returns the KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL value for the given subId.
186      */
getCarrierProvisionsWifiMergedNetworksBool(int subId)187     public boolean getCarrierProvisionsWifiMergedNetworksBool(int subId) {
188         synchronized (mCarrierProvisionsWifiMergedNetworks) {
189             if (mCarrierProvisionsWifiMergedNetworks.indexOfKey(subId) >= 0) {
190                 return mCarrierProvisionsWifiMergedNetworks.get(subId);
191             }
192         }
193         if (!mDefaultCarrierProvisionsWifiMergedNetworksLoaded) {
194             mDefaultCarrierProvisionsWifiMergedNetworks =
195                     CarrierConfigManager.getDefaultConfig().getBoolean(
196                             CarrierConfigManager.KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL);
197             mDefaultCarrierProvisionsWifiMergedNetworksLoaded = true;
198         }
199         return mDefaultCarrierProvisionsWifiMergedNetworks;
200     }
201 
202     /**
203      * Returns the KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL value for the default config
204      */
getShowOperatorNameInStatusBarConfigDefault()205     public boolean getShowOperatorNameInStatusBarConfigDefault() {
206         if (!mDefaultShowOperatorNameConfigLoaded) {
207             mDefaultShowOperatorNameConfig = CarrierConfigManager.getDefaultConfig().getBoolean(
208                     CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL);
209             mDefaultShowOperatorNameConfigLoaded = true;
210         }
211 
212         return mDefaultShowOperatorNameConfig;
213     }
214 
215     /**
216      * Returns KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN value for
217      * the default carrier config.
218      */
getAlwaysShowPrimarySignalBarInOpportunisticNetworkDefault()219     public boolean getAlwaysShowPrimarySignalBarInOpportunisticNetworkDefault() {
220         if (!mDefaultAlwaysShowPrimarySignalBarInOpportunisticNetworkConfigLoaded) {
221             mDefaultAlwaysShowPrimarySignalBarInOpportunisticNetworkConfig = CarrierConfigManager
222                     .getDefaultConfig().getBoolean(CarrierConfigManager
223                             .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN
224                     );
225             mDefaultAlwaysShowPrimarySignalBarInOpportunisticNetworkConfigLoaded = true;
226         }
227 
228         return mDefaultAlwaysShowPrimarySignalBarInOpportunisticNetworkConfig;
229     }
230 
231     /**
232      * Returns the KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL value for the given subId, or the
233      * default value if no override exists
234      *
235      * @param subId the subscription id for which to query the config
236      */
getShowOperatorNameInStatusBarConfig(int subId)237     public boolean getShowOperatorNameInStatusBarConfig(int subId) {
238         if (mShowOperatorNameConfigs.indexOfKey(subId) >= 0) {
239             return mShowOperatorNameConfigs.get(subId);
240         } else {
241             return getShowOperatorNameInStatusBarConfigDefault();
242         }
243     }
244 
245     @Override
addCallback(@onNull CarrierConfigChangedListener listener)246     public void addCallback(@NonNull CarrierConfigChangedListener listener) {
247         mListeners.add(listener);
248     }
249 
250     @Override
removeCallback(@onNull CarrierConfigChangedListener listener)251     public void removeCallback(@NonNull CarrierConfigChangedListener listener) {
252         mListeners.remove(listener);
253     }
254 
255     /** */
addDefaultDataSubscriptionChangedListener( @onNull DefaultDataSubscriptionChangedListener listener)256     public void addDefaultDataSubscriptionChangedListener(
257             @NonNull DefaultDataSubscriptionChangedListener listener) {
258         mDataListeners.add(listener);
259     }
260 
261     /** */
removeDataSubscriptionChangedListener( DefaultDataSubscriptionChangedListener listener)262     public void removeDataSubscriptionChangedListener(
263             DefaultDataSubscriptionChangedListener listener) {
264         mDataListeners.remove(listener);
265     }
266 
267     /**
268      * Called when carrier config changes
269      */
270     public interface CarrierConfigChangedListener {
271         /** */
onCarrierConfigChanged()272         void onCarrierConfigChanged();
273     }
274 
275     /**
276      * Called when the default data subscription changes. Listeners may want to query
277      * subId-dependent configuration values when this event happens
278      */
279     public interface DefaultDataSubscriptionChangedListener {
280         /**
281          * @param subId the new default data subscription id per
282          * {@link SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX}
283          */
onDefaultSubscriptionChanged(int subId)284         void onDefaultSubscriptionChanged(int subId);
285     }
286 }
287