diff options
Diffstat (limited to 'src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java')
-rw-r--r-- | src/com/android/cellbroadcastreceiver/CellBroadcastChannelManager.java | 280 |
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); } |