1 /* 2 * Copyright (C) 2023 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.safetycenter.logging; 18 19 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED; 20 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ACTION__ISSUE_PRIMARY_ACTION_CLICKED; 21 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ACTION__ISSUE_SECONDARY_ACTION_CLICKED; 22 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ACTION__NOTIFICATION_DISMISSED; 23 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ACTION__NOTIFICATION_POSTED; 24 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__ISSUE_STATE__ACTIVE; 25 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__NAVIGATION_SOURCE__SOURCE_UNKNOWN; 26 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_MANAGED; 27 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PERSONAL; 28 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PRIVATE; 29 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN; 30 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SENSOR__SENSOR_UNKNOWN; 31 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_CRITICAL_WARNING; 32 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_OK; 33 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_RECOMMENDATION; 34 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_UNSPECIFIED; 35 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_INTERACTION_REPORTED__VIEW_TYPE__VIEW_TYPE_NOTIFICATION; 36 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED; 37 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__COMPLETE_GET_NEW_DATA; 38 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__COMPLETE_RESCAN; 39 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__EVENT_TYPE_UNKNOWN; 40 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__INLINE_ACTION; 41 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__SINGLE_SOURCE_GET_NEW_DATA; 42 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__SINGLE_SOURCE_RESCAN; 43 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__ERROR; 44 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__SUCCESS; 45 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__TIMEOUT; 46 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_MANAGED; 47 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PERSONAL; 48 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PRIVATE; 49 import static com.android.permission.PermissionStatsLog.SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN; 50 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED; 51 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__COLLECTION_TYPE__AUTOMATIC; 52 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__COLLECTION_TYPE__SOURCE_UPDATED; 53 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_MANAGED; 54 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PERSONAL; 55 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PRIVATE; 56 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN; 57 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_CRITICAL_WARNING; 58 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 59 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_OK; 60 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_RECOMMENDATION; 61 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_UNSPECIFIED; 62 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__DATA_PROVIDED; 63 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__NO_DATA_PROVIDED; 64 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__REFRESH_ERROR; 65 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__REFRESH_TIMEOUT; 66 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_CLEARED; 67 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_ERROR; 68 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_STATE_UNKNOWN; 69 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__UPDATE_TYPE__REFRESH_RESPONSE; 70 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__UPDATE_TYPE__SELF_INITIATED; 71 import static com.android.permission.PermissionStatsLog.SAFETY_SOURCE_STATE_COLLECTED__UPDATE_TYPE__UPDATE_TYPE_UNKNOWN; 72 import static com.android.permission.PermissionStatsLog.SAFETY_STATE; 73 import static com.android.permission.PermissionStatsLog.SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_CRITICAL_WARNING; 74 import static com.android.permission.PermissionStatsLog.SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 75 import static com.android.permission.PermissionStatsLog.SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_OK; 76 import static com.android.permission.PermissionStatsLog.SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_RECOMMENDATION; 77 import static com.android.safetycenter.UserProfileGroup.PROFILE_TYPE_MANAGED; 78 import static com.android.safetycenter.UserProfileGroup.PROFILE_TYPE_PRIMARY; 79 import static com.android.safetycenter.UserProfileGroup.PROFILE_TYPE_PRIVATE; 80 81 import android.annotation.ElapsedRealtimeLong; 82 import android.annotation.IntDef; 83 import android.safetycenter.SafetyCenterManager; 84 import android.safetycenter.SafetyCenterManager.RefreshRequestType; 85 import android.safetycenter.SafetyCenterStatus; 86 import android.safetycenter.SafetyEvent; 87 import android.safetycenter.SafetySourceData; 88 import android.util.Log; 89 import android.util.StatsEvent; 90 91 import androidx.annotation.Nullable; 92 93 import com.android.permission.PermissionStatsLog; 94 import com.android.safetycenter.SafetyCenterFlags; 95 import com.android.safetycenter.UserProfileGroup.ProfileType; 96 97 import java.lang.annotation.Retention; 98 import java.lang.annotation.RetentionPolicy; 99 import java.math.BigInteger; 100 import java.security.MessageDigest; 101 import java.security.NoSuchAlgorithmException; 102 import java.time.Duration; 103 104 /** 105 * Marshalls and writes statsd atoms. Contains implementation details of how atom parameters are 106 * encoded and provides a better-typed interface for other classes to call. 107 * 108 * @hide 109 */ 110 public final class SafetyCenterStatsdLogger { 111 112 private static final String TAG = "SafetyCenterStatsdLog"; 113 private static final long UNSET_SOURCE_ID = 0; 114 private static final long UNSET_ISSUE_TYPE_ID = 0; 115 private static final long UNSET_SESSION_ID = 0; 116 private static final long UNSET_SOURCE_GROUP_ID = 0; 117 private static final long UNSET_REFRESH_REASON = 0L; 118 private static final boolean UNSET_DATA_CHANGED = false; 119 private static final long UNSET_LAST_UPDATED_ELAPSED_TIME_MILLIS = 0L; 120 121 /** 122 * The different results for a system event reported by Safety Center. 123 * 124 * @hide 125 */ 126 @IntDef( 127 prefix = {"SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__"}, 128 value = { 129 SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__SUCCESS, 130 SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__ERROR, 131 SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__TIMEOUT 132 }) 133 @Retention(RetentionPolicy.SOURCE) 134 public @interface SystemEventResult {} 135 136 /** 137 * The different results for a system event reported by Safety Center. 138 * 139 * @hide 140 */ 141 @IntDef( 142 prefix = {"SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__"}, 143 value = { 144 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_STATE_UNKNOWN, 145 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__DATA_PROVIDED, 146 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__NO_DATA_PROVIDED, 147 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__REFRESH_TIMEOUT, 148 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__REFRESH_ERROR, 149 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_ERROR, 150 SAFETY_SOURCE_STATE_COLLECTED__SOURCE_STATE__SOURCE_CLEARED 151 }) 152 @Retention(RetentionPolicy.SOURCE) 153 public @interface SourceState {} 154 155 /** 156 * Creates a {@link PermissionStatsLog#SAFETY_STATE} {@link StatsEvent} with the given 157 * parameters. 158 */ createSafetyStateEvent( @afetyCenterStatus.OverallSeverityLevel int severityLevel, long openIssueCount, long dismissedIssueCount)159 static StatsEvent createSafetyStateEvent( 160 @SafetyCenterStatus.OverallSeverityLevel int severityLevel, 161 long openIssueCount, 162 long dismissedIssueCount) { 163 return PermissionStatsLog.buildStatsEvent( 164 SAFETY_STATE, 165 toSafetyStateOverallSeverityLevel(severityLevel), 166 openIssueCount, 167 dismissedIssueCount); 168 } 169 170 /** Writes a {@link PermissionStatsLog#SAFETY_SOURCE_STATE_COLLECTED} atom. */ writeSafetySourceStateCollected( String sourceId, @ProfileType int profileType, @Nullable @SafetySourceData.SeverityLevel Integer sourceSeverityLevel, long openIssuesCount, long dismissedIssuesCount, long duplicateFilteredOutIssuesCount, @SourceState int sourceState, @Nullable SafetyEvent safetyEvent, @Nullable @SafetyCenterManager.RefreshReason Integer refreshReason, boolean dataChanged, @Nullable @ElapsedRealtimeLong Long lastUpdatedElapsedTimeMillis)171 public static void writeSafetySourceStateCollected( 172 String sourceId, 173 @ProfileType int profileType, 174 @Nullable @SafetySourceData.SeverityLevel Integer sourceSeverityLevel, 175 long openIssuesCount, 176 long dismissedIssuesCount, 177 long duplicateFilteredOutIssuesCount, 178 @SourceState int sourceState, 179 @Nullable SafetyEvent safetyEvent, 180 @Nullable @SafetyCenterManager.RefreshReason Integer refreshReason, 181 boolean dataChanged, 182 @Nullable @ElapsedRealtimeLong Long lastUpdatedElapsedTimeMillis) { 183 if (!SafetyCenterFlags.getAllowStatsdLogging()) { 184 return; 185 } 186 int collectionType = 187 safetyEvent != null 188 ? SAFETY_SOURCE_STATE_COLLECTED__COLLECTION_TYPE__SOURCE_UPDATED 189 : SAFETY_SOURCE_STATE_COLLECTED__COLLECTION_TYPE__AUTOMATIC; 190 PermissionStatsLog.write( 191 SAFETY_SOURCE_STATE_COLLECTED, 192 idStringToLong(sourceId), 193 toSourceStateCollectedProfileType(profileType), 194 toSafetySourceStateCollectedSeverityLevel(sourceSeverityLevel), 195 openIssuesCount, 196 dismissedIssuesCount, 197 duplicateFilteredOutIssuesCount, 198 sourceState, 199 collectionType, 200 toSafetySourceStateCollectedCollectionType(safetyEvent), 201 refreshReason != null ? refreshReason : UNSET_REFRESH_REASON, 202 dataChanged, 203 lastUpdatedElapsedTimeMillis != null 204 ? lastUpdatedElapsedTimeMillis 205 : UNSET_LAST_UPDATED_ELAPSED_TIME_MILLIS); 206 } 207 208 /** 209 * Writes a {@link PermissionStatsLog#SAFETY_CENTER_SYSTEM_EVENT_REPORTED} atom of type {@code 210 * SINGLE_SOURCE_RESCAN} or {@code SINGLE_SOURCE_GET_DATA}. 211 */ writeSourceRefreshSystemEvent( @efreshRequestType int refreshType, String sourceId, @ProfileType int profileType, Duration duration, @SystemEventResult int result, long refreshReason, boolean dataChanged)212 public static void writeSourceRefreshSystemEvent( 213 @RefreshRequestType int refreshType, 214 String sourceId, 215 @ProfileType int profileType, 216 Duration duration, 217 @SystemEventResult int result, 218 long refreshReason, 219 boolean dataChanged) { 220 if (!SafetyCenterFlags.getAllowStatsdLogging()) { 221 return; 222 } 223 PermissionStatsLog.write( 224 SAFETY_CENTER_SYSTEM_EVENT_REPORTED, 225 toSourceRefreshEventType(refreshType), 226 idStringToLong(sourceId), 227 toSystemEventProfileType(profileType), 228 UNSET_ISSUE_TYPE_ID, 229 duration.toMillis(), 230 result, 231 refreshReason, 232 dataChanged); 233 } 234 235 /** 236 * Writes a {@link PermissionStatsLog#SAFETY_CENTER_SYSTEM_EVENT_REPORTED} atom of type {@code 237 * COMPLETE_RESCAN} or {@code COMPLETE_GET_DATA}. 238 */ writeWholeRefreshSystemEvent( @efreshRequestType int refreshType, Duration duration, @SystemEventResult int result, long refreshReason, boolean dataChanged)239 public static void writeWholeRefreshSystemEvent( 240 @RefreshRequestType int refreshType, 241 Duration duration, 242 @SystemEventResult int result, 243 long refreshReason, 244 boolean dataChanged) { 245 if (!SafetyCenterFlags.getAllowStatsdLogging()) { 246 return; 247 } 248 PermissionStatsLog.write( 249 SAFETY_CENTER_SYSTEM_EVENT_REPORTED, 250 toWholeRefreshEventType(refreshType), 251 UNSET_SOURCE_ID, 252 SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN, 253 UNSET_ISSUE_TYPE_ID, 254 duration.toMillis(), 255 result, 256 refreshReason, 257 dataChanged); 258 } 259 260 /** 261 * Writes a {@link PermissionStatsLog#SAFETY_CENTER_SYSTEM_EVENT_REPORTED} atom of type {@code 262 * INLINE_ACTION}. 263 */ writeInlineActionSystemEvent( String sourceId, @ProfileType int profileType, @Nullable String issueTypeId, Duration duration, @SystemEventResult int result)264 public static void writeInlineActionSystemEvent( 265 String sourceId, 266 @ProfileType int profileType, 267 @Nullable String issueTypeId, 268 Duration duration, 269 @SystemEventResult int result) { 270 if (!SafetyCenterFlags.getAllowStatsdLogging()) { 271 return; 272 } 273 PermissionStatsLog.write( 274 SAFETY_CENTER_SYSTEM_EVENT_REPORTED, 275 SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__INLINE_ACTION, 276 idStringToLong(sourceId), 277 toSystemEventProfileType(profileType), 278 issueTypeId == null ? UNSET_ISSUE_TYPE_ID : idStringToLong(issueTypeId), 279 duration.toMillis(), 280 result, 281 UNSET_REFRESH_REASON, 282 UNSET_DATA_CHANGED); 283 } 284 285 /** 286 * Writes a {@link PermissionStatsLog#SAFETY_CENTER_INTERACTION_REPORTED} atom with the action 287 * {@code NOTIFICATION_POSTED}. 288 */ writeNotificationPostedEvent( String sourceId, @ProfileType int profileType, String issueTypeId, @SafetySourceData.SeverityLevel int sourceSeverityLevel)289 public static void writeNotificationPostedEvent( 290 String sourceId, 291 @ProfileType int profileType, 292 String issueTypeId, 293 @SafetySourceData.SeverityLevel int sourceSeverityLevel) { 294 writeNotificationInteractionReportedEvent( 295 SAFETY_CENTER_INTERACTION_REPORTED__ACTION__NOTIFICATION_POSTED, 296 sourceId, 297 profileType, 298 issueTypeId, 299 sourceSeverityLevel); 300 } 301 302 /** 303 * Writes a {@link PermissionStatsLog#SAFETY_CENTER_INTERACTION_REPORTED} atom with the action 304 * {@code NOTIFICATION_DISMISSED}. 305 */ writeNotificationDismissedEvent( String sourceId, @ProfileType int profileType, String issueTypeId, @SafetySourceData.SeverityLevel int sourceSeverityLevel)306 public static void writeNotificationDismissedEvent( 307 String sourceId, 308 @ProfileType int profileType, 309 String issueTypeId, 310 @SafetySourceData.SeverityLevel int sourceSeverityLevel) { 311 writeNotificationInteractionReportedEvent( 312 SAFETY_CENTER_INTERACTION_REPORTED__ACTION__NOTIFICATION_DISMISSED, 313 sourceId, 314 profileType, 315 issueTypeId, 316 sourceSeverityLevel); 317 } 318 319 /** 320 * Writes a {@link PermissionStatsLog#SAFETY_CENTER_INTERACTION_REPORTED} atom with the action 321 * {@code ISSUE_PRIMARY_ACTION_CLICKED} or {@code ISSUE_SECONDARY_ACTION_CLICKED}. 322 */ writeNotificationActionClickedEvent( String sourceId, @ProfileType int profileType, String issueTypeId, @SafetySourceData.SeverityLevel int sourceSeverityLevel, boolean isPrimaryAction)323 public static void writeNotificationActionClickedEvent( 324 String sourceId, 325 @ProfileType int profileType, 326 String issueTypeId, 327 @SafetySourceData.SeverityLevel int sourceSeverityLevel, 328 boolean isPrimaryAction) { 329 int action = 330 isPrimaryAction 331 ? SAFETY_CENTER_INTERACTION_REPORTED__ACTION__ISSUE_PRIMARY_ACTION_CLICKED 332 : SAFETY_CENTER_INTERACTION_REPORTED__ACTION__ISSUE_SECONDARY_ACTION_CLICKED; 333 writeNotificationInteractionReportedEvent( 334 action, sourceId, profileType, issueTypeId, sourceSeverityLevel); 335 } 336 writeNotificationInteractionReportedEvent( int interactionReportedAction, String sourceId, @ProfileType int profileType, String issueTypeId, @SafetySourceData.SeverityLevel int sourceSeverityLevel)337 private static void writeNotificationInteractionReportedEvent( 338 int interactionReportedAction, 339 String sourceId, 340 @ProfileType int profileType, 341 String issueTypeId, 342 @SafetySourceData.SeverityLevel int sourceSeverityLevel) { 343 if (!SafetyCenterFlags.getAllowStatsdLogging()) { 344 return; 345 } 346 PermissionStatsLog.write( 347 SAFETY_CENTER_INTERACTION_REPORTED, 348 UNSET_SESSION_ID, 349 interactionReportedAction, 350 SAFETY_CENTER_INTERACTION_REPORTED__VIEW_TYPE__VIEW_TYPE_NOTIFICATION, 351 SAFETY_CENTER_INTERACTION_REPORTED__NAVIGATION_SOURCE__SOURCE_UNKNOWN, 352 toInteractionReportedSeverityLevel(sourceSeverityLevel), 353 idStringToLong(sourceId), 354 toInteractionReportedProfileType(profileType), 355 idStringToLong(issueTypeId), 356 SAFETY_CENTER_INTERACTION_REPORTED__SENSOR__SENSOR_UNKNOWN, 357 UNSET_SOURCE_GROUP_ID, 358 SAFETY_CENTER_INTERACTION_REPORTED__ISSUE_STATE__ACTIVE); 359 } 360 361 /** 362 * Returns a {@link SystemEventResult} based on whether the given operation was {@code 363 * successful}. 364 */ 365 @SystemEventResult toSystemEventResult(boolean success)366 public static int toSystemEventResult(boolean success) { 367 return success 368 ? SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__SUCCESS 369 : SAFETY_CENTER_SYSTEM_EVENT_REPORTED__RESULT__ERROR; 370 } 371 toSourceRefreshEventType(@efreshRequestType int refreshType)372 private static int toSourceRefreshEventType(@RefreshRequestType int refreshType) { 373 switch (refreshType) { 374 case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA: 375 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__SINGLE_SOURCE_GET_NEW_DATA; 376 case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA: 377 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__SINGLE_SOURCE_RESCAN; 378 } 379 Log.w(TAG, "Unexpected SafetyCenterManager.RefreshRequestType: " + refreshType); 380 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__EVENT_TYPE_UNKNOWN; 381 } 382 toWholeRefreshEventType(@efreshRequestType int refreshType)383 private static int toWholeRefreshEventType(@RefreshRequestType int refreshType) { 384 switch (refreshType) { 385 case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA: 386 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__COMPLETE_GET_NEW_DATA; 387 case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA: 388 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__COMPLETE_RESCAN; 389 } 390 Log.w(TAG, "Unexpected SafetyCenterManager.RefreshRequestType: " + refreshType); 391 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__EVENT_TYPE__EVENT_TYPE_UNKNOWN; 392 } 393 toSourceStateCollectedProfileType(@rofileType int profileType)394 private static int toSourceStateCollectedProfileType(@ProfileType int profileType) { 395 switch (profileType) { 396 case PROFILE_TYPE_PRIMARY: 397 return SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PERSONAL; 398 case PROFILE_TYPE_MANAGED: 399 return SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_MANAGED; 400 case PROFILE_TYPE_PRIVATE: 401 return SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PRIVATE; 402 } 403 Log.w(TAG, "state collect arg requested for unknown profile type " + profileType); 404 return SAFETY_SOURCE_STATE_COLLECTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN; 405 } 406 toSystemEventProfileType(@rofileType int profileType)407 private static int toSystemEventProfileType(@ProfileType int profileType) { 408 switch (profileType) { 409 case PROFILE_TYPE_PRIMARY: 410 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PERSONAL; 411 case PROFILE_TYPE_MANAGED: 412 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_MANAGED; 413 case PROFILE_TYPE_PRIVATE: 414 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PRIVATE; 415 } 416 Log.w(TAG, "system event arg requested for unknown profile type " + profileType); 417 return SAFETY_CENTER_SYSTEM_EVENT_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN; 418 } 419 toInteractionReportedProfileType(@rofileType int profileType)420 private static int toInteractionReportedProfileType(@ProfileType int profileType) { 421 switch (profileType) { 422 case PROFILE_TYPE_PRIMARY: 423 return SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PERSONAL; 424 case PROFILE_TYPE_MANAGED: 425 return SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_MANAGED; 426 case PROFILE_TYPE_PRIVATE: 427 return SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_PRIVATE; 428 } 429 Log.w(TAG, "interaction enum requested for unknown profile type " + profileType); 430 return SAFETY_CENTER_INTERACTION_REPORTED__SAFETY_SOURCE_PROFILE_TYPE__PROFILE_TYPE_UNKNOWN; 431 } 432 433 /** 434 * Converts a {@link String} ID (e.g. a Safety Source ID) to a {@code long} suitable for logging 435 * to statsd. 436 */ idStringToLong(String id)437 private static long idStringToLong(String id) { 438 MessageDigest messageDigest; 439 try { 440 messageDigest = MessageDigest.getInstance("MD5"); 441 } catch (NoSuchAlgorithmException e) { 442 Log.w(TAG, "Couldn't encode safety source id: " + id, e); 443 return 0; 444 } 445 messageDigest.update(id.getBytes()); 446 return new BigInteger(messageDigest.digest()).longValue(); 447 } 448 toSafetyStateOverallSeverityLevel( @afetyCenterStatus.OverallSeverityLevel int severityLevel)449 private static int toSafetyStateOverallSeverityLevel( 450 @SafetyCenterStatus.OverallSeverityLevel int severityLevel) { 451 switch (severityLevel) { 452 case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_UNKNOWN: 453 return SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 454 case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_OK: 455 return SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_OK; 456 case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_RECOMMENDATION: 457 return SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_RECOMMENDATION; 458 case SafetyCenterStatus.OVERALL_SEVERITY_LEVEL_CRITICAL_WARNING: 459 return SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_CRITICAL_WARNING; 460 } 461 Log.w(TAG, "Unexpected SafetyCenterStatus.OverallSeverityLevel: " + severityLevel); 462 return SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 463 } 464 toSafetySourceStateCollectedSeverityLevel( @ullable @afetySourceData.SeverityLevel Integer safetySourceSeverityLevel)465 private static int toSafetySourceStateCollectedSeverityLevel( 466 @Nullable @SafetySourceData.SeverityLevel Integer safetySourceSeverityLevel) { 467 if (safetySourceSeverityLevel == null) { 468 return SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 469 } 470 switch (safetySourceSeverityLevel) { 471 case SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED: 472 return SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_UNSPECIFIED; 473 case SafetySourceData.SEVERITY_LEVEL_INFORMATION: 474 return SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_OK; 475 case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION: 476 return SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_RECOMMENDATION; 477 case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING: 478 return SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_CRITICAL_WARNING; 479 } 480 Log.w(TAG, "Unexpected SafetySourceData.SeverityLevel: " + safetySourceSeverityLevel); 481 return SAFETY_SOURCE_STATE_COLLECTED__SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 482 } 483 toInteractionReportedSeverityLevel( @afetySourceData.SeverityLevel int severityLevel)484 private static int toInteractionReportedSeverityLevel( 485 @SafetySourceData.SeverityLevel int severityLevel) { 486 switch (severityLevel) { 487 case SafetySourceData.SEVERITY_LEVEL_UNSPECIFIED: 488 return SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_UNSPECIFIED; 489 case SafetySourceData.SEVERITY_LEVEL_INFORMATION: 490 return SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_OK; 491 case SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION: 492 return SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_RECOMMENDATION; 493 case SafetySourceData.SEVERITY_LEVEL_CRITICAL_WARNING: 494 return SAFETY_CENTER_INTERACTION_REPORTED__SEVERITY_LEVEL__SAFETY_SEVERITY_CRITICAL_WARNING; 495 } 496 Log.w(TAG, "Unexpected SafetySourceData.SeverityLevel: " + severityLevel); 497 return SAFETY_STATE__OVERALL_SEVERITY_LEVEL__SAFETY_SEVERITY_LEVEL_UNKNOWN; 498 } 499 toSafetySourceStateCollectedCollectionType( @ullable SafetyEvent safetyEvent)500 private static int toSafetySourceStateCollectedCollectionType( 501 @Nullable SafetyEvent safetyEvent) { 502 if (safetyEvent == null) { 503 return SAFETY_SOURCE_STATE_COLLECTED__UPDATE_TYPE__UPDATE_TYPE_UNKNOWN; 504 } 505 if (safetyEvent.getType() == SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED) { 506 return SAFETY_SOURCE_STATE_COLLECTED__UPDATE_TYPE__REFRESH_RESPONSE; 507 } else { 508 return SAFETY_SOURCE_STATE_COLLECTED__UPDATE_TYPE__SELF_INITIATED; 509 } 510 } 511 } 512