1 /* 2 * Copyright (C) 2022 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.cellbroadcastservice; 18 19 import static android.content.Context.MODE_PRIVATE; 20 import static android.telephony.SmsCbMessage.MESSAGE_FORMAT_3GPP; 21 22 import static com.android.cellbroadcastservice.CellBroadcastMetrics.FILTER_CDMA; 23 import static com.android.cellbroadcastservice.CellBroadcastMetrics.FILTER_GSM; 24 25 import android.content.Context; 26 import android.content.SharedPreferences; 27 import android.telephony.SmsCbMessage; 28 import android.util.Log; 29 30 import com.android.internal.annotations.VisibleForTesting; 31 32 import java.util.Arrays; 33 import java.util.List; 34 import java.util.Objects; 35 36 /** 37 * CellBroadcastServiceMetrics 38 * Logging featureUpdated, when alert message is received or channel range is updated 39 */ 40 public class CellBroadcastServiceMetrics { 41 42 private static final String TAG = "CellBroadcastServiceMetrics"; 43 private static final boolean VDBG = false; 44 // Key to access the shared preference of cell broadcast service feature for metric. 45 private static final String CBS_METRIC_PREF = "CellBroadcastServiceMetricSharedPref"; 46 47 private static CellBroadcastServiceMetrics sCbsMetrics; 48 49 private FeatureMetrics mFeatureMetrics; 50 private FeatureMetrics mFeatureMetricsSharedPreferences; 51 52 53 /** 54 * Get instance of CellBroadcastServiceMetrics. 55 */ getInstance()56 public static CellBroadcastServiceMetrics getInstance() { 57 if (sCbsMetrics == null) { 58 sCbsMetrics = new CellBroadcastServiceMetrics(); 59 } 60 return sCbsMetrics; 61 } 62 63 /** 64 * CellBroadcastReceiverMetrics.FeatureMetrics 65 * Logging featureUpdated as needed when alert message is received 66 */ 67 public static class FeatureMetrics implements Cloneable { 68 public static final String ADDITIONAL_CBR_PACKAGES = "additional_cbr_packages"; 69 public static final String AREA_INFO_PACKAGES = "area_info_packages"; 70 public static final String RESET_AREA_INFO = "reset_area_info"; 71 public static final String DEFVAL_AREAPKGS = "com.android.settings"; 72 73 private boolean mIsOverrideCbrPkgs; 74 private boolean mIsOverrideAreaInfoPkgs; 75 private boolean mResetAreaInfo; 76 77 private Context mContext; 78 FeatureMetrics(Context context)79 public FeatureMetrics(Context context) { 80 mContext = context; 81 SharedPreferences sp = mContext.getSharedPreferences(CBS_METRIC_PREF, MODE_PRIVATE); 82 83 mIsOverrideCbrPkgs = sp.getBoolean(ADDITIONAL_CBR_PACKAGES, false); 84 mIsOverrideAreaInfoPkgs = sp.getBoolean(AREA_INFO_PACKAGES, false); 85 mResetAreaInfo = sp.getBoolean(RESET_AREA_INFO, false); 86 } 87 88 @Override hashCode()89 public int hashCode() { 90 return Objects.hash(mIsOverrideCbrPkgs, mIsOverrideAreaInfoPkgs, mResetAreaInfo); 91 } 92 93 @Override equals(Object object)94 public boolean equals(Object object) { 95 if (object instanceof FeatureMetrics) { 96 FeatureMetrics features = (FeatureMetrics) object; 97 return (this.mIsOverrideCbrPkgs == features.mIsOverrideCbrPkgs 98 && this.mIsOverrideAreaInfoPkgs == features.mIsOverrideAreaInfoPkgs 99 && this.mResetAreaInfo == features.mResetAreaInfo); 100 } 101 return false; 102 } 103 104 @Override clone()105 public Object clone() throws CloneNotSupportedException { 106 return super.clone(); 107 } 108 109 /** 110 * Get current status whether cell broadcast receiver packages are overridden 111 */ 112 @VisibleForTesting isOverrideCbrPkgs()113 public boolean isOverrideCbrPkgs() { 114 return mIsOverrideCbrPkgs; 115 } 116 117 /** 118 * Get current status whether area information packages are overridden 119 */ 120 @VisibleForTesting isOverrideAreaInfoPkgs()121 public boolean isOverrideAreaInfoPkgs() { 122 return mIsOverrideAreaInfoPkgs; 123 } 124 125 /** 126 * Get current status whether reset area information while in out of service 127 */ 128 @VisibleForTesting isResetAreaInfo()129 public boolean isResetAreaInfo() { 130 return mResetAreaInfo; 131 } 132 133 /** 134 * Set whether additional cbr packages are overridden 135 * 136 * @param override : whether additional cbr packages are overridden 137 */ 138 @VisibleForTesting onChangedAdditionalCbrPackage(boolean override)139 public void onChangedAdditionalCbrPackage(boolean override) { 140 mIsOverrideCbrPkgs = override; 141 } 142 143 /** 144 * Set whether area info packages are overridden 145 * 146 * @param current : list of area info overriding packages 147 */ 148 @VisibleForTesting onChangedAreaInfoPackage(List<String> current)149 public void onChangedAreaInfoPackage(List<String> current) { 150 mIsOverrideAreaInfoPkgs = !Arrays.asList(new String[]{DEFVAL_AREAPKGS}).equals(current); 151 } 152 153 /** 154 * Set whether area info reset on our of service 155 * 156 * @param current : whether reset area info is supported 157 */ 158 @VisibleForTesting onChangedResetAreaInfo(boolean current)159 public void onChangedResetAreaInfo(boolean current) { 160 mResetAreaInfo = current; 161 } 162 163 /** 164 * Calling check-in method for CB_SERVICE_FEATURE 165 */ 166 @VisibleForTesting logFeatureChanged()167 public void logFeatureChanged() { 168 CellBroadcastModuleStatsLog.write( 169 CellBroadcastModuleStatsLog.CB_SERVICE_FEATURE_CHANGED, 170 mIsOverrideCbrPkgs, 171 mIsOverrideAreaInfoPkgs, 172 mResetAreaInfo); 173 if (VDBG) Log.d(TAG, this.toString()); 174 } 175 176 /** 177 * Update preferences for service feature metrics 178 */ 179 @VisibleForTesting updateSharedPreferences()180 public void updateSharedPreferences() { 181 SharedPreferences sp = mContext.getSharedPreferences(CBS_METRIC_PREF, MODE_PRIVATE); 182 SharedPreferences.Editor editor = sp.edit(); 183 editor.putBoolean(ADDITIONAL_CBR_PACKAGES, mIsOverrideCbrPkgs); 184 editor.putBoolean(AREA_INFO_PACKAGES, mIsOverrideAreaInfoPkgs); 185 editor.putBoolean(RESET_AREA_INFO, mResetAreaInfo); 186 editor.apply(); 187 } 188 189 @Override toString()190 public String toString() { 191 return "CellBroadcast_Service_Feature : " 192 + "mIsOverrideCbrPkgs = " + mIsOverrideCbrPkgs + " | " 193 + "mIsOverrideAreaInfoPkgs = " + mIsOverrideAreaInfoPkgs + " | " 194 + "mResetAreaInfo = " + mResetAreaInfo; 195 } 196 } 197 198 /** 199 * get cached feature metrics for shared preferences 200 */ 201 @VisibleForTesting getFeatureMetricsSharedPreferences()202 public FeatureMetrics getFeatureMetricsSharedPreferences() { 203 return mFeatureMetricsSharedPreferences; 204 } 205 206 /** 207 * set cached feature metrics for current status 208 */ 209 @VisibleForTesting setFeatureMetrics(FeatureMetrics featureMetrics)210 public void setFeatureMetrics(FeatureMetrics featureMetrics) { 211 mFeatureMetrics = featureMetrics; 212 } 213 214 /** 215 * Set featureMetricsSharedPreferences 216 * 217 * @param featureMetricsSharedPreferences : Cbs features information 218 */ 219 @VisibleForTesting setFeatureMetricsSharedPreferences(FeatureMetrics featureMetricsSharedPreferences)220 public void setFeatureMetricsSharedPreferences(FeatureMetrics featureMetricsSharedPreferences) { 221 mFeatureMetricsSharedPreferences = featureMetricsSharedPreferences; 222 } 223 224 /** 225 * Get featureMetrics if null then create 226 */ 227 @VisibleForTesting getFeatureMetrics(Context context)228 public FeatureMetrics getFeatureMetrics(Context context) { 229 if (mFeatureMetrics == null) { 230 mFeatureMetrics = new FeatureMetrics(context); 231 mFeatureMetricsSharedPreferences = new FeatureMetrics(context); 232 } 233 return mFeatureMetrics; 234 } 235 236 /** 237 * When feature changed and net alert message received then check-in logging 238 * 239 * @param context : Context 240 */ 241 @VisibleForTesting logFeatureChangedAsNeeded(Context context)242 public void logFeatureChangedAsNeeded(Context context) { 243 if (!getFeatureMetrics(context).equals(mFeatureMetricsSharedPreferences)) { 244 mFeatureMetrics.logFeatureChanged(); 245 mFeatureMetrics.updateSharedPreferences(); 246 try { 247 mFeatureMetricsSharedPreferences = (FeatureMetrics) mFeatureMetrics.clone(); 248 } catch (CloneNotSupportedException e) { 249 Log.e(TAG, "exception during making clone for service feature metrics: " + e); 250 } 251 } 252 } 253 254 /** 255 * Create a new logMessageReported 256 * 257 * @param type : radio type 258 * @param source : layer of reported message 259 * @param serialNo : unique identifier of message 260 * @param msgId : service_category of message 261 */ logMessageReported(Context context, int type, int source, int serialNo, int msgId)262 public void logMessageReported(Context context, int type, int source, int serialNo, int msgId) { 263 if (VDBG) { 264 Log.d(TAG, 265 "logMessageReported : " + type + " " + source + " " + serialNo + " " + msgId); 266 } 267 CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MESSAGE_REPORTED, type, 268 source, serialNo, msgId); 269 } 270 271 /** 272 * Create a new logMessageError 273 * 274 * @param type : error type 275 * @param exceptionMessage : error message 276 */ logMessageError(int type, String exceptionMessage)277 public void logMessageError(int type, String exceptionMessage) { 278 if (VDBG) { 279 Log.d(TAG, "logMessageError : " + type + " " + exceptionMessage); 280 } 281 CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MESSAGE_ERROR, 282 type, exceptionMessage); 283 } 284 285 /** 286 * Create a new logMessageFiltered 287 * 288 * @param filterType : reason type of filtered 289 * @param msg : sms cell broadcast message information 290 */ logMessageFiltered(int filterType, SmsCbMessage msg)291 public void logMessageFiltered(int filterType, SmsCbMessage msg) { 292 int ratType = msg.getMessageFormat() == MESSAGE_FORMAT_3GPP ? FILTER_GSM : FILTER_CDMA; 293 if (VDBG) { 294 Log.d(TAG, "logMessageFiltered : " + ratType + " " + filterType + " " 295 + msg.getSerialNumber() + " " + msg.getServiceCategory()); 296 } 297 CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MESSAGE_FILTERED, 298 ratType, filterType, msg.getSerialNumber(), msg.getServiceCategory()); 299 } 300 301 /** 302 * Create a new logModuleError 303 * 304 * @param source : where this log happened 305 * @param errorType : type of error 306 */ logModuleError(int source, int errorType)307 public void logModuleError(int source, int errorType) { 308 if (VDBG) { 309 Log.d(TAG, "logModuleError : " + source + " " + errorType); 310 } 311 CellBroadcastModuleStatsLog.write(CellBroadcastModuleStatsLog.CB_MODULE_ERROR_REPORTED, 312 source, errorType); 313 } 314 } 315