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.ons; 18 19 import android.content.Context; 20 import android.content.SharedPreferences; 21 import android.telephony.SubscriptionInfo; 22 import android.telephony.SubscriptionManager; 23 24 import com.android.ons.ONSProfileActivator.Result; 25 import com.android.ons.ONSProfileDownloader.DownloadRetryResultCode; 26 27 import java.util.List; 28 29 public class ONSStats { 30 private static final String ONS_ATOM_LOG_FILE = "ons_atom_log_info"; 31 private static final String KEY_PROVISIONING_RESULT = "_provisioning_result"; 32 private static final String KEY_DOWNLOAD_RESULT = "_download_result"; 33 private static final String KEY_RETRY_COUNT = "_retry_count"; 34 private static final String KEY_DETAILED_ERROR_CODE = "_detailed_error_code"; 35 private static final String KEY_OPP_CARRIER_ID = "_opportunistic_carrier_id"; 36 private static final String KEY_PRIMARY_CARRIER_ID = "_primary_sim_carrier_id"; 37 private final Context mContext; 38 private final SubscriptionManager mSubscriptionManager; 39 40 /** Constructor to create instance for ONSStats. */ ONSStats(Context context, SubscriptionManager subscriptionManager)41 public ONSStats(Context context, SubscriptionManager subscriptionManager) { 42 mContext = context; 43 mSubscriptionManager = subscriptionManager; 44 } 45 46 /** 47 * It logs the ONS atom with the info passed as ONSStatsInfo. If the information is already 48 * logged, it will be skipped. 49 * 50 * @param info information to be logged. 51 * @return returns true if information is logged, otherwise false. 52 */ logEvent(ONSStatsInfo info)53 public boolean logEvent(ONSStatsInfo info) { 54 // check if the info needs to be ignored. 55 if (ignoreEvent(info)) { 56 return false; 57 } 58 int statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_UNKNOWN; 59 if (info.isProvisioningResultUpdated()) { 60 switch (info.getProvisioningResult()) { 61 case SUCCESS: 62 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_SUCCESS; 63 break; 64 case ERR_CANNOT_SWITCH_TO_DUAL_SIM_MODE: 65 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_SWITCH_TO_MULTISIM_FAILED; 66 break; 67 case ERR_CARRIER_DOESNT_SUPPORT_CBRS: 68 case ERR_AUTO_PROVISIONING_DISABLED: 69 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_AUTO_PROVISIONING_DISABLED; 70 break; 71 case ERR_ESIM_NOT_SUPPORTED: 72 case ERR_MULTISIM_NOT_SUPPORTED: 73 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_DEVICE_NOT_CAPABLE; 74 break; 75 case ERR_SINGLE_ACTIVE_OPPORTUNISTIC_SIM: 76 case ERR_DUAL_ACTIVE_SUBSCRIPTIONS: 77 case ERR_PSIM_NOT_FOUND: 78 case ERR_DOWNLOADED_ESIM_NOT_FOUND: 79 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_ESIM_PROVISIONING_FAILED; 80 break; 81 case ERR_WAITING_FOR_INTERNET_CONNECTION: 82 case ERR_WAITING_FOR_WIFI_CONNECTION: 83 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_INTERNET_NOT_AVAILABLE; 84 break; 85 case ERR_INVALID_CARRIER_CONFIG: 86 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_UNRESOLVABLE_ERROR; 87 break; 88 default: 89 break; 90 } 91 } else { 92 switch (info.getDownloadResult()) { 93 case ERR_UNRESOLVABLE: 94 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_UNRESOLVABLE_ERROR; 95 break; 96 case ERR_MEMORY_FULL: 97 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_MEMORY_FULL; 98 break; 99 case ERR_INSTALL_ESIM_PROFILE_FAILED: 100 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_INSTALL_ESIM_PROFILE_FAILED; 101 break; 102 case ERR_RETRY_DOWNLOAD: 103 statsCode = OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE__ERROR_CODE__RESULT_CONNECTION_ERROR; 104 break; 105 default: 106 break; 107 } 108 } 109 OnsStatsLog.write( 110 OnsStatsLog.ONS_OPPORTUNISTIC_ESIM_PROVISIONING_COMPLETE, 111 getSimCarrierId(info.getPrimarySimSubId()), 112 info.getOppSimCarrierId(), 113 info.isWifiConnected(), 114 statsCode, 115 info.getRetryCount(), 116 info.getDetailedErrCode()); 117 updateSharedPreferences(info); 118 return true; 119 } 120 updateSharedPreferences(ONSStatsInfo info)121 private void updateSharedPreferences(ONSStatsInfo info) { 122 SharedPreferences sharedPref = 123 mContext.getSharedPreferences(ONS_ATOM_LOG_FILE, Context.MODE_PRIVATE); 124 SharedPreferences.Editor editor = sharedPref.edit(); 125 if (info.isProvisioningResultUpdated()) { 126 editor.putInt(KEY_PROVISIONING_RESULT, info.getProvisioningResult().ordinal()); 127 editor.remove(KEY_DOWNLOAD_RESULT); 128 } else { 129 editor.putInt(KEY_DOWNLOAD_RESULT, info.getDownloadResult().ordinal()); 130 editor.remove(KEY_PROVISIONING_RESULT); 131 } 132 editor.putInt(KEY_PRIMARY_CARRIER_ID, getSimCarrierId(info.getPrimarySimSubId())) 133 .putInt(KEY_RETRY_COUNT, info.getRetryCount()) 134 .putInt(KEY_OPP_CARRIER_ID, info.getOppSimCarrierId()) 135 .putInt(KEY_DETAILED_ERROR_CODE, info.getDetailedErrCode()) 136 .apply(); 137 } 138 ignoreEvent(ONSStatsInfo info)139 private boolean ignoreEvent(ONSStatsInfo info) { 140 Result result = info.getProvisioningResult(); 141 if (info.isProvisioningResultUpdated()) { 142 info.setDetailedErrCode(result.ordinal()); 143 // Codes are ignored since they are intermediate state of CBRS provisioning check. 144 if ((result == Result.DOWNLOAD_REQUESTED) 145 || result == Result.ERR_NO_SIM_INSERTED 146 || result == Result.ERR_DUPLICATE_DOWNLOAD_REQUEST 147 || result == Result.ERR_SWITCHING_TO_DUAL_SIM_MODE) { 148 return true; 149 } 150 151 // add subscription id for carrier if it doesn't support CBRS. 152 if (result == Result.ERR_CARRIER_DOESNT_SUPPORT_CBRS) { 153 List<SubscriptionInfo> subInfos = 154 mSubscriptionManager.getActiveSubscriptionInfoList(); 155 info.setPrimarySimSubId( 156 (subInfos != null && !subInfos.isEmpty()) 157 ? subInfos.get(0).getSubscriptionId() 158 : -1); 159 } 160 } 161 162 SharedPreferences sharedPref = 163 mContext.getSharedPreferences(ONS_ATOM_LOG_FILE, Context.MODE_PRIVATE); 164 165 boolean errorCodeUpdated = 166 (info.isProvisioningResultUpdated() 167 ? sharedPref.getInt(KEY_PROVISIONING_RESULT, -1) != result.ordinal() 168 : sharedPref.getInt(KEY_DOWNLOAD_RESULT, -1) 169 != info.getDownloadResult().ordinal()); 170 boolean carrierIdUpdated = 171 sharedPref.getInt(KEY_PRIMARY_CARRIER_ID, -1) 172 != getSimCarrierId(info.getPrimarySimSubId()); 173 boolean retryCountUpdated = sharedPref.getInt(KEY_RETRY_COUNT, -1) != info.getRetryCount(); 174 boolean oppCarrierIdChanged = 175 sharedPref.getInt(KEY_OPP_CARRIER_ID, -1) != info.getOppSimCarrierId(); 176 boolean detailedErrorChanged = 177 sharedPref.getInt(KEY_DETAILED_ERROR_CODE, -1) != info.getDetailedErrCode(); 178 if (!(errorCodeUpdated 179 || carrierIdUpdated 180 || retryCountUpdated 181 || oppCarrierIdChanged 182 || detailedErrorChanged)) { 183 // Result codes are meant to log on every occurrence. These should not be ignored. 184 if (result == Result.SUCCESS 185 || result == Result.ERR_DOWNLOADED_ESIM_NOT_FOUND 186 || info.getDownloadResult() 187 == DownloadRetryResultCode.ERR_INSTALL_ESIM_PROFILE_FAILED) { 188 return false; 189 } 190 return true; 191 } 192 return false; 193 } 194 getSimCarrierId(int subId)195 private int getSimCarrierId(int subId) { 196 if (subId == -1) return -1; 197 SubscriptionInfo subInfo = mSubscriptionManager.getActiveSubscriptionInfo(subId); 198 return (subInfo != null) ? subInfo.getCarrierId() : -1; 199 } 200 } 201