blob: 699605f5cdcb89dec71ffc29bbc7b19dffa94ae3 [file] [log] [blame]
Ben Kwa72379982016-01-26 11:50:03 -08001/*
2 * Copyright (C) 2016 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
17package com.android.documentsui;
18
19import static com.android.documentsui.Shared.DEBUG;
Ben Kwad5b2af12016-01-28 16:39:57 -080020import static com.android.internal.util.Preconditions.checkArgument;
Ben Kwa72379982016-01-26 11:50:03 -080021
Ben Kwad5b2af12016-01-28 16:39:57 -080022import android.annotation.IntDef;
23import android.annotation.Nullable;
Ben Kwa72379982016-01-26 11:50:03 -080024import android.content.Context;
25import android.content.Intent;
26import android.content.pm.ResolveInfo;
27import android.net.Uri;
28import android.provider.DocumentsContract;
29import android.util.Log;
30
Ben Kwad5b2af12016-01-28 16:39:57 -080031import com.android.documentsui.model.DocumentInfo;
Ben Kwa72379982016-01-26 11:50:03 -080032import com.android.documentsui.model.RootInfo;
Ben Kwad5b2af12016-01-28 16:39:57 -080033import com.android.documentsui.services.FileOperationService;
34import com.android.documentsui.services.FileOperationService.OpType;
Ben Kwa72379982016-01-26 11:50:03 -080035import com.android.internal.logging.MetricsLogger;
36
Ben Kwad5b2af12016-01-28 16:39:57 -080037import java.lang.annotation.Retention;
38import java.lang.annotation.RetentionPolicy;
39import java.util.List;
40
Ben Kwa72379982016-01-26 11:50:03 -080041/** @hide */
42public final class Metrics {
43 private static final String TAG = "Metrics";
44
45 // These are the native provider authorities that the metrics code is capable of recognizing and
46 // explicitly counting.
47 private static final String AUTHORITY_MEDIA = "com.android.providers.media.documents";
48 private static final String AUTHORITY_STORAGE = "com.android.externalstorage.documents";
49 private static final String AUTHORITY_DOWNLOADS = "com.android.providers.downloads.documents";
Ben Kwada518c92016-01-28 18:15:07 -080050 private static final String AUTHORITY_MTP = "com.android.mtp.documents";
Ben Kwa72379982016-01-26 11:50:03 -080051
52 // These strings have to be whitelisted in tron. Do not change them.
53 private static final String COUNT_LAUNCH_ACTION = "docsui_launch_action";
54 private static final String COUNT_ROOT_VISITED = "docsui_root_visited";
55 private static final String COUNT_OPEN_MIME = "docsui_open_mime";
56 private static final String COUNT_CREATE_MIME = "docsui_create_mime";
57 private static final String COUNT_GET_CONTENT_MIME = "docsui_get_content_mime";
58 private static final String COUNT_BROWSE_ROOT = "docsui_browse_root";
59 private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
60 private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
Ben Kwad5b2af12016-01-28 16:39:57 -080061 private static final String COUNT_FILEOP_SYSTEM = "docsui_fileop_system";
62 private static final String COUNT_FILEOP_EXTERNAL = "docsui_fileop_external";
63 private static final String COUNT_FILEOP_CANCELED = "docsui_fileop_canceled";
Ben Kwa72379982016-01-26 11:50:03 -080064
65 // Indices for bucketing roots in the roots histogram. "Other" is the catch-all index for any
66 // root that is not explicitly recognized by the Metrics code (see {@link
Ben Kwaa87e9f92016-02-17 16:06:22 -080067 // #getSanitizedRootIndex}). Apps are also bucketed in this histogram.
Ben Kwada518c92016-01-28 18:15:07 -080068 // Do not change or rearrange these values, that will break historical data. Only add to the end
69 // of the list.
Ben Kwaa87e9f92016-02-17 16:06:22 -080070 // Do not use negative numbers or zero; clearcut only handles positive integers.
71 private static final int ROOT_NONE = 1;
72 private static final int ROOT_OTHER = 2;
73 private static final int ROOT_AUDIO = 3;
74 private static final int ROOT_DEVICE_STORAGE = 4;
75 private static final int ROOT_DOWNLOADS = 5;
76 private static final int ROOT_HOME = 6;
77 private static final int ROOT_IMAGES = 7;
78 private static final int ROOT_RECENTS = 8;
79 private static final int ROOT_VIDEOS = 9;
80 private static final int ROOT_MTP = 10;
Ben Kwa72379982016-01-26 11:50:03 -080081 // Apps aren't really "roots", but they are treated as such in the roots fragment UI and so they
Ben Kwaa87e9f92016-02-17 16:06:22 -080082 // are logged analogously to roots.
83 private static final int ROOT_THIRD_PARTY_APP = 100;
Ben Kwa72379982016-01-26 11:50:03 -080084
Ben Kwad5b2af12016-01-28 16:39:57 -080085 @IntDef(flag = true, value = {
86 ROOT_NONE,
87 ROOT_OTHER,
88 ROOT_AUDIO,
89 ROOT_DEVICE_STORAGE,
90 ROOT_DOWNLOADS,
91 ROOT_HOME,
92 ROOT_IMAGES,
93 ROOT_RECENTS,
94 ROOT_VIDEOS,
Ben Kwada518c92016-01-28 18:15:07 -080095 ROOT_MTP,
Ben Kwad5b2af12016-01-28 16:39:57 -080096 ROOT_THIRD_PARTY_APP
97 })
98 @Retention(RetentionPolicy.SOURCE)
99 public @interface Root {}
100
Ben Kwa72379982016-01-26 11:50:03 -0800101 // Indices for bucketing mime types.
Ben Kwaa87e9f92016-02-17 16:06:22 -0800102 // Do not change or rearrange these values, that will break historical data. Only add to the end
103 // of the list.
104 // Do not use negative numbers or zero; clearcut only handles positive integers.
105 private static final int MIME_NONE = 1; // null mime
106 private static final int MIME_ANY = 2; // */*
107 private static final int MIME_APPLICATION = 3; // application/*
108 private static final int MIME_AUDIO = 4; // audio/*
109 private static final int MIME_IMAGE = 5; // image/*
110 private static final int MIME_MESSAGE = 6; // message/*
111 private static final int MIME_MULTIPART = 7; // multipart/*
112 private static final int MIME_TEXT = 8; // text/*
113 private static final int MIME_VIDEO = 9; // video/*
114 private static final int MIME_OTHER = 10; // anything not enumerated below
Ben Kwa72379982016-01-26 11:50:03 -0800115
Ben Kwad5b2af12016-01-28 16:39:57 -0800116 @IntDef(flag = true, value = {
Ben Kwad5b2af12016-01-28 16:39:57 -0800117 MIME_NONE,
118 MIME_ANY,
119 MIME_APPLICATION,
120 MIME_AUDIO,
121 MIME_IMAGE,
122 MIME_MESSAGE,
123 MIME_MULTIPART,
124 MIME_TEXT,
Ben Kwaa87e9f92016-02-17 16:06:22 -0800125 MIME_VIDEO,
126 MIME_OTHER
Ben Kwad5b2af12016-01-28 16:39:57 -0800127 })
128 @Retention(RetentionPolicy.SOURCE)
129 public @interface Mime {}
130
131 // Codes representing different kinds of file operations. These are used for bucketing
132 // operations in the COUNT_FILEOP_{SYSTEM|EXTERNAL} histograms.
Ben Kwaa87e9f92016-02-17 16:06:22 -0800133 // Do not change or rearrange these values, that will break historical data. Only add to the
134 // list.
135 // Do not use negative numbers or zero; clearcut only handles positive integers.
136 private static final int FILEOP_OTHER = 1; // any file operation not listed below
137 private static final int FILEOP_COPY_INTRA_PROVIDER = 2; // Copy within a provider
138 private static final int FILEOP_COPY_SYSTEM_PROVIDER = 3; // Copy to a system provider.
139 private static final int FILEOP_COPY_EXTERNAL_PROVIDER = 4; // Copy to a 3rd-party provider.
140 private static final int FILEOP_MOVE_INTRA_PROVIDER = 5; // Move within a provider.
141 private static final int FILEOP_MOVE_SYSTEM_PROVIDER = 6; // Move to a system provider.
142 private static final int FILEOP_MOVE_EXTERNAL_PROVIDER = 7; // Move to a 3rd-party provider.
143 private static final int FILEOP_DELETE = 8;
144 private static final int FILEOP_OTHER_ERROR = 100;
145 private static final int FILEOP_DELETE_ERROR = 101;
146 private static final int FILEOP_MOVE_ERROR = 102;
147 private static final int FILEOP_COPY_ERROR = 103;
Ben Kwad5b2af12016-01-28 16:39:57 -0800148
149 @IntDef(flag = true, value = {
150 FILEOP_OTHER,
151 FILEOP_COPY_INTRA_PROVIDER,
152 FILEOP_COPY_SYSTEM_PROVIDER,
153 FILEOP_COPY_EXTERNAL_PROVIDER,
154 FILEOP_MOVE_INTRA_PROVIDER,
155 FILEOP_MOVE_SYSTEM_PROVIDER,
156 FILEOP_MOVE_EXTERNAL_PROVIDER,
157 FILEOP_DELETE,
158 FILEOP_OTHER_ERROR,
159 FILEOP_COPY_ERROR,
160 FILEOP_MOVE_ERROR,
161 FILEOP_DELETE_ERROR
162 })
163 @Retention(RetentionPolicy.SOURCE)
164 public @interface FileOp {}
165
Ben Kwaa87e9f92016-02-17 16:06:22 -0800166 // Codes representing different kinds of file operations. These are used for bucketing
167 // operations in the COUNT_FILEOP_CANCELED histogram.
168 // Do not change or rearrange these values, that will break historical data. Only add to the
169 // list.
170 // Do not use negative numbers or zero; clearcut only handles positive integers.
171 private static final int OPERATION_UNKNOWN = 1;
172 private static final int OPERATION_COPY = 2;
173 private static final int OPERATION_MOVE = 3;
174 private static final int OPERATION_DELETE= 4;
175
176 @IntDef(flag = true, value = {
177 OPERATION_UNKNOWN,
178 OPERATION_COPY,
179 OPERATION_MOVE,
180 OPERATION_DELETE
181 })
182 @Retention(RetentionPolicy.SOURCE)
183 public @interface MetricsOpType {}
184
185 // Codes representing different launch actions. These are used for bucketing stats in the
186 // COUNT_LAUNCH_ACTION histogram.
187 // Do not change or rearrange these values, that will break historical data. Only add to the
188 // list.
189 // Do not use negative numbers or zero; clearcut only handles positive integers.
190 private static final int ACTION_OTHER = 1;
191 private static final int ACTION_OPEN = 2;
192 private static final int ACTION_CREATE = 3;
193 private static final int ACTION_GET_CONTENT = 4;
194 private static final int ACTION_OPEN_TREE = 5;
195 private static final int ACTION_MANAGE = 6;
196 private static final int ACTION_BROWSE = 7;
197 private static final int ACTION_PICK_COPY_DESTINATION = 8;
198
199 @IntDef(flag = true, value = {
200 ACTION_OTHER,
201 ACTION_OPEN,
202 ACTION_CREATE,
203 ACTION_GET_CONTENT,
204 ACTION_OPEN_TREE,
205 ACTION_MANAGE,
206 ACTION_BROWSE,
207 ACTION_PICK_COPY_DESTINATION
208 })
209 @Retention(RetentionPolicy.SOURCE)
210 public @interface MetricsAction {}
211
Ben Kwad5b2af12016-01-28 16:39:57 -0800212 // Codes representing different provider types. Used for sorting file operations when logging.
213 private static final int PROVIDER_INTRA = 0;
214 private static final int PROVIDER_SYSTEM = 1;
215 private static final int PROVIDER_EXTERNAL = 2;
216
217 @IntDef(flag = true, value = {
218 PROVIDER_INTRA,
219 PROVIDER_SYSTEM,
220 PROVIDER_EXTERNAL
221 })
222 @Retention(RetentionPolicy.SOURCE)
223 public @interface Provider {}
224
Ben Kwa72379982016-01-26 11:50:03 -0800225 /**
226 * Logs when DocumentsUI is started, and how. Call this when DocumentsUI first starts up.
227 *
228 * @param context
229 * @param state
230 * @param intent
231 */
232 public static void logActivityLaunch(Context context, State state, Intent intent) {
233 // Log the launch action.
Ben Kwaa87e9f92016-02-17 16:06:22 -0800234 logHistogram(context, COUNT_LAUNCH_ACTION, toMetricsAction(state.action));
Ben Kwa72379982016-01-26 11:50:03 -0800235 // Then log auxiliary data (roots/mime types) associated with some actions.
236 Uri uri = intent.getData();
237 switch (state.action) {
238 case State.ACTION_OPEN:
239 logHistogram(context, COUNT_OPEN_MIME, sanitizeMime(intent.getType()));
240 break;
241 case State.ACTION_CREATE:
242 logHistogram(context, COUNT_CREATE_MIME, sanitizeMime(intent.getType()));
243 break;
244 case State.ACTION_GET_CONTENT:
245 logHistogram(context, COUNT_GET_CONTENT_MIME, sanitizeMime(intent.getType()));
246 break;
247 case State.ACTION_MANAGE:
248 logHistogram(context, COUNT_MANAGE_ROOT, sanitizeRoot(uri));
249 break;
250 case State.ACTION_BROWSE:
251 logHistogram(context, COUNT_BROWSE_ROOT, sanitizeRoot(uri));
252 break;
253 default:
254 break;
255 }
256 }
257
258 /**
259 * Logs a root visited event. Call this when the user clicks on a root in the RootsFragment.
260 *
261 * @param context
262 * @param info
263 */
264 public static void logRootVisited(Context context, RootInfo info) {
265 logHistogram(context, COUNT_ROOT_VISITED, sanitizeRoot(info));
266 }
267
268 /**
269 * Logs an app visited event. Call this when the user clicks on an app in the RootsFragment.
270 *
271 * @param context
272 * @param info
273 */
274 public static void logAppVisited(Context context, ResolveInfo info) {
275 logHistogram(context, COUNT_ROOT_VISITED, sanitizeRoot(info));
276 }
277
278 /**
279 * Logs a multi-window start. Call this when the user spawns a new DocumentsUI window.
280 *
281 * @param context
282 */
283 public static void logMultiWindow(Context context) {
284 logCount(context, COUNT_MULTI_WINDOW);
285 }
286
287 /**
Ben Kwad5b2af12016-01-28 16:39:57 -0800288 * Logs file operation stats. Call this when a file operation has completed. The given
289 * DocumentInfo is only used to distinguish broad categories of actions (e.g. copying from one
290 * provider to another vs copying within a given provider). No PII is logged.
291 *
292 * @param context
293 * @param operationType
294 * @param srcs
295 * @param dst
296 */
297 public static void logFileOperation(
298 Context context,
299 @OpType int operationType,
300 List<DocumentInfo> srcs,
301 @Nullable DocumentInfo dst) {
302 ProviderCounts counts = countProviders(srcs, dst);
303
304 if (counts.intraProvider > 0) {
305 logIntraProviderFileOps(context, dst.authority, operationType);
306 }
307 if (counts.systemProvider > 0) {
308 // Log file operations on system providers.
309 logInterProviderFileOps(context, COUNT_FILEOP_SYSTEM, dst, operationType);
310 }
311 if (counts.externalProvider > 0) {
312 // Log file operations on external providers.
313 logInterProviderFileOps(context, COUNT_FILEOP_EXTERNAL, dst, operationType);
314 }
315 }
316
317 /**
318 * Logs some kind of file operation error. Call this when a file operation (e.g. copy, delete)
319 * fails.
320 *
321 * @param context
322 * @param operationType
323 * @param failedFiles
324 */
325 public static void logFileOperationErrors(Context context, @OpType int operationType,
326 List<DocumentInfo> failedFiles) {
327 ProviderCounts counts = countProviders(failedFiles, null);
328
329 @FileOp int opCode = FILEOP_OTHER_ERROR;
330 switch (operationType) {
331 case FileOperationService.OPERATION_COPY:
332 opCode = FILEOP_COPY_ERROR;
333 break;
334 case FileOperationService.OPERATION_DELETE:
335 opCode = FILEOP_DELETE_ERROR;
336 break;
337 case FileOperationService.OPERATION_MOVE:
338 opCode = FILEOP_MOVE_ERROR;
339 break;
340 }
341 if (counts.systemProvider > 0) {
342 logHistogram(context, COUNT_FILEOP_SYSTEM, opCode);
343 }
344 if (counts.externalProvider > 0) {
345 logHistogram(context, COUNT_FILEOP_EXTERNAL, opCode);
346 }
347 }
348
349 /**
350 * Log the cancellation of a file operation. Call this when a Job is canceled.
351 * @param context
352 * @param operationType
353 */
354 public static void logFileOperationCancelled(Context context, @OpType int operationType) {
Ben Kwaa87e9f92016-02-17 16:06:22 -0800355 logHistogram(context, COUNT_FILEOP_CANCELED, toMetricsOpType(operationType));
Ben Kwad5b2af12016-01-28 16:39:57 -0800356 }
357
358 private static void logInterProviderFileOps(
359 Context context,
360 String histogram,
361 DocumentInfo dst,
362 @OpType int operationType) {
363 if (operationType == FileOperationService.OPERATION_DELETE) {
364 logHistogram(context, histogram, FILEOP_DELETE);
365 } else {
366 checkArgument(dst != null);
367 @Provider int providerType =
368 isSystemProvider(dst.authority) ? PROVIDER_SYSTEM : PROVIDER_EXTERNAL;
369 logHistogram(context, histogram, getOpCode(operationType, providerType));
370 }
371 }
372
373 private static void logIntraProviderFileOps(
374 Context context, String authority, @OpType int operationType) {
375 // Find the right histogram to log to, then log the operation.
376 String histogram = isSystemProvider(authority) ? COUNT_FILEOP_SYSTEM : COUNT_FILEOP_EXTERNAL;
377 logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
378 }
379
380 /**
Ben Kwa72379982016-01-26 11:50:03 -0800381 * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
382 *
383 * @param context
384 * @param name The counter to increment.
385 */
386 private static void logCount(Context context, String name) {
387 if (DEBUG) Log.d(TAG, name + ": " + 1);
388 MetricsLogger.count(context, name, 1);
389 }
390
391 /**
392 * Internal method for making a MetricsLogger.histogram call.
393 *
394 * @param context
395 * @param name The name of the histogram.
396 * @param bucket The bucket to increment.
397 */
398 private static void logHistogram(Context context, String name, int bucket) {
399 if (DEBUG) Log.d(TAG, name + ": " + bucket);
400 MetricsLogger.histogram(context, name, bucket);
401 }
402
403 /**
404 * Generates an integer identifying the given root. For privacy, this function only recognizes a
405 * small set of hard-coded roots (ones provided by the system). Other roots are all grouped into
406 * a single ROOT_OTHER bucket.
407 */
Ben Kwad5b2af12016-01-28 16:39:57 -0800408 private static @Root int sanitizeRoot(Uri uri) {
Tomasz Mikolajewskicd270152016-02-01 12:01:14 +0900409 if (uri == null || uri.getAuthority() == null || LauncherActivity.isLaunchUri(uri)) {
Ben Kwa72379982016-01-26 11:50:03 -0800410 return ROOT_NONE;
411 }
412
413 switch (uri.getAuthority()) {
414 case AUTHORITY_MEDIA:
415 switch (DocumentsContract.getRootId(uri)) {
416 case "audio_root":
417 return ROOT_AUDIO;
418 case "images_root":
419 return ROOT_IMAGES;
420 case "videos_root":
421 return ROOT_VIDEOS;
422 default:
423 return ROOT_OTHER;
424 }
425 case AUTHORITY_STORAGE:
426 if ("home".equals(DocumentsContract.getRootId(uri))) {
427 return ROOT_HOME;
428 } else {
429 return ROOT_DEVICE_STORAGE;
430 }
431 case AUTHORITY_DOWNLOADS:
432 return ROOT_DOWNLOADS;
Ben Kwada518c92016-01-28 18:15:07 -0800433 case AUTHORITY_MTP:
434 return ROOT_MTP;
Ben Kwa72379982016-01-26 11:50:03 -0800435 default:
436 return ROOT_OTHER;
437 }
438 }
439
440 /** @see #sanitizeRoot(Uri) */
Ben Kwad5b2af12016-01-28 16:39:57 -0800441 private static @Root int sanitizeRoot(RootInfo root) {
Ben Kwa72379982016-01-26 11:50:03 -0800442 if (root.isRecents()) {
443 // Recents root is special and only identifiable via this method call. Other roots are
444 // identified by URI.
445 return ROOT_RECENTS;
446 } else {
447 return sanitizeRoot(root.getUri());
448 }
449 }
450
451 /** @see #sanitizeRoot(Uri) */
Ben Kwad5b2af12016-01-28 16:39:57 -0800452 private static @Root int sanitizeRoot(ResolveInfo info) {
Ben Kwa72379982016-01-26 11:50:03 -0800453 // Log all apps under a single bucket in the roots histogram.
454 return ROOT_THIRD_PARTY_APP;
455 }
456
457 /**
458 * Generates an int identifying a mime type. For privacy, this function only recognizes a small
459 * set of hard-coded types. For any other type, this function returns "other".
460 *
461 * @param mimeType
462 * @return
463 */
Ben Kwad5b2af12016-01-28 16:39:57 -0800464 private static @Mime int sanitizeMime(String mimeType) {
Ben Kwa72379982016-01-26 11:50:03 -0800465 if (mimeType == null) {
466 return MIME_NONE;
467 } else if ("*/*".equals(mimeType)) {
468 return MIME_ANY;
469 } else {
470 String type = mimeType.substring(0, mimeType.indexOf('/'));
471 switch (type) {
472 case "application":
473 return MIME_APPLICATION;
474 case "audio":
475 return MIME_AUDIO;
476 case "image":
477 return MIME_IMAGE;
478 case "message":
479 return MIME_MESSAGE;
480 case "multipart":
481 return MIME_MULTIPART;
482 case "text":
483 return MIME_TEXT;
484 case "video":
485 return MIME_VIDEO;
486 }
487 }
488 // Bucket all other types into one bucket.
489 return MIME_OTHER;
490 }
Ben Kwad5b2af12016-01-28 16:39:57 -0800491
492 private static boolean isSystemProvider(String authority) {
493 switch (authority) {
494 case AUTHORITY_MEDIA:
495 case AUTHORITY_STORAGE:
496 case AUTHORITY_DOWNLOADS:
497 return true;
498 default:
499 return false;
500 }
501 }
502
503 /**
504 * @param operation
505 * @param providerType
506 * @return An opcode, suitable for use as histogram bucket, for the given operation/provider
507 * combination.
508 */
509 private static @FileOp int getOpCode(@OpType int operation, @Provider int providerType) {
510 switch (operation) {
511 case FileOperationService.OPERATION_COPY:
512 switch (providerType) {
513 case PROVIDER_INTRA:
514 return FILEOP_COPY_INTRA_PROVIDER;
515 case PROVIDER_SYSTEM:
516 return FILEOP_COPY_SYSTEM_PROVIDER;
517 case PROVIDER_EXTERNAL:
518 return FILEOP_COPY_EXTERNAL_PROVIDER;
519 }
520 case FileOperationService.OPERATION_MOVE:
521 switch (providerType) {
522 case PROVIDER_INTRA:
523 return FILEOP_MOVE_INTRA_PROVIDER;
524 case PROVIDER_SYSTEM:
525 return FILEOP_MOVE_SYSTEM_PROVIDER;
526 case PROVIDER_EXTERNAL:
527 return FILEOP_MOVE_EXTERNAL_PROVIDER;
528 }
529 case FileOperationService.OPERATION_DELETE:
530 return FILEOP_DELETE;
531 default:
532 Log.w(TAG, "Unrecognized operation type when logging a file operation");
533 return FILEOP_OTHER;
534 }
535 }
536
537 /**
Ben Kwaa87e9f92016-02-17 16:06:22 -0800538 * Maps FileOperationService OpType values, to MetricsOpType values.
539 */
540 private static @MetricsOpType int toMetricsOpType(@OpType int operation) {
541 switch (operation) {
542 case FileOperationService.OPERATION_COPY:
543 return OPERATION_COPY;
544 case FileOperationService.OPERATION_MOVE:
545 return OPERATION_MOVE;
546 case FileOperationService.OPERATION_DELETE:
547 return OPERATION_DELETE;
548 case FileOperationService.OPERATION_UNKNOWN:
549 default:
550 return OPERATION_UNKNOWN;
551 }
552 }
553
554 private static @MetricsAction int toMetricsAction(int action) {
555 switch(action) {
556 case State.ACTION_OPEN:
557 return ACTION_OPEN;
558 case State.ACTION_CREATE:
559 return ACTION_CREATE;
560 case State.ACTION_GET_CONTENT:
561 return ACTION_GET_CONTENT;
562 case State.ACTION_OPEN_TREE:
563 return ACTION_OPEN_TREE;
564 case State.ACTION_MANAGE:
565 return ACTION_MANAGE;
566 case State.ACTION_BROWSE:
567 return ACTION_BROWSE;
568 case State.ACTION_PICK_COPY_DESTINATION:
569 return ACTION_PICK_COPY_DESTINATION;
570 default:
571 return ACTION_OTHER;
572 }
573 }
574
575 /**
Ben Kwad5b2af12016-01-28 16:39:57 -0800576 * Count the given src documents and provide a tally of how many come from the same provider as
577 * the dst document (if a dst is provided), how many come from system providers, and how many
578 * come from external 3rd-party providers.
579 */
580 private static ProviderCounts countProviders(
581 List<DocumentInfo> srcs, @Nullable DocumentInfo dst) {
582 ProviderCounts counts = new ProviderCounts();
583 for (DocumentInfo doc: srcs) {
584 if (dst != null && doc.authority.equals(dst.authority)) {
585 counts.intraProvider++;
586 } else if (isSystemProvider(doc.authority)){
587 counts.systemProvider++;
588 } else {
589 counts.externalProvider++;
590 }
591 }
592 return counts;
593 }
594
595 private static class ProviderCounts {
596 int intraProvider;
597 int systemProvider;
598 int externalProvider;
599 }
Ben Kwa72379982016-01-26 11:50:03 -0800600}