summaryrefslogtreecommitdiff
path: root/src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java')
-rw-r--r--src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java280
1 files changed, 194 insertions, 86 deletions
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java b/src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java
index a56cd0a42..973fab896 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java
@@ -18,15 +18,22 @@ package com.android.cellbroadcastreceiver;
import static android.telephony.ServiceState.ROAMING_TYPE_NOT_ROAMING;
+import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.VDBG;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Resources;
import android.os.SystemProperties;
import android.telephony.AccessNetworkConstants;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.SmsCbMessage;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.Log;
+import android.util.Pair;
import androidx.annotation.VisibleForTesting;
@@ -35,6 +42,7 @@ import com.android.cellbroadcastreceiver.CellBroadcastAlertService.AlertType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Map;
/**
* CellBroadcastChannelManager handles the additional cell broadcast channels that
@@ -54,6 +62,7 @@ public class CellBroadcastChannelManager {
private static final String TAG = "CBChannelManager";
+ private static final int MAX_CACHE_SIZE = 3;
private static List<Integer> sCellBroadcastRangeResourceKeys = new ArrayList<>(
Arrays.asList(R.array.additional_cbs_channels_strings,
R.array.emergency_alerts_channels_range_strings,
@@ -67,16 +76,23 @@ public class CellBroadcastChannelManager {
R.array.etws_alerts_range_strings,
R.array.etws_test_alerts_range_strings,
R.array.public_safety_messages_channels_range_strings,
- R.array.state_local_test_alert_range_strings
+ R.array.state_local_test_alert_range_strings,
+ R.array.geo_fencing_trigger_messages_range_strings
));
- private static ArrayList<CellBroadcastChannelRange> sAllCellBroadcastChannelRanges = null;
- private static final Object channelRangesLock = new Object();
+ private static Map<Integer, Map<Integer, List<CellBroadcastChannelRange>>>
+ sAllCellBroadcastChannelRangesPerSub = new ArrayMap<>();
+ private static Map<String, Map<Integer, List<CellBroadcastChannelRange>>>
+ sAllCellBroadcastChannelRangesPerOperator = new ArrayMap<>();
+
+ private static final Object mChannelRangesLock = new Object();
private final Context mContext;
private final int mSubId;
+ private final String mOperator;
+
private boolean mIsDebugBuild = false;
/**
@@ -167,14 +183,14 @@ public class CellBroadcastChannelManager {
// Display both ways dialog and notification
public boolean mDisplayDialogWithNotification = false;
- public CellBroadcastChannelRange(Context context, int subId, String channelRange) {
+ public CellBroadcastChannelRange(Context context, int subId,
+ Resources res, String channelRange) {
mAlertType = AlertType.DEFAULT;
mEmergencyLevel = LEVEL_UNKNOWN;
mRanType = SmsCbMessage.MESSAGE_FORMAT_3GPP;
mScope = SCOPE_UNKNOWN;
- mVibrationPattern =
- CellBroadcastSettings.getResources(context, subId)
- .getIntArray(R.array.default_vibration_pattern);
+
+ mVibrationPattern = res.getIntArray(R.array.default_vibration_pattern);
mFilterLanguage = false;
// by default all received messages should be displayed.
mDisplay = true;
@@ -293,8 +309,7 @@ public class CellBroadcastChannelManager {
// If alert type is info, override vibration pattern
if (!hasVibrationPattern && mAlertType.equals(AlertType.INFO)) {
- mVibrationPattern = CellBroadcastSettings.getResources(context, subId)
- .getIntArray(R.array.default_notification_vibration_pattern);
+ mVibrationPattern = res.getIntArray(R.array.default_notification_vibration_pattern);
}
// Parse the channel range
@@ -331,14 +346,88 @@ public class CellBroadcastChannelManager {
* @param subId Subscription index
*/
public CellBroadcastChannelManager(Context context, int subId) {
- this(context, subId, SystemProperties.getInt("ro.debuggable", 0) == 1);
+ this(context, subId, CellBroadcastReceiver.getRoamingOperatorSupported(context),
+ SystemProperties.getInt("ro.debuggable", 0) == 1);
+ }
+
+ public CellBroadcastChannelManager(Context context, int subId, @Nullable String operator) {
+ this(context, subId, operator, SystemProperties.getInt("ro.debuggable", 0) == 1);
}
@VisibleForTesting
- public CellBroadcastChannelManager(Context context, int subId, boolean isDebugBuild) {
+ public CellBroadcastChannelManager(Context context, int subId,
+ String operator, boolean isDebugBuild) {
mContext = context;
mSubId = subId;
+ mOperator = operator;
mIsDebugBuild = isDebugBuild;
+ initAsNeeded();
+ }
+
+ /**
+ * Parse channel ranges from resources, and initialize the cache as needed
+ */
+ private void initAsNeeded() {
+ if (!TextUtils.isEmpty(mOperator)) {
+ synchronized (mChannelRangesLock) {
+ if (!sAllCellBroadcastChannelRangesPerOperator.containsKey(mOperator)) {
+ if (VDBG) {
+ log("init for operator: " + mOperator);
+ }
+ if (sAllCellBroadcastChannelRangesPerOperator.size() == MAX_CACHE_SIZE) {
+ sAllCellBroadcastChannelRangesPerOperator.clear();
+ }
+ sAllCellBroadcastChannelRangesPerOperator.put(mOperator,
+ getChannelRangesMapFromResoures(CellBroadcastSettings
+ .getResourcesByOperator(mContext, mSubId, mOperator)));
+ }
+ }
+ }
+
+ synchronized (mChannelRangesLock) {
+ if (!sAllCellBroadcastChannelRangesPerSub.containsKey(mSubId)) {
+ if (sAllCellBroadcastChannelRangesPerSub.size() == MAX_CACHE_SIZE) {
+ sAllCellBroadcastChannelRangesPerSub.clear();
+ }
+ if (VDBG) {
+ log("init for sub: " + mSubId);
+ }
+ sAllCellBroadcastChannelRangesPerSub.put(mSubId,
+ getChannelRangesMapFromResoures(CellBroadcastSettings
+ .getResources(mContext, mSubId)));
+ }
+ }
+ }
+
+ private @NonNull Map<Integer, List<CellBroadcastChannelRange>> getChannelRangesMapFromResoures(
+ @NonNull Resources res) {
+ Map<Integer, List<CellBroadcastChannelRange>> map = new ArrayMap<>();
+
+ for (int key : sCellBroadcastRangeResourceKeys) {
+ String[] ranges = res.getStringArray(key);
+ if (ranges != null) {
+ List<CellBroadcastChannelRange> rangesList = new ArrayList<>();
+ for (String range : ranges) {
+ try {
+ if (VDBG) {
+ log("parse channel range: " + range);
+ }
+ CellBroadcastChannelRange r =
+ new CellBroadcastChannelRange(mContext, mSubId, res, range);
+ // Bypass if the range is disabled
+ if (r.mIsDebugBuildOnly && !mIsDebugBuild) {
+ continue;
+ }
+ rangesList.add(r);
+ } catch (Exception e) {
+ loge("Failed to parse \"" + range + "\". e=" + e);
+ }
+ }
+ map.put(key, rangesList);
+ }
+ }
+
+ return map;
}
/**
@@ -348,26 +437,23 @@ public class CellBroadcastChannelManager {
*
* @return The list of channel ranges enabled by the carriers.
*/
- public @NonNull ArrayList<CellBroadcastChannelRange> getCellBroadcastChannelRanges(int key) {
- ArrayList<CellBroadcastChannelRange> result = new ArrayList<>();
- String[] ranges =
- CellBroadcastSettings.getResources(mContext, mSubId).getStringArray(key);
- if (ranges != null) {
- for (String range : ranges) {
- try {
- CellBroadcastChannelRange r =
- new CellBroadcastChannelRange(mContext, mSubId, range);
- // Bypass if the range is disabled
- if (r.mIsDebugBuildOnly && !mIsDebugBuild) {
- continue;
- }
- result.add(r);
- } catch (Exception e) {
- loge("Failed to parse \"" + range + "\". e=" + e);
- }
+ public @NonNull List<CellBroadcastChannelRange> getCellBroadcastChannelRanges(int key) {
+ List<CellBroadcastChannelRange> result = null;
+
+ synchronized (mChannelRangesLock) {
+ initAsNeeded();
+
+ // Check the config per network first if applicable
+ if (!TextUtils.isEmpty(mOperator)) {
+ result = sAllCellBroadcastChannelRangesPerOperator.get(mOperator).get(key);
+ }
+
+ if (result == null) {
+ result = sAllCellBroadcastChannelRangesPerSub.get(mSubId).get(key);
}
}
- return result;
+
+ return result == null ? new ArrayList<>() : result;
}
/**
@@ -375,31 +461,28 @@ public class CellBroadcastChannelManager {
*
* @return all cell broadcast channels
*/
- public @NonNull ArrayList<CellBroadcastChannelRange> getAllCellBroadcastChannelRanges() {
- synchronized(channelRangesLock) {
- if (sAllCellBroadcastChannelRanges != null) return sAllCellBroadcastChannelRanges;
-
- Log.d(TAG, "Create new channel range list");
- ArrayList<CellBroadcastChannelRange> result = new ArrayList<>();
-
- for (int key : sCellBroadcastRangeResourceKeys) {
- result.addAll(getCellBroadcastChannelRanges(key));
+ public @NonNull List<CellBroadcastChannelRange> getAllCellBroadcastChannelRanges() {
+ final List<CellBroadcastChannelRange> result = new ArrayList<>();
+ synchronized (mChannelRangesLock) {
+ if (!TextUtils.isEmpty(mOperator)
+ && sAllCellBroadcastChannelRangesPerOperator.containsKey(mOperator)) {
+ sAllCellBroadcastChannelRangesPerOperator.get(mOperator).forEach(
+ (k, v)->result.addAll(v));
}
- sAllCellBroadcastChannelRanges = result;
- return result;
+ sAllCellBroadcastChannelRangesPerSub.get(mSubId).forEach((k, v)->result.addAll(v));
}
+ return result;
}
/**
* Clear broadcast channel range list
*/
public static void clearAllCellBroadcastChannelRanges() {
- synchronized(channelRangesLock) {
- if (sAllCellBroadcastChannelRanges != null) {
- Log.d(TAG, "Clear channel range list");
- sAllCellBroadcastChannelRanges = null;
- }
+ synchronized (mChannelRangesLock) {
+ Log.d(TAG, "Clear channel range list");
+ sAllCellBroadcastChannelRangesPerSub.clear();
+ sAllCellBroadcastChannelRangesPerOperator.clear();
}
}
@@ -411,15 +494,59 @@ public class CellBroadcastChannelManager {
* return {@code FALSE} otherwise
*/
public boolean checkCellBroadcastChannelRange(int channel, int key) {
- ArrayList<CellBroadcastChannelRange> ranges = getCellBroadcastChannelRanges(key);
+ return getCellBroadcastChannelResourcesKey(channel) == key;
+ }
+
+ /**
+ * Get the resources key for the channel
+ * @param channel Cell broadcast message channel
+ *
+ * @return 0 if the key is not found, otherwise the value of the resources key
+ */
+ public int getCellBroadcastChannelResourcesKey(int channel) {
+ Pair<Integer, CellBroadcastChannelRange> p = findChannelRange(channel);
+
+ return p != null ? p.first : 0;
+ }
+
+ /**
+ * Get the CellBroadcastChannelRange for the channel
+ * @param channel Cell broadcast message channel
+ *
+ * @return the CellBroadcastChannelRange for the channel, null if not found
+ */
+ public @Nullable CellBroadcastChannelRange getCellBroadcastChannelRange(int channel) {
+ Pair<Integer, CellBroadcastChannelRange> p = findChannelRange(channel);
+
+ return p != null ? p.second : null;
+ }
- for (CellBroadcastChannelRange range : ranges) {
- if (channel >= range.mStartId && channel <= range.mEndId) {
- return checkScope(range.mScope);
+ private @Nullable Pair<Integer, CellBroadcastChannelRange> findChannelRange(int channel) {
+ if (!TextUtils.isEmpty(mOperator)) {
+ Pair<Integer, CellBroadcastChannelRange> p = findChannelRange(
+ sAllCellBroadcastChannelRangesPerOperator.get(mOperator), channel);
+ if (p != null) {
+ return p;
}
}
- return false;
+ return findChannelRange(sAllCellBroadcastChannelRangesPerSub.get(mSubId), channel);
+ }
+
+ private @Nullable Pair<Integer, CellBroadcastChannelRange> findChannelRange(
+ Map<Integer, List<CellBroadcastChannelRange>> channelRangeMap, int channel) {
+ if (channelRangeMap != null) {
+ for (Map.Entry<Integer, List<CellBroadcastChannelRange>> entry
+ : channelRangeMap.entrySet()) {
+ for (CellBroadcastChannelRange range : entry.getValue()) {
+ if (channel >= range.mStartId && channel <= range.mEndId
+ && checkScope(range.mScope)) {
+ return new Pair<>(entry.getKey(), range);
+ }
+ }
+ }
+ }
+ return null;
}
/**
@@ -474,24 +601,7 @@ public class CellBroadcastChannelManager {
+ message.getSubscriptionId());
}
- int channel = message.getServiceCategory();
- ArrayList<CellBroadcastChannelRange> ranges = null;
-
- for (int key : sCellBroadcastRangeResourceKeys) {
- if (checkCellBroadcastChannelRange(channel, key)) {
- ranges = getCellBroadcastChannelRanges(key);
- break;
- }
- }
- if (ranges != null) {
- for (CellBroadcastChannelRange range : ranges) {
- if (range.mStartId <= message.getServiceCategory()
- && range.mEndId >= message.getServiceCategory()) {
- return range;
- }
- }
- }
- return null;
+ return getCellBroadcastChannelRange(message.getServiceCategory());
}
/**
@@ -511,25 +621,19 @@ public class CellBroadcastChannelManager {
}
int id = message.getServiceCategory();
-
- for (int key : sCellBroadcastRangeResourceKeys) {
- ArrayList<CellBroadcastChannelRange> ranges =
- getCellBroadcastChannelRanges(key);
- for (CellBroadcastChannelRange range : ranges) {
- if (range.mStartId <= id && range.mEndId >= id) {
- switch (range.mEmergencyLevel) {
- case CellBroadcastChannelRange.LEVEL_EMERGENCY:
- Log.d(TAG, "isEmergencyMessage: true, message id = " + id);
- return true;
- case CellBroadcastChannelRange.LEVEL_NOT_EMERGENCY:
- Log.d(TAG, "isEmergencyMessage: false, message id = " + id);
- return false;
- case CellBroadcastChannelRange.LEVEL_UNKNOWN:
- default:
- break;
- }
+ CellBroadcastChannelRange range = getCellBroadcastChannelRange(id);
+
+ if (range != null) {
+ switch (range.mEmergencyLevel) {
+ case CellBroadcastChannelRange.LEVEL_EMERGENCY:
+ Log.d(TAG, "isEmergencyMessage: true, message id = " + id);
+ return true;
+ case CellBroadcastChannelRange.LEVEL_NOT_EMERGENCY:
+ Log.d(TAG, "isEmergencyMessage: false, message id = " + id);
+ return false;
+ case CellBroadcastChannelRange.LEVEL_UNKNOWN:
+ default:
break;
- }
}
}
@@ -541,6 +645,10 @@ public class CellBroadcastChannelManager {
return message.isEmergencyMessage();
}
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+
private static void loge(String msg) {
Log.e(TAG, msg);
}