| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.cellbroadcastservice; |
| |
| import static android.content.Context.MODE_PRIVATE; |
| import static android.telephony.SmsCbMessage.MESSAGE_FORMAT_3GPP; |
| |
| import static com.android.cellbroadcastservice.CellBroadcastMetrics.FILTER_CDMA; |
| import static com.android.cellbroadcastservice.CellBroadcastMetrics.FILTER_GSM; |
| |
| import android.content.Context; |
| import android.content.SharedPreferences; |
| import android.telephony.SmsCbMessage; |
| import android.util.Log; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Objects; |
| |
| /** |
| * CellBroadcastServiceMetrics |
| * Logging featureUpdated, when alert message is received or channel range is updated |
| */ |
| public class CellBroadcastServiceMetrics { |
| |
| private static final String TAG = "CellBroadcastServiceMetrics"; |
| private static final boolean VDBG = false; |
| // Key to access the shared preference of cell broadcast service feature for metric. |
| private static final String CBS_METRIC_PREF = "CellBroadcastServiceMetricSharedPref"; |
| |
| private static CellBroadcastServiceMetrics sCbsMetrics; |
| |
| private FeatureMetrics mFeatureMetrics; |
| private FeatureMetrics mFeatureMetricsSharedPreferences; |
| |
| |
| /** |
| * Get instance of CellBroadcastServiceMetrics. |
| */ |
| public static CellBroadcastServiceMetrics getInstance() { |
| if (sCbsMetrics == null) { |
| sCbsMetrics = new CellBroadcastServiceMetrics(); |
| } |
| return sCbsMetrics; |
| } |
| |
| /** |
| * CellBroadcastReceiverMetrics.FeatureMetrics |
| * Logging featureUpdated as needed when alert message is received |
| */ |
| public static class FeatureMetrics implements Cloneable { |
| public static final String ADDITIONAL_CBR_PACKAGES = "additional_cbr_packages"; |
| public static final String AREA_INFO_PACKAGES = "area_info_packages"; |
| public static final String RESET_AREA_INFO = "reset_area_info"; |
| public static final String DEFVAL_AREAPKGS = "com.android.settings"; |
| |
| private boolean mIsOverrideCbrPkgs; |
| private boolean mIsOverrideAreaInfoPkgs; |
| private boolean mResetAreaInfo; |
| |
| private Context mContext; |
| |
| public FeatureMetrics(Context context) { |
| mContext = context; |
| SharedPreferences sp = mContext.getSharedPreferences(CBS_METRIC_PREF, MODE_PRIVATE); |
| |
| mIsOverrideCbrPkgs = sp.getBoolean(ADDITIONAL_CBR_PACKAGES, false); |
| mIsOverrideAreaInfoPkgs = sp.getBoolean(AREA_INFO_PACKAGES, false); |
| mResetAreaInfo = sp.getBoolean(RESET_AREA_INFO, false); |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hash(mIsOverrideCbrPkgs, mIsOverrideAreaInfoPkgs, mResetAreaInfo); |
| } |
| |
| @Override |
| public boolean equals(Object object) { |
| if (object instanceof FeatureMetrics) { |
| FeatureMetrics features = (FeatureMetrics) object; |
| return (this.mIsOverrideCbrPkgs == features.mIsOverrideCbrPkgs |
| && this.mIsOverrideAreaInfoPkgs == features.mIsOverrideAreaInfoPkgs |
| && this.mResetAreaInfo == features.mResetAreaInfo); |
| } |
| return false; |
| } |
| |
| @Override |
| public Object clone() throws CloneNotSupportedException { |
| return super.clone(); |
| } |
| |
| /** |
| * Get current status whether cell broadcast receiver packages are overridden |
| */ |
| @VisibleForTesting |
| public boolean isOverrideCbrPkgs() { |
| return mIsOverrideCbrPkgs; |
| } |
| |
| /** |
| * Get current status whether area information packages are overridden |
| */ |
| @VisibleForTesting |
| public boolean isOverrideAreaInfoPkgs() { |
| return mIsOverrideAreaInfoPkgs; |
| } |
| |
| /** |
| * Get current status whether reset area information while in out of service |
| */ |
| @VisibleForTesting |
| public boolean isResetAreaInfo() { |
| return mResetAreaInfo; |
| } |
| |
| /** |
| * Set whether additional cbr packages are overridden |
| * |
| * @param override : whether additional cbr packages are overridden |
| */ |
| @VisibleForTesting |
| public void onChangedAdditionalCbrPackage(boolean override) { |
| mIsOverrideCbrPkgs = override; |
| } |
| |
| /** |
| * Set whether area info packages are overridden |
| * |
| * @param current : list of area info overriding packages |
| */ |
| @VisibleForTesting |
| public void onChangedAreaInfoPackage(List<String> current) { |
| mIsOverrideAreaInfoPkgs = !Arrays.asList(new String[]{DEFVAL_AREAPKGS}).equals(current); |
| } |
| |
| /** |
| * Set whether area info reset on our of service |
| * |
| * @param current : whether reset area info is supported |
| */ |
| @VisibleForTesting |
| public void onChangedResetAreaInfo(boolean current) { |
| mResetAreaInfo = current; |
| } |
| |
| /** |
| * Calling check-in method for CB_SERVICE_FEATURE |
| */ |
| @VisibleForTesting |
| public void logFeatureChanged() { |
| CellBroadcastModuleStatsLog.write( |
| CellBroadcastModuleStatsLog.CB_SERVICE_FEATURE_CHANGED, |
| mIsOverrideCbrPkgs, |
| mIsOverrideAreaInfoPkgs, |
| mResetAreaInfo); |
| if (VDBG) Log.d(TAG, this.toString()); |
| } |
| |
| /** |
| * Update preferences for service feature metrics |
| */ |
| @VisibleForTesting |
| public void updateSharedPreferences() { |
| SharedPreferences sp = mContext.getSharedPreferences(CBS_METRIC_PREF, MODE_PRIVATE); |
| SharedPreferences.Editor editor = sp.edit(); |
| editor.putBoolean(ADDITIONAL_CBR_PACKAGES, mIsOverrideCbrPkgs); |
| editor.putBoolean(AREA_INFO_PACKAGES, mIsOverrideAreaInfoPkgs); |
| editor.putBoolean(RESET_AREA_INFO, mResetAreaInfo); |
| editor.apply(); |
| } |
| |
| @Override |
| public String toString() { |
| return "CellBroadcast_Service_Feature : " |
| + "mIsOverrideCbrPkgs = " + mIsOverrideCbrPkgs + " | " |
| + "mIsOverrideAreaInfoPkgs = " + mIsOverrideAreaInfoPkgs + " | " |
| + "mResetAreaInfo = " + mResetAreaInfo; |
| } |
| } |
| |
| /** |
| * get cached feature metrics for shared preferences |
| */ |
| @VisibleForTesting |
| public FeatureMetrics getFeatureMetricsSharedPreferences() { |
| return mFeatureMetricsSharedPreferences; |
| } |
| |
| /** |
| * set cached feature metrics for current status |
| */ |
| @VisibleForTesting |
| public void setFeatureMetrics(FeatureMetrics featureMetrics) { |
| mFeatureMetrics = featureMetrics; |
| } |
| |
| /** |
| * Set featureMetricsSharedPreferences |
| * |
| * @param featureMetricsSharedPreferences : Cbs features information |
| */ |
| @VisibleForTesting |
| public void setFeatureMetricsSharedPreferences(FeatureMetrics featureMetricsSharedPreferences) { |
| mFeatureMetricsSharedPreferences = featureMetricsSharedPreferences; |
| } |
| |
| /** |
| * Get featureMetrics if null then create |
| */ |
| @VisibleForTesting |
| public FeatureMetrics getFeatureMetrics(Context context) { |
| if (mFeatureMetrics == null) { |
| mFeatureMetrics = new FeatureMetrics(context); |
| mFeatureMetricsSharedPreferences = new FeatureMetrics(context); |
| } |
| return mFeatureMetrics; |
| } |
| |
| /** |
| * When feature changed and net alert message received then check-in logging |
| * |
| * @param context : Context |
| */ |
| @VisibleForTesting |
| public void logFeatureChangedAsNeeded(Context context) { |
| if (!getFeatureMetrics(context).equals(mFeatureMetricsSharedPreferences)) { |
| mFeatureMetrics.logFeatureChanged(); |
| mFeatureMetrics.updateSharedPreferences(); |
| try { |
| mFeatureMetricsSharedPreferences = (FeatureMetrics) mFeatureMetrics.clone(); |
| } catch (CloneNotSupportedException e) { |
| Log.e(TAG, "exception during making clone for service feature metrics: " + e); |
| } |
| } |
| } |
| |
| /** |
| * Create a new logMessageReported |
| * |
| * @param type : radio type |
| * @param source : layer of reported message |
| * @param serialNo : set 0 as deprecated |
| * @param msgId : service_category of message |
| */ |
| public void logMessageReported(Context context, int type, int source, int serialNo, int msgId) { |
| if (VDBG) { |
| Log.d(TAG, "logMessageReported : " + type + " " + source + " " + 0 + " " + msgId); |
| } |
| CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MESSAGE_REPORTED, type, |
| source, 0, msgId); |
| } |
| |
| /** |
| * Create a new logMessageError |
| * |
| * @param type : error type |
| * @param exceptionMessage : error message |
| */ |
| public void logMessageError(int type, String exceptionMessage) { |
| if (VDBG) { |
| Log.d(TAG, "logMessageError : " + type + " " + exceptionMessage); |
| } |
| CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MESSAGE_ERROR, |
| type, exceptionMessage); |
| } |
| |
| /** |
| * Create a new logMessageFiltered |
| * |
| * @param filterType : reason type of filtered |
| * @param msg : sms cell broadcast message information |
| */ |
| public void logMessageFiltered(int filterType, SmsCbMessage msg) { |
| int ratType = msg.getMessageFormat() == MESSAGE_FORMAT_3GPP ? FILTER_GSM : FILTER_CDMA; |
| if (VDBG) { |
| Log.d(TAG, "logMessageFiltered : " + ratType + " " + filterType + " " + 0 + " " |
| + msg.getServiceCategory()); |
| } |
| CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MESSAGE_FILTERED, |
| ratType, filterType, 0, msg.getServiceCategory()); |
| } |
| |
| /** |
| * Create a new logModuleError |
| * |
| * @param source : where this log happened |
| * @param errorType : type of error |
| */ |
| public void logModuleError(int source, int errorType) { |
| if (VDBG) { |
| Log.d(TAG, "logModuleError : " + source + " " + errorType); |
| } |
| CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MODULE_ERROR_REPORTED, |
| source, errorType); |
| } |
| } |