1 /* 2 * Copyright (C) 2020 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.intentresolver; 18 19 import android.annotation.Nullable; 20 import android.content.Intent; 21 import android.metrics.LogMaker; 22 import android.net.Uri; 23 import android.provider.MediaStore; 24 import android.util.HashedStringCache; 25 import android.util.Log; 26 27 import com.android.intentresolver.contentpreview.ContentPreviewType; 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.internal.logging.InstanceId; 30 import com.android.internal.logging.InstanceIdSequence; 31 import com.android.internal.logging.MetricsLogger; 32 import com.android.internal.logging.UiEvent; 33 import com.android.internal.logging.UiEventLogger; 34 import com.android.internal.logging.UiEventLoggerImpl; 35 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 36 import com.android.internal.util.FrameworkStatsLog; 37 38 /** 39 * Helper for writing Sharesheet atoms to statsd log. 40 * @hide 41 */ 42 public class ChooserActivityLogger { 43 private static final String TAG = "ChooserActivity"; 44 private static final boolean DEBUG = true; 45 46 public static final int SELECTION_TYPE_SERVICE = 1; 47 public static final int SELECTION_TYPE_APP = 2; 48 public static final int SELECTION_TYPE_STANDARD = 3; 49 public static final int SELECTION_TYPE_COPY = 4; 50 public static final int SELECTION_TYPE_NEARBY = 5; 51 public static final int SELECTION_TYPE_EDIT = 6; 52 public static final int SELECTION_TYPE_MODIFY_SHARE = 7; 53 public static final int SELECTION_TYPE_CUSTOM_ACTION = 8; 54 55 /** 56 * This shim is provided only for testing. In production, clients will only ever use a 57 * {@link DefaultFrameworkStatsLogger}. 58 */ 59 @VisibleForTesting 60 interface FrameworkStatsLogger { 61 /** Overload to use for logging {@code FrameworkStatsLog.SHARESHEET_STARTED}. */ write( int frameworkEventId, int appEventId, String packageName, int instanceId, String mimeType, int numAppProvidedDirectTargets, int numAppProvidedAppTargets, boolean isWorkProfile, int previewType, int intentType, int numCustomActions, boolean modifyShareActionProvided)62 void write( 63 int frameworkEventId, 64 int appEventId, 65 String packageName, 66 int instanceId, 67 String mimeType, 68 int numAppProvidedDirectTargets, 69 int numAppProvidedAppTargets, 70 boolean isWorkProfile, 71 int previewType, 72 int intentType, 73 int numCustomActions, 74 boolean modifyShareActionProvided); 75 76 /** Overload to use for logging {@code FrameworkStatsLog.RANKING_SELECTED}. */ write( int frameworkEventId, int appEventId, String packageName, int instanceId, int positionPicked, boolean isPinned)77 void write( 78 int frameworkEventId, 79 int appEventId, 80 String packageName, 81 int instanceId, 82 int positionPicked, 83 boolean isPinned); 84 } 85 86 private static final int SHARESHEET_INSTANCE_ID_MAX = (1 << 13); 87 88 // A small per-notification ID, used for statsd logging. 89 // TODO: consider precomputing and storing as final. 90 private static InstanceIdSequence sInstanceIdSequence; 91 private InstanceId mInstanceId; 92 93 private final UiEventLogger mUiEventLogger; 94 private final FrameworkStatsLogger mFrameworkStatsLogger; 95 private final MetricsLogger mMetricsLogger; 96 ChooserActivityLogger()97 public ChooserActivityLogger() { 98 this(new UiEventLoggerImpl(), new DefaultFrameworkStatsLogger(), new MetricsLogger()); 99 } 100 101 @VisibleForTesting ChooserActivityLogger( UiEventLogger uiEventLogger, FrameworkStatsLogger frameworkLogger, MetricsLogger metricsLogger)102 ChooserActivityLogger( 103 UiEventLogger uiEventLogger, 104 FrameworkStatsLogger frameworkLogger, 105 MetricsLogger metricsLogger) { 106 mUiEventLogger = uiEventLogger; 107 mFrameworkStatsLogger = frameworkLogger; 108 mMetricsLogger = metricsLogger; 109 } 110 111 /** Records metrics for the start time of the {@link ChooserActivity}. */ logChooserActivityShown( boolean isWorkProfile, String targetMimeType, long systemCost)112 public void logChooserActivityShown( 113 boolean isWorkProfile, String targetMimeType, long systemCost) { 114 mMetricsLogger.write(new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN) 115 .setSubtype( 116 isWorkProfile ? MetricsEvent.MANAGED_PROFILE : MetricsEvent.PARENT_PROFILE) 117 .addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, targetMimeType) 118 .addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost)); 119 } 120 121 /** Logs a UiEventReported event for the system sharesheet completing initial start-up. */ logShareStarted( String packageName, String mimeType, int appProvidedDirect, int appProvidedApp, boolean isWorkprofile, int previewType, String intent, int customActionCount, boolean modifyShareActionProvided)122 public void logShareStarted( 123 String packageName, 124 String mimeType, 125 int appProvidedDirect, 126 int appProvidedApp, 127 boolean isWorkprofile, 128 int previewType, 129 String intent, 130 int customActionCount, 131 boolean modifyShareActionProvided) { 132 mFrameworkStatsLogger.write(FrameworkStatsLog.SHARESHEET_STARTED, 133 /* event_id = 1 */ SharesheetStartedEvent.SHARE_STARTED.getId(), 134 /* package_name = 2 */ packageName, 135 /* instance_id = 3 */ getInstanceId().getId(), 136 /* mime_type = 4 */ mimeType, 137 /* num_app_provided_direct_targets = 5 */ appProvidedDirect, 138 /* num_app_provided_app_targets = 6 */ appProvidedApp, 139 /* is_workprofile = 7 */ isWorkprofile, 140 /* previewType = 8 */ typeFromPreviewInt(previewType), 141 /* intentType = 9 */ typeFromIntentString(intent), 142 /* num_provided_custom_actions = 10 */ customActionCount, 143 /* modify_share_action_provided = 11 */ modifyShareActionProvided); 144 } 145 146 /** 147 * Log that a custom action has been tapped by the user. 148 * 149 * @param positionPicked index of the custom action within the list of custom actions. 150 */ logCustomActionSelected(int positionPicked)151 public void logCustomActionSelected(int positionPicked) { 152 mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, 153 /* event_id = 1 */ 154 SharesheetTargetSelectedEvent.SHARESHEET_CUSTOM_ACTION_SELECTED.getId(), 155 /* package_name = 2 */ null, 156 /* instance_id = 3 */ getInstanceId().getId(), 157 /* position_picked = 4 */ positionPicked, 158 /* is_pinned = 5 */ false); 159 } 160 161 /** 162 * Logs a UiEventReported event for the system sharesheet when the user selects a target. 163 * TODO: document parameters and/or consider breaking up by targetType so we don't have to 164 * support an overly-generic signature. 165 */ logShareTargetSelected( int targetType, String packageName, int positionPicked, int directTargetAlsoRanked, int numCallerProvided, @Nullable HashedStringCache.HashResult directTargetHashed, boolean isPinned, boolean successfullySelected, long selectionCost)166 public void logShareTargetSelected( 167 int targetType, 168 String packageName, 169 int positionPicked, 170 int directTargetAlsoRanked, 171 int numCallerProvided, 172 @Nullable HashedStringCache.HashResult directTargetHashed, 173 boolean isPinned, 174 boolean successfullySelected, 175 long selectionCost) { 176 mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, 177 /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), 178 /* package_name = 2 */ packageName, 179 /* instance_id = 3 */ getInstanceId().getId(), 180 /* position_picked = 4 */ positionPicked, 181 /* is_pinned = 5 */ isPinned); 182 183 int category = getTargetSelectionCategory(targetType); 184 if (category != 0) { 185 LogMaker targetLogMaker = new LogMaker(category).setSubtype(positionPicked); 186 if (directTargetHashed != null) { 187 targetLogMaker.addTaggedData( 188 MetricsEvent.FIELD_HASHED_TARGET_NAME, directTargetHashed.hashedString); 189 targetLogMaker.addTaggedData( 190 MetricsEvent.FIELD_HASHED_TARGET_SALT_GEN, 191 directTargetHashed.saltGeneration); 192 targetLogMaker.addTaggedData(MetricsEvent.FIELD_RANKED_POSITION, 193 directTargetAlsoRanked); 194 } 195 targetLogMaker.addTaggedData(MetricsEvent.FIELD_IS_CATEGORY_USED, numCallerProvided); 196 mMetricsLogger.write(targetLogMaker); 197 } 198 199 if (successfullySelected) { 200 if (DEBUG) { 201 Log.d(TAG, "User Selection Time Cost is " + selectionCost); 202 Log.d(TAG, "position of selected app/service/caller is " + positionPicked); 203 } 204 MetricsLogger.histogram( 205 null, "user_selection_cost_for_smart_sharing", (int) selectionCost); 206 MetricsLogger.histogram(null, "app_position_for_smart_sharing", positionPicked); 207 } 208 } 209 210 /** Log when direct share targets were received. */ logDirectShareTargetReceived(int category, int latency)211 public void logDirectShareTargetReceived(int category, int latency) { 212 mMetricsLogger.write(new LogMaker(category).setSubtype(latency)); 213 } 214 215 /** 216 * Log when we display a preview UI of the specified {@code previewType} as part of our 217 * Sharesheet session. 218 */ logActionShareWithPreview(int previewType)219 public void logActionShareWithPreview(int previewType) { 220 mMetricsLogger.write( 221 new LogMaker(MetricsEvent.ACTION_SHARE_WITH_PREVIEW).setSubtype(previewType)); 222 } 223 224 /** Log when the user selects an action button with the specified {@code targetType}. */ logActionSelected(int targetType)225 public void logActionSelected(int targetType) { 226 if (targetType == SELECTION_TYPE_COPY) { 227 LogMaker targetLogMaker = new LogMaker( 228 MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SYSTEM_TARGET).setSubtype(1); 229 mMetricsLogger.write(targetLogMaker); 230 } 231 mFrameworkStatsLogger.write(FrameworkStatsLog.RANKING_SELECTED, 232 /* event_id = 1 */ SharesheetTargetSelectedEvent.fromTargetType(targetType).getId(), 233 /* package_name = 2 */ "", 234 /* instance_id = 3 */ getInstanceId().getId(), 235 /* position_picked = 4 */ -1, 236 /* is_pinned = 5 */ false); 237 } 238 239 /** Log a warning that we couldn't display the content preview from the supplied {@code uri}. */ logContentPreviewWarning(Uri uri)240 public void logContentPreviewWarning(Uri uri) { 241 // The ContentResolver already logs the exception. Log something more informative. 242 Log.w(TAG, "Could not load (" + uri.toString() + ") thumbnail/name for preview. If " 243 + "desired, consider using Intent#createChooser to launch the ChooserActivity, " 244 + "and set your Intent's clipData and flags in accordance with that method's " 245 + "documentation"); 246 247 } 248 249 /** Logs a UiEventReported event for the system sharesheet being triggered by the user. */ logSharesheetTriggered()250 public void logSharesheetTriggered() { 251 log(SharesheetStandardEvent.SHARESHEET_TRIGGERED, getInstanceId()); 252 } 253 254 /** Logs a UiEventReported event for the system sharesheet completing loading app targets. */ logSharesheetAppLoadComplete()255 public void logSharesheetAppLoadComplete() { 256 log(SharesheetStandardEvent.SHARESHEET_APP_LOAD_COMPLETE, getInstanceId()); 257 } 258 259 /** 260 * Logs a UiEventReported event for the system sharesheet completing loading service targets. 261 */ logSharesheetDirectLoadComplete()262 public void logSharesheetDirectLoadComplete() { 263 log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_COMPLETE, getInstanceId()); 264 } 265 266 /** 267 * Logs a UiEventReported event for the system sharesheet timing out loading service targets. 268 */ logSharesheetDirectLoadTimeout()269 public void logSharesheetDirectLoadTimeout() { 270 log(SharesheetStandardEvent.SHARESHEET_DIRECT_LOAD_TIMEOUT, getInstanceId()); 271 } 272 273 /** 274 * Logs a UiEventReported event for the system sharesheet switching 275 * between work and main profile. 276 */ logSharesheetProfileChanged()277 public void logSharesheetProfileChanged() { 278 log(SharesheetStandardEvent.SHARESHEET_PROFILE_CHANGED, getInstanceId()); 279 } 280 281 /** Logs a UiEventReported event for the system sharesheet getting expanded or collapsed. */ logSharesheetExpansionChanged(boolean isCollapsed)282 public void logSharesheetExpansionChanged(boolean isCollapsed) { 283 log(isCollapsed ? SharesheetStandardEvent.SHARESHEET_COLLAPSED : 284 SharesheetStandardEvent.SHARESHEET_EXPANDED, getInstanceId()); 285 } 286 287 /** 288 * Logs a UiEventReported event for the system sharesheet app share ranking timing out. 289 */ logSharesheetAppShareRankingTimeout()290 public void logSharesheetAppShareRankingTimeout() { 291 log(SharesheetStandardEvent.SHARESHEET_APP_SHARE_RANKING_TIMEOUT, getInstanceId()); 292 } 293 294 /** 295 * Logs a UiEventReported event for the system sharesheet when direct share row is empty. 296 */ logSharesheetEmptyDirectShareRow()297 public void logSharesheetEmptyDirectShareRow() { 298 log(SharesheetStandardEvent.SHARESHEET_EMPTY_DIRECT_SHARE_ROW, getInstanceId()); 299 } 300 301 /** 302 * Logs a UiEventReported event for a given share activity 303 * @param event 304 * @param instanceId 305 */ log(UiEventLogger.UiEventEnum event, InstanceId instanceId)306 private void log(UiEventLogger.UiEventEnum event, InstanceId instanceId) { 307 mUiEventLogger.logWithInstanceId( 308 event, 309 0, 310 null, 311 instanceId); 312 } 313 314 /** 315 * @return A unique {@link InstanceId} to join across events recorded by this logger instance. 316 */ getInstanceId()317 private InstanceId getInstanceId() { 318 if (mInstanceId == null) { 319 if (sInstanceIdSequence == null) { 320 sInstanceIdSequence = new InstanceIdSequence(SHARESHEET_INSTANCE_ID_MAX); 321 } 322 mInstanceId = sInstanceIdSequence.newInstanceId(); 323 } 324 return mInstanceId; 325 } 326 327 /** 328 * The UiEvent enums that this class can log. 329 */ 330 enum SharesheetStartedEvent implements UiEventLogger.UiEventEnum { 331 @UiEvent(doc = "Basic system Sharesheet has started and is visible.") 332 SHARE_STARTED(228); 333 334 private final int mId; SharesheetStartedEvent(int id)335 SharesheetStartedEvent(int id) { 336 mId = id; 337 } 338 @Override getId()339 public int getId() { 340 return mId; 341 } 342 } 343 344 /** 345 * The UiEvent enums that this class can log. 346 */ 347 enum SharesheetTargetSelectedEvent implements UiEventLogger.UiEventEnum { 348 INVALID(0), 349 @UiEvent(doc = "User selected a service target.") 350 SHARESHEET_SERVICE_TARGET_SELECTED(232), 351 @UiEvent(doc = "User selected an app target.") 352 SHARESHEET_APP_TARGET_SELECTED(233), 353 @UiEvent(doc = "User selected a standard target.") 354 SHARESHEET_STANDARD_TARGET_SELECTED(234), 355 @UiEvent(doc = "User selected the copy target.") 356 SHARESHEET_COPY_TARGET_SELECTED(235), 357 @UiEvent(doc = "User selected the nearby target.") 358 SHARESHEET_NEARBY_TARGET_SELECTED(626), 359 @UiEvent(doc = "User selected the edit target.") 360 SHARESHEET_EDIT_TARGET_SELECTED(669), 361 @UiEvent(doc = "User selected the modify share target.") 362 SHARESHEET_MODIFY_SHARE_SELECTED(1316), 363 @UiEvent(doc = "User selected a custom action.") 364 SHARESHEET_CUSTOM_ACTION_SELECTED(1317); 365 366 private final int mId; SharesheetTargetSelectedEvent(int id)367 SharesheetTargetSelectedEvent(int id) { 368 mId = id; 369 } getId()370 @Override public int getId() { 371 return mId; 372 } 373 fromTargetType(int targetType)374 public static SharesheetTargetSelectedEvent fromTargetType(int targetType) { 375 switch(targetType) { 376 case SELECTION_TYPE_SERVICE: 377 return SHARESHEET_SERVICE_TARGET_SELECTED; 378 case SELECTION_TYPE_APP: 379 return SHARESHEET_APP_TARGET_SELECTED; 380 case SELECTION_TYPE_STANDARD: 381 return SHARESHEET_STANDARD_TARGET_SELECTED; 382 case SELECTION_TYPE_COPY: 383 return SHARESHEET_COPY_TARGET_SELECTED; 384 case SELECTION_TYPE_NEARBY: 385 return SHARESHEET_NEARBY_TARGET_SELECTED; 386 case SELECTION_TYPE_EDIT: 387 return SHARESHEET_EDIT_TARGET_SELECTED; 388 case SELECTION_TYPE_MODIFY_SHARE: 389 return SHARESHEET_MODIFY_SHARE_SELECTED; 390 case SELECTION_TYPE_CUSTOM_ACTION: 391 return SHARESHEET_CUSTOM_ACTION_SELECTED; 392 default: 393 return INVALID; 394 } 395 } 396 } 397 398 /** 399 * The UiEvent enums that this class can log. 400 */ 401 enum SharesheetStandardEvent implements UiEventLogger.UiEventEnum { 402 INVALID(0), 403 @UiEvent(doc = "User clicked share.") 404 SHARESHEET_TRIGGERED(227), 405 @UiEvent(doc = "User changed from work to personal profile or vice versa.") 406 SHARESHEET_PROFILE_CHANGED(229), 407 @UiEvent(doc = "User expanded target list.") 408 SHARESHEET_EXPANDED(230), 409 @UiEvent(doc = "User collapsed target list.") 410 SHARESHEET_COLLAPSED(231), 411 @UiEvent(doc = "Sharesheet app targets is fully populated.") 412 SHARESHEET_APP_LOAD_COMPLETE(322), 413 @UiEvent(doc = "Sharesheet direct targets is fully populated.") 414 SHARESHEET_DIRECT_LOAD_COMPLETE(323), 415 @UiEvent(doc = "Sharesheet direct targets timed out.") 416 SHARESHEET_DIRECT_LOAD_TIMEOUT(324), 417 @UiEvent(doc = "Sharesheet app share ranking timed out.") 418 SHARESHEET_APP_SHARE_RANKING_TIMEOUT(831), 419 @UiEvent(doc = "Sharesheet empty direct share row.") 420 SHARESHEET_EMPTY_DIRECT_SHARE_ROW(828); 421 422 private final int mId; SharesheetStandardEvent(int id)423 SharesheetStandardEvent(int id) { 424 mId = id; 425 } getId()426 @Override public int getId() { 427 return mId; 428 } 429 } 430 431 /** 432 * Returns the enum used in sharesheet started atom to indicate what preview type was used. 433 */ typeFromPreviewInt(int previewType)434 private static int typeFromPreviewInt(int previewType) { 435 switch(previewType) { 436 case ContentPreviewType.CONTENT_PREVIEW_IMAGE: 437 return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_IMAGE; 438 case ContentPreviewType.CONTENT_PREVIEW_FILE: 439 return FrameworkStatsLog.SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_FILE; 440 case ContentPreviewType.CONTENT_PREVIEW_TEXT: 441 default: 442 return FrameworkStatsLog 443 .SHARESHEET_STARTED__PREVIEW_TYPE__CONTENT_PREVIEW_TYPE_UNKNOWN; 444 } 445 } 446 447 /** 448 * Returns the enum used in sharesheet started atom to indicate what intent triggers the 449 * ChooserActivity. 450 */ typeFromIntentString(String intent)451 private static int typeFromIntentString(String intent) { 452 if (intent == null) { 453 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; 454 } 455 switch (intent) { 456 case Intent.ACTION_VIEW: 457 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_VIEW; 458 case Intent.ACTION_EDIT: 459 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_EDIT; 460 case Intent.ACTION_SEND: 461 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND; 462 case Intent.ACTION_SENDTO: 463 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SENDTO; 464 case Intent.ACTION_SEND_MULTIPLE: 465 return FrameworkStatsLog 466 .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_SEND_MULTIPLE; 467 case MediaStore.ACTION_IMAGE_CAPTURE: 468 return FrameworkStatsLog 469 .SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_IMAGE_CAPTURE; 470 case Intent.ACTION_MAIN: 471 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_ACTION_MAIN; 472 default: 473 return FrameworkStatsLog.SHARESHEET_STARTED__INTENT_TYPE__INTENT_DEFAULT; 474 } 475 } 476 477 @VisibleForTesting getTargetSelectionCategory(int targetType)478 static int getTargetSelectionCategory(int targetType) { 479 switch (targetType) { 480 case SELECTION_TYPE_SERVICE: 481 return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET; 482 case SELECTION_TYPE_APP: 483 return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET; 484 case SELECTION_TYPE_STANDARD: 485 return MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET; 486 default: 487 return 0; 488 } 489 } 490 491 private static class DefaultFrameworkStatsLogger implements FrameworkStatsLogger { 492 @Override write( int frameworkEventId, int appEventId, String packageName, int instanceId, String mimeType, int numAppProvidedDirectTargets, int numAppProvidedAppTargets, boolean isWorkProfile, int previewType, int intentType, int numCustomActions, boolean modifyShareActionProvided)493 public void write( 494 int frameworkEventId, 495 int appEventId, 496 String packageName, 497 int instanceId, 498 String mimeType, 499 int numAppProvidedDirectTargets, 500 int numAppProvidedAppTargets, 501 boolean isWorkProfile, 502 int previewType, 503 int intentType, 504 int numCustomActions, 505 boolean modifyShareActionProvided) { 506 FrameworkStatsLog.write( 507 frameworkEventId, 508 /* event_id = 1 */ appEventId, 509 /* package_name = 2 */ packageName, 510 /* instance_id = 3 */ instanceId, 511 /* mime_type = 4 */ mimeType, 512 /* num_app_provided_direct_targets */ numAppProvidedDirectTargets, 513 /* num_app_provided_app_targets */ numAppProvidedAppTargets, 514 /* is_workprofile */ isWorkProfile, 515 /* previewType = 8 */ previewType, 516 /* intentType = 9 */ intentType, 517 /* num_provided_custom_actions = 10 */ numCustomActions, 518 /* modify_share_action_provided = 11 */ modifyShareActionProvided); 519 } 520 521 @Override write( int frameworkEventId, int appEventId, String packageName, int instanceId, int positionPicked, boolean isPinned)522 public void write( 523 int frameworkEventId, 524 int appEventId, 525 String packageName, 526 int instanceId, 527 int positionPicked, 528 boolean isPinned) { 529 FrameworkStatsLog.write( 530 frameworkEventId, 531 /* event_id = 1 */ appEventId, 532 /* package_name = 2 */ packageName, 533 /* instance_id = 3 */ instanceId, 534 /* position_picked = 4 */ positionPicked, 535 /* is_pinned = 5 */ isPinned); 536 } 537 } 538 } 539