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