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_API_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 ApiStats extends TelecomPulledAtom { 43 public static final int API_UNSPECIFIC = TelecomStatsLog 44 .TELECOM_API_STATS__API_NAME__API_UNSPECIFIED; 45 public static final int API_ACCEPTHANDOVER = TelecomStatsLog 46 .TELECOM_API_STATS__API_NAME__API_ACCEPT_HANDOVER; 47 public static final int API_ACCEPTRINGINGCALL = TelecomStatsLog 48 .TELECOM_API_STATS__API_NAME__API_ACCEPT_RINGING_CALL; 49 public static final int API_ACCEPTRINGINGCALLWITHVIDEOSTATE = TelecomStatsLog 50 .TELECOM_API_STATS__API_NAME__API_ACCEPT_RINGING_CALL_WITH_VIDEO_STATE; 51 public static final int API_ADDCALL = TelecomStatsLog.TELECOM_API_STATS__API_NAME__API_ADD_CALL; 52 public static final int API_ADDNEWINCOMINGCALL = TelecomStatsLog 53 .TELECOM_API_STATS__API_NAME__API_ADD_NEW_INCOMING_CALL; 54 public static final int API_ADDNEWINCOMINGCONFERENCE = TelecomStatsLog 55 .TELECOM_API_STATS__API_NAME__API_ADD_NEW_INCOMING_CONFERENCE; 56 public static final int API_ADDNEWUNKNOWNCALL = TelecomStatsLog 57 .TELECOM_API_STATS__API_NAME__API_ADD_NEW_UNKNOWN_CALL; 58 public static final int API_CANCELMISSEDCALLSNOTIFICATION = TelecomStatsLog 59 .TELECOM_API_STATS__API_NAME__API_CANCEL_MISSED_CALLS_NOTIFICATION; 60 public static final int API_CLEARACCOUNTS = TelecomStatsLog 61 .TELECOM_API_STATS__API_NAME__API_CLEAR_ACCOUNTS; 62 public static final int API_CREATELAUNCHEMERGENCYDIALERINTENT = TelecomStatsLog 63 .TELECOM_API_STATS__API_NAME__API_CREATE_LAUNCH_EMERGENCY_DIALER_INTENT; 64 public static final int API_CREATEMANAGEBLOCKEDNUMBERSINTENT = TelecomStatsLog 65 .TELECOM_API_STATS__API_NAME__API_CREATE_MANAGE_BLOCKED_NUMBERS_INTENT; 66 public static final int API_DUMP = TelecomStatsLog.TELECOM_API_STATS__API_NAME__API_DUMP; 67 public static final int API_DUMPCALLANALYTICS = TelecomStatsLog 68 .TELECOM_API_STATS__API_NAME__API_DUMP_CALL_ANALYTICS; 69 public static final int API_ENABLEPHONEACCOUNT = TelecomStatsLog 70 .TELECOM_API_STATS__API_NAME__API_ENABLE_PHONE_ACCOUNT; 71 public static final int API_ENDCALL = TelecomStatsLog.TELECOM_API_STATS__API_NAME__API_END_CALL; 72 public static final int API_GETADNURIFORPHONEACCOUNT = TelecomStatsLog 73 .TELECOM_API_STATS__API_NAME__API_GET_ADN_URI_FOR_PHONE_ACCOUNT; 74 public static final int API_GETALLPHONEACCOUNTHANDLES = TelecomStatsLog 75 .TELECOM_API_STATS__API_NAME__API_GET_ALL_PHONE_ACCOUNT_HANDLES; 76 public static final int API_GETALLPHONEACCOUNTS = TelecomStatsLog 77 .TELECOM_API_STATS__API_NAME__API_GET_ALL_PHONE_ACCOUNTS; 78 public static final int API_GETALLPHONEACCOUNTSCOUNT = TelecomStatsLog 79 .TELECOM_API_STATS__API_NAME__API_GET_ALL_PHONE_ACCOUNTS_COUNT; 80 public static final int API_GETCALLCAPABLEPHONEACCOUNTS = TelecomStatsLog 81 .TELECOM_API_STATS__API_NAME__API_GET_CALL_CAPABLE_PHONE_ACCOUNTS; 82 public static final int API_GETCALLSTATE = TelecomStatsLog 83 .TELECOM_API_STATS__API_NAME__API_GET_CALL_STATE; 84 public static final int API_GETCALLSTATEUSINGPACKAGE = TelecomStatsLog 85 .TELECOM_API_STATS__API_NAME__API_GET_CALL_STATE_USING_PACKAGE; 86 public static final int API_GETCURRENTTTYMODE = TelecomStatsLog 87 .TELECOM_API_STATS__API_NAME__API_GET_CURRENT_TTY_MODE; 88 public static final int API_GETDEFAULTDIALERPACKAGE = TelecomStatsLog 89 .TELECOM_API_STATS__API_NAME__API_GET_DEFAULT_DIALER_PACKAGE; 90 public static final int API_GETDEFAULTDIALERPACKAGEFORUSER = TelecomStatsLog 91 .TELECOM_API_STATS__API_NAME__API_GET_DEFAULT_DIALER_PACKAGE_FOR_USER; 92 public static final int API_GETDEFAULTOUTGOINGPHONEACCOUNT = TelecomStatsLog 93 .TELECOM_API_STATS__API_NAME__API_GET_DEFAULT_OUTGOING_PHONE_ACCOUNT; 94 public static final int API_GETDEFAULTPHONEAPP = TelecomStatsLog 95 .TELECOM_API_STATS__API_NAME__API_GET_DEFAULT_PHONE_APP; 96 public static final int API_GETLINE1NUMBER = TelecomStatsLog 97 .TELECOM_API_STATS__API_NAME__API_GET_LINE1_NUMBER; 98 public static final int API_GETOWNSELFMANAGEDPHONEACCOUNTS = TelecomStatsLog 99 .TELECOM_API_STATS__API_NAME__API_GET_OWN_SELF_MANAGED_PHONE_ACCOUNTS; 100 public static final int API_GETPHONEACCOUNT = TelecomStatsLog 101 .TELECOM_API_STATS__API_NAME__API_GET_PHONE_ACCOUNT; 102 public static final int API_GETPHONEACCOUNTSFORPACKAGE = TelecomStatsLog 103 .TELECOM_API_STATS__API_NAME__API_GET_PHONE_ACCOUNTS_FOR_PACKAGE; 104 public static final int API_GETPHONEACCOUNTSSUPPORTINGSCHEME = TelecomStatsLog 105 .TELECOM_API_STATS__API_NAME__API_GET_PHONE_ACCOUNTS_SUPPORTING_SCHEME; 106 public static final int API_GETREGISTEREDPHONEACCOUNTS = TelecomStatsLog 107 .TELECOM_API_STATS__API_NAME__API_GET_REGISTERED_PHONE_ACCOUNTS; 108 public static final int API_GETSELFMANAGEDPHONEACCOUNTS = TelecomStatsLog 109 .TELECOM_API_STATS__API_NAME__API_GET_SELF_MANAGED_PHONE_ACCOUNTS; 110 public static final int API_GETSIMCALLMANAGER = TelecomStatsLog 111 .TELECOM_API_STATS__API_NAME__API_GET_SIM_CALL_MANAGER; 112 public static final int API_GETSIMCALLMANAGERFORUSER = TelecomStatsLog 113 .TELECOM_API_STATS__API_NAME__API_GET_SIM_CALL_MANAGER_FOR_USER; 114 public static final int API_GETSYSTEMDIALERPACKAGE = TelecomStatsLog 115 .TELECOM_API_STATS__API_NAME__API_GET_SYSTEM_DIALER_PACKAGE; 116 public static final int API_GETUSERSELECTEDOUTGOINGPHONEACCOUNT = TelecomStatsLog 117 .TELECOM_API_STATS__API_NAME__API_GET_USER_SELECTED_OUTGOING_PHONE_ACCOUNT; 118 public static final int API_GETVOICEMAILNUMBER = TelecomStatsLog 119 .TELECOM_API_STATS__API_NAME__API_GET_VOICE_MAIL_NUMBER; 120 public static final int API_HANDLEPINMMI = TelecomStatsLog 121 .TELECOM_API_STATS__API_NAME__API_HANDLE_PIN_MMI; 122 public static final int API_HANDLEPINMMIFORPHONEACCOUNT = TelecomStatsLog 123 .TELECOM_API_STATS__API_NAME__API_HANDLE_PIN_MMI_FOR_PHONE_ACCOUNT; 124 public static final int API_HASMANAGEONGOINGCALLSPERMISSION = TelecomStatsLog 125 .TELECOM_API_STATS__API_NAME__API_HAS_MANAGE_ONGOING_CALLS_PERMISSION; 126 public static final int API_ISINCALL = TelecomStatsLog 127 .TELECOM_API_STATS__API_NAME__API_IS_IN_CALL; 128 public static final int API_ISINCOMINGCALLPERMITTED = TelecomStatsLog 129 .TELECOM_API_STATS__API_NAME__API_IS_IN_EMERGENCY_CALL; 130 public static final int API_ISINEMERGENCYCALL = TelecomStatsLog 131 .TELECOM_API_STATS__API_NAME__API_IS_IN_MANAGED_CALL; 132 public static final int API_ISINMANAGEDCALL = TelecomStatsLog 133 .TELECOM_API_STATS__API_NAME__API_IS_IN_SELF_MANAGED_CALL; 134 public static final int API_ISINSELFMANAGEDCALL = TelecomStatsLog 135 .TELECOM_API_STATS__API_NAME__API_IS_INCOMING_CALL_PERMITTED; 136 public static final int API_ISOUTGOINGCALLPERMITTED = TelecomStatsLog 137 .TELECOM_API_STATS__API_NAME__API_IS_OUTGOING_CALL_PERMITTED; 138 public static final int API_ISRINGING = TelecomStatsLog 139 .TELECOM_API_STATS__API_NAME__API_IS_RINGING; 140 public static final int API_ISTTYSUPPORTED = TelecomStatsLog 141 .TELECOM_API_STATS__API_NAME__API_IS_TTY_SUPPORTED; 142 public static final int API_ISVOICEMAILNUMBER = TelecomStatsLog 143 .TELECOM_API_STATS__API_NAME__API_IS_VOICE_MAIL_NUMBER; 144 public static final int API_PLACECALL = TelecomStatsLog 145 .TELECOM_API_STATS__API_NAME__API_PLACE_CALL; 146 public static final int API_REGISTERPHONEACCOUNT = TelecomStatsLog 147 .TELECOM_API_STATS__API_NAME__API_REGISTER_PHONE_ACCOUNT; 148 public static final int API_SETDEFAULTDIALER = TelecomStatsLog 149 .TELECOM_API_STATS__API_NAME__API_SET_DEFAULT_DIALER; 150 public static final int API_SETUSERSELECTEDOUTGOINGPHONEACCOUNT = TelecomStatsLog 151 .TELECOM_API_STATS__API_NAME__API_SET_USER_SELECTED_OUTGOING_PHONE_ACCOUNT; 152 public static final int API_SHOWINCALLSCREEN = TelecomStatsLog 153 .TELECOM_API_STATS__API_NAME__API_SHOW_IN_CALL_SCREEN; 154 public static final int API_SILENCERINGER = TelecomStatsLog 155 .TELECOM_API_STATS__API_NAME__API_SILENCE_RINGER; 156 public static final int API_STARTCONFERENCE = TelecomStatsLog 157 .TELECOM_API_STATS__API_NAME__API_START_CONFERENCE; 158 public static final int API_UNREGISTERPHONEACCOUNT = TelecomStatsLog 159 .TELECOM_API_STATS__API_NAME__API_UNREGISTER_PHONE_ACCOUNT; 160 public static final int RESULT_UNKNOWN = TelecomStatsLog 161 .TELECOM_API_STATS__API_RESULT__RESULT_UNKNOWN; 162 public static final int RESULT_NORMAL = TelecomStatsLog 163 .TELECOM_API_STATS__API_RESULT__RESULT_SUCCESS; 164 public static final int RESULT_PERMISSION = TelecomStatsLog 165 .TELECOM_API_STATS__API_RESULT__RESULT_PERMISSION; 166 public static final int RESULT_EXCEPTION = TelecomStatsLog 167 .TELECOM_API_STATS__API_RESULT__RESULT_EXCEPTION; 168 private static final String TAG = ApiStats.class.getSimpleName(); 169 private static final String FILE_NAME = "api_stats"; 170 private Map<ApiEvent, Integer> mApiStatsMap; 171 ApiStats(@onNull Context context, @NonNull Looper looper, boolean isTestMode)172 public ApiStats(@NonNull Context context, @NonNull Looper looper, boolean isTestMode) { 173 super(context, looper, isTestMode); 174 } 175 176 @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) 177 @Override getTag()178 public int getTag() { 179 return TELECOM_API_STATS; 180 } 181 182 @Override getFileName()183 protected String getFileName() { 184 return FILE_NAME; 185 } 186 187 @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) 188 @Override onPull(final List<StatsEvent> data)189 public synchronized int onPull(final List<StatsEvent> data) { 190 if (mPulledAtoms.telecomApiStats.length != 0) { 191 Arrays.stream(mPulledAtoms.telecomApiStats).forEach(v -> data.add( 192 TelecomStatsLog.buildStatsEvent(getTag(), 193 v.getApiName(), v.getUid(), v.getApiResult(), v.getCount()))); 194 mApiStatsMap.clear(); 195 onAggregate(); 196 return StatsManager.PULL_SUCCESS; 197 } else { 198 return StatsManager.PULL_SKIP; 199 } 200 } 201 202 @Override onLoad()203 protected synchronized void onLoad() { 204 if (mPulledAtoms.telecomApiStats != null) { 205 mApiStatsMap = new HashMap<>(); 206 for (PulledAtomsClass.TelecomApiStats v : mPulledAtoms.telecomApiStats) { 207 mApiStatsMap.put(new ApiEvent(v.getApiName(), v.getUid(), v.getApiResult()), 208 v.getCount()); 209 } 210 mLastPulledTimestamps = mPulledAtoms.getTelecomApiStatsPullTimestampMillis(); 211 } 212 } 213 214 @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) 215 @Override onAggregate()216 public synchronized void onAggregate() { 217 Log.d(TAG, "onAggregate: %s", mApiStatsMap); 218 clearAtoms(); 219 if (mApiStatsMap.isEmpty()) { 220 return; 221 } 222 mPulledAtoms.setTelecomApiStatsPullTimestampMillis(mLastPulledTimestamps); 223 mPulledAtoms.telecomApiStats = 224 new PulledAtomsClass.TelecomApiStats[mApiStatsMap.size()]; 225 int[] index = new int[1]; 226 mApiStatsMap.forEach((k, v) -> { 227 mPulledAtoms.telecomApiStats[index[0]] = new PulledAtomsClass.TelecomApiStats(); 228 mPulledAtoms.telecomApiStats[index[0]].setApiName(k.mId); 229 mPulledAtoms.telecomApiStats[index[0]].setUid(k.mCallerUid); 230 mPulledAtoms.telecomApiStats[index[0]].setApiResult(k.mResult); 231 mPulledAtoms.telecomApiStats[index[0]].setCount(v); 232 index[0]++; 233 }); 234 save(DELAY_FOR_PERSISTENT_MILLIS); 235 } 236 log(@onNull ApiEvent event)237 public void log(@NonNull ApiEvent event) { 238 post(() -> { 239 mApiStatsMap.put(event, mApiStatsMap.getOrDefault(event, 0) + 1); 240 onAggregate(); 241 }); 242 } 243 244 @IntDef(prefix = "API", value = { 245 API_UNSPECIFIC, 246 API_ACCEPTHANDOVER, 247 API_ACCEPTRINGINGCALL, 248 API_ACCEPTRINGINGCALLWITHVIDEOSTATE, 249 API_ADDCALL, 250 API_ADDNEWINCOMINGCALL, 251 API_ADDNEWINCOMINGCONFERENCE, 252 API_ADDNEWUNKNOWNCALL, 253 API_CANCELMISSEDCALLSNOTIFICATION, 254 API_CLEARACCOUNTS, 255 API_CREATELAUNCHEMERGENCYDIALERINTENT, 256 API_CREATEMANAGEBLOCKEDNUMBERSINTENT, 257 API_DUMP, 258 API_DUMPCALLANALYTICS, 259 API_ENABLEPHONEACCOUNT, 260 API_ENDCALL, 261 API_GETADNURIFORPHONEACCOUNT, 262 API_GETALLPHONEACCOUNTHANDLES, 263 API_GETALLPHONEACCOUNTS, 264 API_GETALLPHONEACCOUNTSCOUNT, 265 API_GETCALLCAPABLEPHONEACCOUNTS, 266 API_GETCALLSTATE, 267 API_GETCALLSTATEUSINGPACKAGE, 268 API_GETCURRENTTTYMODE, 269 API_GETDEFAULTDIALERPACKAGE, 270 API_GETDEFAULTDIALERPACKAGEFORUSER, 271 API_GETDEFAULTOUTGOINGPHONEACCOUNT, 272 API_GETDEFAULTPHONEAPP, 273 API_GETLINE1NUMBER, 274 API_GETOWNSELFMANAGEDPHONEACCOUNTS, 275 API_GETPHONEACCOUNT, 276 API_GETPHONEACCOUNTSFORPACKAGE, 277 API_GETPHONEACCOUNTSSUPPORTINGSCHEME, 278 API_GETREGISTEREDPHONEACCOUNTS, 279 API_GETSELFMANAGEDPHONEACCOUNTS, 280 API_GETSIMCALLMANAGER, 281 API_GETSIMCALLMANAGERFORUSER, 282 API_GETSYSTEMDIALERPACKAGE, 283 API_GETUSERSELECTEDOUTGOINGPHONEACCOUNT, 284 API_GETVOICEMAILNUMBER, 285 API_HANDLEPINMMI, 286 API_HANDLEPINMMIFORPHONEACCOUNT, 287 API_HASMANAGEONGOINGCALLSPERMISSION, 288 API_ISINCALL, 289 API_ISINCOMINGCALLPERMITTED, 290 API_ISINEMERGENCYCALL, 291 API_ISINMANAGEDCALL, 292 API_ISINSELFMANAGEDCALL, 293 API_ISOUTGOINGCALLPERMITTED, 294 API_ISRINGING, 295 API_ISTTYSUPPORTED, 296 API_ISVOICEMAILNUMBER, 297 API_PLACECALL, 298 API_REGISTERPHONEACCOUNT, 299 API_SETDEFAULTDIALER, 300 API_SETUSERSELECTEDOUTGOINGPHONEACCOUNT, 301 API_SHOWINCALLSCREEN, 302 API_SILENCERINGER, 303 API_STARTCONFERENCE, 304 API_UNREGISTERPHONEACCOUNT, 305 }) 306 @Retention(RetentionPolicy.SOURCE) 307 public @interface ApiId { 308 } 309 310 @IntDef(prefix = "RESULT", value = { 311 RESULT_UNKNOWN, 312 RESULT_NORMAL, 313 RESULT_PERMISSION, 314 RESULT_EXCEPTION, 315 }) 316 @Retention(RetentionPolicy.SOURCE) 317 public @interface ResultId { 318 } 319 320 public static class ApiEvent { 321 322 @ApiId 323 int mId; 324 int mCallerUid; 325 @ResultId 326 int mResult; 327 ApiEvent(@piId int id, int callerUid, @ResultId int result)328 public ApiEvent(@ApiId int id, int callerUid, @ResultId int result) { 329 mId = id; 330 mCallerUid = callerUid; 331 mResult = result; 332 } 333 setCallerUid(int uid)334 public void setCallerUid(int uid) { 335 this.mCallerUid = uid; 336 } 337 setResult(@esultId int result)338 public void setResult(@ResultId int result) { 339 this.mResult = result; 340 } 341 342 @Override equals(Object other)343 public boolean equals(Object other) { 344 if (this == other) { 345 return true; 346 } 347 if (!(other instanceof ApiEvent obj)) { 348 return false; 349 } 350 return this.mId == obj.mId && this.mCallerUid == obj.mCallerUid 351 && this.mResult == obj.mResult; 352 } 353 354 @Override hashCode()355 public int hashCode() { 356 return Objects.hash(mId, mCallerUid, mResult); 357 } 358 359 @Override toString()360 public String toString() { 361 return "[ApiEvent: mApiId=" + mId + ", mCallerUid=" + mCallerUid 362 + ", mResult=" + mResult + "]"; 363 } 364 } 365 } 366