• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.server.telecom.metrics;
18 
19 import static com.android.server.telecom.TelecomStatsLog.TELECOM_ERROR_STATS;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.app.StatsManager;
24 import android.content.Context;
25 import android.os.Looper;
26 import android.telecom.Log;
27 import android.util.StatsEvent;
28 
29 import androidx.annotation.VisibleForTesting;
30 
31 import com.android.server.telecom.TelecomStatsLog;
32 import com.android.server.telecom.nano.PulledAtomsClass;
33 
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.util.Arrays;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Map;
40 import java.util.Objects;
41 
42 public class ErrorStats extends TelecomPulledAtom {
43     public static final int SUB_UNKNOWN = TelecomStatsLog
44             .TELECOM_ERROR_STATS__SUBMODULE__SUB_UNKNOWN;
45     public static final int SUB_CALL_AUDIO = TelecomStatsLog
46             .TELECOM_ERROR_STATS__SUBMODULE__SUB_CALL_AUDIO;
47     public static final int SUB_CALL_LOGS = TelecomStatsLog
48             .TELECOM_ERROR_STATS__SUBMODULE__SUB_CALL_LOGS;
49     public static final int SUB_CALL_MANAGER = TelecomStatsLog
50             .TELECOM_ERROR_STATS__SUBMODULE__SUB_CALL_MANAGER;
51     public static final int SUB_CONNECTION_SERVICE = TelecomStatsLog
52             .TELECOM_ERROR_STATS__SUBMODULE__SUB_CONNECTION_SERVICE;
53     public static final int SUB_EMERGENCY_CALL = TelecomStatsLog
54             .TELECOM_ERROR_STATS__SUBMODULE__SUB_EMERGENCY_CALL;
55     public static final int SUB_IN_CALL_SERVICE = TelecomStatsLog
56             .TELECOM_ERROR_STATS__SUBMODULE__SUB_IN_CALL_SERVICE;
57     public static final int SUB_MISC = TelecomStatsLog.TELECOM_ERROR_STATS__SUBMODULE__SUB_MISC;
58     public static final int SUB_PHONE_ACCOUNT = TelecomStatsLog
59             .TELECOM_ERROR_STATS__SUBMODULE__SUB_PHONE_ACCOUNT;
60     public static final int SUB_SYSTEM_SERVICE = TelecomStatsLog
61             .TELECOM_ERROR_STATS__SUBMODULE__SUB_SYSTEM_SERVICE;
62     public static final int SUB_TELEPHONY = TelecomStatsLog
63             .TELECOM_ERROR_STATS__SUBMODULE__SUB_TELEPHONY;
64     public static final int SUB_UI = TelecomStatsLog.TELECOM_ERROR_STATS__SUBMODULE__SUB_UI;
65     public static final int SUB_VOIP_CALL = TelecomStatsLog
66             .TELECOM_ERROR_STATS__SUBMODULE__SUB_VOIP_CALL;
67     public static final int ERROR_UNKNOWN = TelecomStatsLog
68             .TELECOM_ERROR_STATS__ERROR__ERROR_UNKNOWN;
69     public static final int ERROR_EXTERNAL_EXCEPTION = TelecomStatsLog
70             .TELECOM_ERROR_STATS__ERROR__ERROR_EXTERNAL_EXCEPTION;
71     public static final int ERROR_INTERNAL_EXCEPTION = TelecomStatsLog
72             .TELECOM_ERROR_STATS__ERROR__ERROR_INTERNAL_EXCEPTION;
73     public static final int ERROR_AUDIO_ROUTE_RETRY_REJECTED = TelecomStatsLog
74             .TELECOM_ERROR_STATS__ERROR__ERROR_AUDIO_ROUTE_RETRY_REJECTED;
75     public static final int ERROR_BT_GET_SERVICE_FAILURE = TelecomStatsLog
76             .TELECOM_ERROR_STATS__ERROR__ERROR_BT_GET_SERVICE_FAILURE;
77     public static final int ERROR_BT_REGISTER_CALLBACK_FAILURE = TelecomStatsLog
78             .TELECOM_ERROR_STATS__ERROR__ERROR_BT_REGISTER_CALLBACK_FAILURE;
79     public static final int ERROR_AUDIO_ROUTE_UNAVAILABLE = TelecomStatsLog
80             .TELECOM_ERROR_STATS__ERROR__ERROR_AUDIO_ROUTE_UNAVAILABLE;
81     public static final int ERROR_EMERGENCY_NUMBER_DETERMINED_FAILURE = TelecomStatsLog
82             .TELECOM_ERROR_STATS__ERROR__ERROR_EMERGENCY_NUMBER_DETERMINED_FAILURE;
83     public static final int ERROR_NOTIFY_CALL_STREAM_START_FAILURE = TelecomStatsLog
84             .TELECOM_ERROR_STATS__ERROR__ERROR_NOTIFY_CALL_STREAM_START_FAILURE;
85     public static final int ERROR_NOTIFY_CALL_STREAM_STATE_CHANGED_FAILURE = TelecomStatsLog
86             .TELECOM_ERROR_STATS__ERROR__ERROR_NOTIFY_CALL_STREAM_STATE_CHANGED_FAILURE;
87     public static final int ERROR_NOTIFY_CALL_STREAM_STOP_FAILURE = TelecomStatsLog
88             .TELECOM_ERROR_STATS__ERROR__ERROR_NOTIFY_CALL_STREAM_STOP_FAILURE;
89     public static final int ERROR_RTT_STREAM_CLOSE_FAILURE = TelecomStatsLog
90             .TELECOM_ERROR_STATS__ERROR__ERROR_RTT_STREAM_CLOSE_FAILURE;
91     public static final int ERROR_RTT_STREAM_CREATE_FAILURE = TelecomStatsLog
92             .TELECOM_ERROR_STATS__ERROR__ERROR_RTT_STREAM_CREATE_FAILURE;
93     public static final int ERROR_SET_MUTED_FAILURE = TelecomStatsLog
94             .TELECOM_ERROR_STATS__ERROR__ERROR_SET_MUTED_FAILURE;
95     public static final int ERROR_VIDEO_PROVIDER_SET_FAILURE = TelecomStatsLog
96             .TELECOM_ERROR_STATS__ERROR__ERROR_VIDEO_PROVIDER_SET_FAILURE;
97     public static final int ERROR_WIRED_HEADSET_NOT_AVAILABLE = TelecomStatsLog
98             .TELECOM_ERROR_STATS__ERROR__ERROR_WIRED_HEADSET_NOT_AVAILABLE;
99     public static final int ERROR_LOG_CALL_FAILURE = TelecomStatsLog
100             .TELECOM_ERROR_STATS__ERROR__ERROR_LOG_CALL_FAILURE;
101     public static final int ERROR_RETRIEVING_ACCOUNT_EMERGENCY = TelecomStatsLog
102             .TELECOM_ERROR_STATS__ERROR__ERROR_RETRIEVING_ACCOUNT_EMERGENCY;
103     public static final int ERROR_RETRIEVING_ACCOUNT = TelecomStatsLog
104             .TELECOM_ERROR_STATS__ERROR__ERROR_RETRIEVING_ACCOUNT;
105     public static final int ERROR_EMERGENCY_CALL_ABORTED_NO_ACCOUNT = TelecomStatsLog
106             .TELECOM_ERROR_STATS__ERROR__ERROR_EMERGENCY_CALL_ABORTED_NO_ACCOUNT;
107     public static final int ERROR_DEFAULT_MO_ACCOUNT_MISMATCH = TelecomStatsLog
108             .TELECOM_ERROR_STATS__ERROR__ERROR_DEFAULT_MO_ACCOUNT_MISMATCH;
109     public static final int ERROR_ESTABLISHING_CONNECTION = TelecomStatsLog
110             .TELECOM_ERROR_STATS__ERROR__ERROR_ESTABLISHING_CONNECTION;
111     public static final int ERROR_REMOVING_CALL = TelecomStatsLog
112             .TELECOM_ERROR_STATS__ERROR__ERROR_REMOVING_CALL;
113     public static final int ERROR_STUCK_CONNECTING_EMERGENCY = TelecomStatsLog
114             .TELECOM_ERROR_STATS__ERROR__ERROR_STUCK_CONNECTING_EMERGENCY;
115     public static final int ERROR_STUCK_CONNECTING = TelecomStatsLog
116             .TELECOM_ERROR_STATS__ERROR__ERROR_STUCK_CONNECTING;
117     private static final String TAG = ErrorStats.class.getSimpleName();
118     private static final String FILE_NAME = "error_stats";
119     private Map<ErrorEvent, Integer> mErrorStatsMap;
120 
ErrorStats(@onNull Context context, @NonNull Looper looper, boolean isTestMode)121     public ErrorStats(@NonNull Context context, @NonNull Looper looper, boolean isTestMode) {
122         super(context, looper, isTestMode);
123     }
124 
125     @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
126     @Override
getTag()127     public int getTag() {
128         return TELECOM_ERROR_STATS;
129     }
130 
131     @Override
getFileName()132     protected String getFileName() {
133         return FILE_NAME;
134     }
135 
136     @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
137     @Override
onPull(final List<StatsEvent> data)138     public synchronized int onPull(final List<StatsEvent> data) {
139         if (mPulledAtoms.telecomErrorStats.length != 0) {
140             Arrays.stream(mPulledAtoms.telecomErrorStats).forEach(v -> data.add(
141                     TelecomStatsLog.buildStatsEvent(getTag(),
142                             v.getSubmodule(), v.getError(), v.getCount())));
143             mErrorStatsMap.clear();
144             onAggregate();
145             return StatsManager.PULL_SUCCESS;
146         } else {
147             return StatsManager.PULL_SKIP;
148         }
149     }
150 
151     @Override
onLoad()152     protected synchronized void onLoad() {
153         if (mPulledAtoms.telecomErrorStats != null) {
154             mErrorStatsMap = new HashMap<>();
155             for (PulledAtomsClass.TelecomErrorStats v : mPulledAtoms.telecomErrorStats) {
156                 mErrorStatsMap.put(new ErrorEvent(v.getSubmodule(), v.getError()),
157                         v.getCount());
158             }
159             mLastPulledTimestamps = mPulledAtoms.getTelecomErrorStatsPullTimestampMillis();
160         }
161     }
162 
163     @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
164     @Override
onAggregate()165     public synchronized void onAggregate() {
166         Log.d(TAG, "onAggregate: %s", mErrorStatsMap);
167         clearAtoms();
168         if (mErrorStatsMap.isEmpty()) {
169             return;
170         }
171         mPulledAtoms.setTelecomErrorStatsPullTimestampMillis(mLastPulledTimestamps);
172         mPulledAtoms.telecomErrorStats =
173                 new PulledAtomsClass.TelecomErrorStats[mErrorStatsMap.size()];
174         int[] index = new int[1];
175         mErrorStatsMap.forEach((k, v) -> {
176             mPulledAtoms.telecomErrorStats[index[0]] = new PulledAtomsClass.TelecomErrorStats();
177             mPulledAtoms.telecomErrorStats[index[0]].setSubmodule(k.mModuleId);
178             mPulledAtoms.telecomErrorStats[index[0]].setError(k.mErrorId);
179             mPulledAtoms.telecomErrorStats[index[0]].setCount(v);
180             index[0]++;
181         });
182         save(DELAY_FOR_PERSISTENT_MILLIS);
183     }
184 
log(@ubModuleId int moduleId, @ErrorId int errorId)185     public void log(@SubModuleId int moduleId, @ErrorId int errorId) {
186         post(() -> {
187             ErrorEvent key = new ErrorEvent(moduleId, errorId);
188             mErrorStatsMap.put(key, mErrorStatsMap.getOrDefault(key, 0) + 1);
189             onAggregate();
190         });
191     }
192 
193     @IntDef(prefix = "SUB", value = {
194             SUB_UNKNOWN,
195             SUB_CALL_AUDIO,
196             SUB_CALL_LOGS,
197             SUB_CALL_MANAGER,
198             SUB_CONNECTION_SERVICE,
199             SUB_EMERGENCY_CALL,
200             SUB_IN_CALL_SERVICE,
201             SUB_MISC,
202             SUB_PHONE_ACCOUNT,
203             SUB_SYSTEM_SERVICE,
204             SUB_TELEPHONY,
205             SUB_UI,
206             SUB_VOIP_CALL,
207     })
208     @Retention(RetentionPolicy.SOURCE)
209     public @interface SubModuleId {
210     }
211 
212     @IntDef(prefix = "ERROR", value = {
213             ERROR_UNKNOWN,
214             ERROR_EXTERNAL_EXCEPTION,
215             ERROR_INTERNAL_EXCEPTION,
216             ERROR_AUDIO_ROUTE_RETRY_REJECTED,
217             ERROR_BT_GET_SERVICE_FAILURE,
218             ERROR_BT_REGISTER_CALLBACK_FAILURE,
219             ERROR_AUDIO_ROUTE_UNAVAILABLE,
220             ERROR_EMERGENCY_NUMBER_DETERMINED_FAILURE,
221             ERROR_NOTIFY_CALL_STREAM_START_FAILURE,
222             ERROR_NOTIFY_CALL_STREAM_STATE_CHANGED_FAILURE,
223             ERROR_NOTIFY_CALL_STREAM_STOP_FAILURE,
224             ERROR_RTT_STREAM_CLOSE_FAILURE,
225             ERROR_RTT_STREAM_CREATE_FAILURE,
226             ERROR_SET_MUTED_FAILURE,
227             ERROR_VIDEO_PROVIDER_SET_FAILURE,
228             ERROR_WIRED_HEADSET_NOT_AVAILABLE,
229             ERROR_LOG_CALL_FAILURE,
230             ERROR_RETRIEVING_ACCOUNT_EMERGENCY,
231             ERROR_RETRIEVING_ACCOUNT,
232             ERROR_EMERGENCY_CALL_ABORTED_NO_ACCOUNT,
233             ERROR_DEFAULT_MO_ACCOUNT_MISMATCH,
234             ERROR_ESTABLISHING_CONNECTION,
235             ERROR_REMOVING_CALL,
236             ERROR_STUCK_CONNECTING_EMERGENCY,
237             ERROR_STUCK_CONNECTING,
238     })
239     @Retention(RetentionPolicy.SOURCE)
240     public @interface ErrorId {
241     }
242 
243     static class ErrorEvent {
244 
245         final @SubModuleId int mModuleId;
246         final @ErrorId int mErrorId;
247 
ErrorEvent(@ubModuleId int moduleId, @ErrorId int errorId)248         ErrorEvent(@SubModuleId int moduleId, @ErrorId int errorId) {
249             mModuleId = moduleId;
250             mErrorId = errorId;
251         }
252 
253         @Override
equals(Object other)254         public boolean equals(Object other) {
255             if (this == other) {
256                 return true;
257             }
258             if (!(other instanceof ErrorEvent obj)) {
259                 return false;
260             }
261             return this.mModuleId == obj.mModuleId && this.mErrorId == obj.mErrorId;
262         }
263 
264         @Override
hashCode()265         public int hashCode() {
266             return Objects.hash(mModuleId, mErrorId);
267         }
268 
269         @Override
toString()270         public String toString() {
271             return "[ErrorEvent: mModuleId=" + mModuleId + ", mErrorId=" + mErrorId + "]";
272         }
273     }
274 }
275