blob: fba24be4dfea6484b8e760f0d5dde5c0a7272b26 [file] [log] [blame]
Ben Kwa1c0a3892016-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
Garfield Tan02fd92f2017-01-13 15:28:30 -080019import static com.android.documentsui.DocumentsApplication.acquireUnstableProviderOrThrow;
Felipe Leme9de58072018-01-19 16:40:04 -080020import static com.android.documentsui.base.SharedMinimal.DEBUG;
Steve McKay15b92782016-03-09 15:20:00 -080021
Ben Kwafaa27202016-01-28 16:39:57 -080022import android.annotation.IntDef;
23import android.annotation.Nullable;
Garfield Tan02fd92f2017-01-13 15:28:30 -080024import android.content.ContentProviderClient;
Ben Kwa1c0a3892016-01-26 11:50:03 -080025import android.content.Context;
26import android.content.Intent;
27import android.content.pm.ResolveInfo;
28import android.net.Uri;
Garfield Tan02fd92f2017-01-13 15:28:30 -080029import android.os.RemoteException;
Ben Kwa1c0a3892016-01-26 11:50:03 -080030import android.provider.DocumentsContract;
Garfield Tan02fd92f2017-01-13 15:28:30 -080031import android.provider.DocumentsContract.Path;
Garfield Tan935c5132017-01-12 14:16:08 -080032import android.provider.DocumentsProvider;
Ben Kwa1c0a3892016-01-26 11:50:03 -080033import android.util.Log;
34
Steve McKayd0805062016-09-15 14:30:38 -070035import com.android.documentsui.base.DocumentInfo;
Steve McKay8659cbc2016-10-31 13:13:36 -070036import com.android.documentsui.base.Providers;
Steve McKayd0805062016-09-15 14:30:38 -070037import com.android.documentsui.base.RootInfo;
Steve McKayd9caa6a2016-09-15 16:36:45 -070038import com.android.documentsui.base.State;
39import com.android.documentsui.base.State.ActionType;
Steve McKayb6006b22016-09-29 09:23:45 -070040import com.android.documentsui.files.LauncherActivity;
Jon Mann9bd40992017-03-24 12:34:34 -070041import com.android.documentsui.roots.ProvidersAccess;
Ben Kwafaa27202016-01-28 16:39:57 -080042import com.android.documentsui.services.FileOperationService;
43import com.android.documentsui.services.FileOperationService.OpType;
Ben Kwa1c0a3892016-01-26 11:50:03 -080044import com.android.internal.logging.MetricsLogger;
45
Ben Kwafaa27202016-01-28 16:39:57 -080046import java.lang.annotation.Retention;
47import java.lang.annotation.RetentionPolicy;
48import java.util.List;
49
Leif Hendrik Wilden42053492018-01-03 11:16:09 -080050/**
51 * Methods for logging metrics.
52 */
Ben Kwa1c0a3892016-01-26 11:50:03 -080053public final class Metrics {
54 private static final String TAG = "Metrics";
55
Ben Kwa1c0a3892016-01-26 11:50:03 -080056 // These strings have to be whitelisted in tron. Do not change them.
57 private static final String COUNT_LAUNCH_ACTION = "docsui_launch_action";
Garfield Tan045ce6b2017-01-19 16:17:04 -080058 private static final String COUNT_ROOT_VISITED_IN_MANAGER
59 = "docsui_root_visited_in_manager";
60 private static final String COUNT_ROOT_VISITED_IN_PICKER
61 = "docsui_root_visited_in_picker";
Ben Kwa1c0a3892016-01-26 11:50:03 -080062 private static final String COUNT_OPEN_MIME = "docsui_open_mime";
63 private static final String COUNT_CREATE_MIME = "docsui_create_mime";
64 private static final String COUNT_GET_CONTENT_MIME = "docsui_get_content_mime";
65 private static final String COUNT_BROWSE_ROOT = "docsui_browse_root";
Steve McKay15b92782016-03-09 15:20:00 -080066 @Deprecated private static final String COUNT_MANAGE_ROOT = "docsui_manage_root";
Aga Wronska94e53e42016-04-07 13:09:58 -070067 @Deprecated private static final String COUNT_MULTI_WINDOW = "docsui_multi_window";
Ben Kwafaa27202016-01-28 16:39:57 -080068 private static final String COUNT_FILEOP_SYSTEM = "docsui_fileop_system";
69 private static final String COUNT_FILEOP_EXTERNAL = "docsui_fileop_external";
70 private static final String COUNT_FILEOP_CANCELED = "docsui_fileop_canceled";
Daichi Hirono320a08f2016-03-25 19:04:39 +090071 private static final String COUNT_STARTUP_MS = "docsui_startup_ms";
Garfield Tan3f54c9c2017-03-31 14:52:36 -070072 @Deprecated private static final String COUNT_DRAWER_OPENED = "docsui_drawer_opened";
Aga Wronska94e53e42016-04-07 13:09:58 -070073 private static final String COUNT_USER_ACTION = "docsui_menu_action";
Garfield Tanf8969d62017-02-02 16:55:55 -080074 private static final String COUNT_BROWSE_AT_LOCATION = "docsui_browse_at_location";
Garfield Tan935c5132017-01-12 14:16:08 -080075 private static final String COUNT_CREATE_AT_LOCATION = "docsui_create_at_location";
76 private static final String COUNT_OPEN_AT_LOCATION = "docsui_open_at_location";
77 private static final String COUNT_GET_CONTENT_AT_LOCATION = "docsui_get_content_at_location";
Garfield Tan02fd92f2017-01-13 15:28:30 -080078 private static final String COUNT_MEDIA_FILEOP_FAILURE = "docsui_media_fileop_failure";
79 private static final String COUNT_DOWNLOADS_FILEOP_FAILURE = "docsui_downloads_fileop_failure";
80 private static final String COUNT_INTERNAL_STORAGE_FILEOP_FAILURE
81 = "docsui_internal_storage_fileop_failure";
82 private static final String COUNT_EXTERNAL_STORAGE_FILEOP_FAILURE
83 = "docsui_external_storage_fileop_failure";
84 private static final String COUNT_MTP_FILEOP_FAILURE = "docsui_mtp_fileop_failure";
85 private static final String COUNT_OTHER_FILEOP_FAILURE = "docsui_other_fileop_failure";
Garfield Tan331de982017-04-19 16:22:00 -070086 private static final String COUNT_FILE_COPIED = "docsui_file_copied";
87 private static final String COUNT_FILE_MOVED = "docsui_file_moved";
Ben Kwa1c0a3892016-01-26 11:50:03 -080088
89 // Indices for bucketing roots in the roots histogram. "Other" is the catch-all index for any
90 // root that is not explicitly recognized by the Metrics code (see {@link
Ben Kwab41a5ed2016-02-17 16:06:22 -080091 // #getSanitizedRootIndex}). Apps are also bucketed in this histogram.
Ben Kwaebaaea42016-01-28 18:15:07 -080092 // Do not change or rearrange these values, that will break historical data. Only add to the end
93 // of the list.
Ben Kwab41a5ed2016-02-17 16:06:22 -080094 // Do not use negative numbers or zero; clearcut only handles positive integers.
95 private static final int ROOT_NONE = 1;
96 private static final int ROOT_OTHER = 2;
97 private static final int ROOT_AUDIO = 3;
98 private static final int ROOT_DEVICE_STORAGE = 4;
99 private static final int ROOT_DOWNLOADS = 5;
100 private static final int ROOT_HOME = 6;
101 private static final int ROOT_IMAGES = 7;
102 private static final int ROOT_RECENTS = 8;
103 private static final int ROOT_VIDEOS = 9;
104 private static final int ROOT_MTP = 10;
Ben Kwa1c0a3892016-01-26 11:50:03 -0800105 // Apps aren't really "roots", but they are treated as such in the roots fragment UI and so they
Ben Kwab41a5ed2016-02-17 16:06:22 -0800106 // are logged analogously to roots.
107 private static final int ROOT_THIRD_PARTY_APP = 100;
Ben Kwa1c0a3892016-01-26 11:50:03 -0800108
Ben Kwafaa27202016-01-28 16:39:57 -0800109 @IntDef(flag = true, value = {
110 ROOT_NONE,
111 ROOT_OTHER,
112 ROOT_AUDIO,
113 ROOT_DEVICE_STORAGE,
114 ROOT_DOWNLOADS,
115 ROOT_HOME,
116 ROOT_IMAGES,
117 ROOT_RECENTS,
118 ROOT_VIDEOS,
Ben Kwaebaaea42016-01-28 18:15:07 -0800119 ROOT_MTP,
Ben Kwafaa27202016-01-28 16:39:57 -0800120 ROOT_THIRD_PARTY_APP
121 })
122 @Retention(RetentionPolicy.SOURCE)
123 public @interface Root {}
124
Ben Kwa1c0a3892016-01-26 11:50:03 -0800125 // Indices for bucketing mime types.
Ben Kwab41a5ed2016-02-17 16:06:22 -0800126 // Do not change or rearrange these values, that will break historical data. Only add to the end
127 // of the list.
128 // Do not use negative numbers or zero; clearcut only handles positive integers.
129 private static final int MIME_NONE = 1; // null mime
130 private static final int MIME_ANY = 2; // */*
131 private static final int MIME_APPLICATION = 3; // application/*
132 private static final int MIME_AUDIO = 4; // audio/*
133 private static final int MIME_IMAGE = 5; // image/*
134 private static final int MIME_MESSAGE = 6; // message/*
135 private static final int MIME_MULTIPART = 7; // multipart/*
136 private static final int MIME_TEXT = 8; // text/*
137 private static final int MIME_VIDEO = 9; // video/*
138 private static final int MIME_OTHER = 10; // anything not enumerated below
Ben Kwa1c0a3892016-01-26 11:50:03 -0800139
Ben Kwafaa27202016-01-28 16:39:57 -0800140 @IntDef(flag = true, value = {
Ben Kwafaa27202016-01-28 16:39:57 -0800141 MIME_NONE,
142 MIME_ANY,
143 MIME_APPLICATION,
144 MIME_AUDIO,
145 MIME_IMAGE,
146 MIME_MESSAGE,
147 MIME_MULTIPART,
148 MIME_TEXT,
Ben Kwab41a5ed2016-02-17 16:06:22 -0800149 MIME_VIDEO,
150 MIME_OTHER
Ben Kwafaa27202016-01-28 16:39:57 -0800151 })
152 @Retention(RetentionPolicy.SOURCE)
153 public @interface Mime {}
154
Garfield Tan045ce6b2017-01-19 16:17:04 -0800155 public static final int FILES_SCOPE = 1;
156 public static final int PICKER_SCOPE = 2;
157
158 @IntDef({ FILES_SCOPE, PICKER_SCOPE })
159 @Retention(RetentionPolicy.SOURCE)
160 public @interface ContextScope {}
161
Ben Kwafaa27202016-01-28 16:39:57 -0800162 // Codes representing different kinds of file operations. These are used for bucketing
163 // operations in the COUNT_FILEOP_{SYSTEM|EXTERNAL} histograms.
Ben Kwab41a5ed2016-02-17 16:06:22 -0800164 // Do not change or rearrange these values, that will break historical data. Only add to the
165 // list.
166 // Do not use negative numbers or zero; clearcut only handles positive integers.
167 private static final int FILEOP_OTHER = 1; // any file operation not listed below
168 private static final int FILEOP_COPY_INTRA_PROVIDER = 2; // Copy within a provider
169 private static final int FILEOP_COPY_SYSTEM_PROVIDER = 3; // Copy to a system provider.
170 private static final int FILEOP_COPY_EXTERNAL_PROVIDER = 4; // Copy to a 3rd-party provider.
171 private static final int FILEOP_MOVE_INTRA_PROVIDER = 5; // Move within a provider.
172 private static final int FILEOP_MOVE_SYSTEM_PROVIDER = 6; // Move to a system provider.
173 private static final int FILEOP_MOVE_EXTERNAL_PROVIDER = 7; // Move to a 3rd-party provider.
174 private static final int FILEOP_DELETE = 8;
Aga Wronska46a868a2016-03-30 10:57:04 -0700175 private static final int FILEOP_RENAME = 9;
176 private static final int FILEOP_CREATE_DIR = 10;
Ben Kwab41a5ed2016-02-17 16:06:22 -0800177 private static final int FILEOP_OTHER_ERROR = 100;
178 private static final int FILEOP_DELETE_ERROR = 101;
179 private static final int FILEOP_MOVE_ERROR = 102;
180 private static final int FILEOP_COPY_ERROR = 103;
Aga Wronska46a868a2016-03-30 10:57:04 -0700181 private static final int FILEOP_RENAME_ERROR = 104;
182 private static final int FILEOP_CREATE_DIR_ERROR = 105;
Garfield Tan8d1443a2017-04-20 15:27:38 -0700183 private static final int FILEOP_COMPRESS_INTRA_PROVIDER = 106; // Compres within a provider
184 private static final int FILEOP_COMPRESS_SYSTEM_PROVIDER = 107; // Compress to a system provider.
185 private static final int FILEOP_COMPRESS_EXTERNAL_PROVIDER = 108; // Compress to a 3rd-party provider.
186 private static final int FILEOP_EXTRACT_INTRA_PROVIDER = 109; // Extract within a provider
187 private static final int FILEOP_EXTRACT_SYSTEM_PROVIDER = 110; // Extract to a system provider.
188 private static final int FILEOP_EXTRACT_EXTERNAL_PROVIDER = 111; // Extract to a 3rd-party provider.
189 private static final int FILEOP_COMPRESS_ERROR = 112;
190 private static final int FILEOP_EXTRACT_ERROR = 113;
Ben Kwafaa27202016-01-28 16:39:57 -0800191
192 @IntDef(flag = true, value = {
193 FILEOP_OTHER,
194 FILEOP_COPY_INTRA_PROVIDER,
195 FILEOP_COPY_SYSTEM_PROVIDER,
196 FILEOP_COPY_EXTERNAL_PROVIDER,
197 FILEOP_MOVE_INTRA_PROVIDER,
198 FILEOP_MOVE_SYSTEM_PROVIDER,
199 FILEOP_MOVE_EXTERNAL_PROVIDER,
200 FILEOP_DELETE,
Aga Wronska46a868a2016-03-30 10:57:04 -0700201 FILEOP_RENAME,
202 FILEOP_CREATE_DIR,
Ben Kwafaa27202016-01-28 16:39:57 -0800203 FILEOP_OTHER_ERROR,
Aga Wronska46a868a2016-03-30 10:57:04 -0700204 FILEOP_DELETE_ERROR,
Garfield Tan8d1443a2017-04-20 15:27:38 -0700205 FILEOP_MOVE_ERROR,
206 FILEOP_COPY_ERROR,
Aga Wronska46a868a2016-03-30 10:57:04 -0700207 FILEOP_RENAME_ERROR,
Garfield Tan8d1443a2017-04-20 15:27:38 -0700208 FILEOP_CREATE_DIR_ERROR,
209 FILEOP_COMPRESS_INTRA_PROVIDER,
210 FILEOP_COMPRESS_SYSTEM_PROVIDER,
211 FILEOP_COMPRESS_EXTERNAL_PROVIDER,
212 FILEOP_EXTRACT_INTRA_PROVIDER,
213 FILEOP_EXTRACT_SYSTEM_PROVIDER,
214 FILEOP_EXTRACT_EXTERNAL_PROVIDER,
215 FILEOP_COMPRESS_ERROR,
216 FILEOP_EXTRACT_ERROR
Ben Kwafaa27202016-01-28 16:39:57 -0800217 })
218 @Retention(RetentionPolicy.SOURCE)
219 public @interface FileOp {}
220
Ben Kwab41a5ed2016-02-17 16:06:22 -0800221 // Codes representing different kinds of file operations. These are used for bucketing
222 // operations in the COUNT_FILEOP_CANCELED histogram.
223 // Do not change or rearrange these values, that will break historical data. Only add to the
224 // list.
225 // Do not use negative numbers or zero; clearcut only handles positive integers.
226 private static final int OPERATION_UNKNOWN = 1;
227 private static final int OPERATION_COPY = 2;
228 private static final int OPERATION_MOVE = 3;
Tomasz Mikolajewski4f225492017-01-27 16:29:30 +0900229 private static final int OPERATION_DELETE = 4;
Garfield Tan8d1443a2017-04-20 15:27:38 -0700230 private static final int OPERATION_COMPRESS = 5;
231 private static final int OPERATION_EXTRACT = 6;
Ben Kwab41a5ed2016-02-17 16:06:22 -0800232
233 @IntDef(flag = true, value = {
234 OPERATION_UNKNOWN,
235 OPERATION_COPY,
236 OPERATION_MOVE,
Garfield Tan8d1443a2017-04-20 15:27:38 -0700237 OPERATION_DELETE,
238 OPERATION_COMPRESS,
239 OPERATION_EXTRACT
Ben Kwab41a5ed2016-02-17 16:06:22 -0800240 })
241 @Retention(RetentionPolicy.SOURCE)
242 public @interface MetricsOpType {}
243
Aga Wronska4972d712016-03-30 13:55:19 -0700244 // Codes representing different provider types. Used for sorting file operations when logging.
245 private static final int PROVIDER_INTRA = 0;
246 private static final int PROVIDER_SYSTEM = 1;
247 private static final int PROVIDER_EXTERNAL = 2;
248
249 @IntDef(flag = false, value = {
250 PROVIDER_INTRA,
251 PROVIDER_SYSTEM,
252 PROVIDER_EXTERNAL
253 })
254 @Retention(RetentionPolicy.SOURCE)
255 public @interface Provider {}
256
Garfield Tan02fd92f2017-01-13 15:28:30 -0800257 // Codes representing different types of sub-fileops. These are used for bucketing fileop
258 // failures in COUNT_*_FILEOP_FAILURE.
259 public static final int SUBFILEOP_QUERY_DOCUMENT = 1;
260 public static final int SUBFILEOP_QUERY_CHILDREN = 2;
261 public static final int SUBFILEOP_OPEN_FILE = 3;
262 public static final int SUBFILEOP_READ_FILE = 4;
263 public static final int SUBFILEOP_CREATE_DOCUMENT = 5;
264 public static final int SUBFILEOP_WRITE_FILE = 6;
265 public static final int SUBFILEOP_DELETE_DOCUMENT = 7;
266 public static final int SUBFILEOP_OBTAIN_STREAM_TYPE = 8;
267 public static final int SUBFILEOP_QUICK_MOVE = 9;
268 public static final int SUBFILEOP_QUICK_COPY = 10;
269
270 @IntDef(flag = false, value = {
271 SUBFILEOP_QUERY_DOCUMENT,
272 SUBFILEOP_QUERY_CHILDREN,
273 SUBFILEOP_OPEN_FILE,
274 SUBFILEOP_READ_FILE,
275 SUBFILEOP_CREATE_DOCUMENT,
276 SUBFILEOP_WRITE_FILE,
277 SUBFILEOP_DELETE_DOCUMENT,
278 SUBFILEOP_OBTAIN_STREAM_TYPE,
279 SUBFILEOP_QUICK_MOVE,
280 SUBFILEOP_QUICK_COPY
281 })
282 @Retention(RetentionPolicy.SOURCE)
283 public @interface SubFileOp {}
Aga Wronska4972d712016-03-30 13:55:19 -0700284
Aga Wronska94e53e42016-04-07 13:09:58 -0700285 // Codes representing different user actions. These are used for bucketing stats in the
286 // COUNT_USER_ACTION histogram.
287 // The historgram includes action triggered from menu or invoked by keyboard shortcut.
Aga Wronska4972d712016-03-30 13:55:19 -0700288 // Do not change or rearrange these values, that will break historical data. Only add to the
289 // list.
290 // Do not use negative numbers or zero; clearcut only handles positive integers.
Aga Wronska94e53e42016-04-07 13:09:58 -0700291 public static final int USER_ACTION_OTHER = 1;
292 public static final int USER_ACTION_GRID = 2;
293 public static final int USER_ACTION_LIST = 3;
294 public static final int USER_ACTION_SORT_NAME = 4;
295 public static final int USER_ACTION_SORT_DATE = 5;
296 public static final int USER_ACTION_SORT_SIZE = 6;
297 public static final int USER_ACTION_SEARCH = 7;
298 public static final int USER_ACTION_SHOW_SIZE = 8;
299 public static final int USER_ACTION_HIDE_SIZE = 9;
300 public static final int USER_ACTION_SETTINGS = 10;
301 public static final int USER_ACTION_COPY_TO = 11;
302 public static final int USER_ACTION_MOVE_TO = 12;
303 public static final int USER_ACTION_DELETE = 13;
304 public static final int USER_ACTION_RENAME = 14;
305 public static final int USER_ACTION_CREATE_DIR = 15;
306 public static final int USER_ACTION_SELECT_ALL = 16;
307 public static final int USER_ACTION_SHARE = 17;
308 public static final int USER_ACTION_OPEN = 18;
309 public static final int USER_ACTION_SHOW_ADVANCED = 19;
310 public static final int USER_ACTION_HIDE_ADVANCED = 20;
311 public static final int USER_ACTION_NEW_WINDOW = 21;
312 public static final int USER_ACTION_PASTE_CLIPBOARD = 22;
313 public static final int USER_ACTION_COPY_CLIPBOARD = 23;
314 public static final int USER_ACTION_DRAG_N_DROP = 24;
315 public static final int USER_ACTION_DRAG_N_DROP_MULTI_WINDOW = 25;
Ben Linff4d5842016-04-18 14:35:28 -0700316 public static final int USER_ACTION_CUT_CLIPBOARD = 26;
Garfield Tan8d1443a2017-04-20 15:27:38 -0700317 public static final int USER_ACTION_COMPRESS = 27;
318 public static final int USER_ACTION_EXTRACT_TO = 28;
319 public static final int USER_ACTION_VIEW_IN_APPLICATION = 29;
Dooper3975fa22017-06-02 10:32:00 -0700320 public static final int USER_ACTION_INSPECTOR = 30;
Aga Wronska4972d712016-03-30 13:55:19 -0700321
322 @IntDef(flag = false, value = {
Aga Wronska94e53e42016-04-07 13:09:58 -0700323 USER_ACTION_OTHER,
324 USER_ACTION_GRID,
325 USER_ACTION_LIST,
326 USER_ACTION_SORT_NAME,
327 USER_ACTION_SORT_DATE,
328 USER_ACTION_SORT_SIZE,
329 USER_ACTION_SEARCH,
330 USER_ACTION_SHOW_SIZE,
331 USER_ACTION_HIDE_SIZE,
332 USER_ACTION_SETTINGS,
333 USER_ACTION_COPY_TO,
334 USER_ACTION_MOVE_TO,
335 USER_ACTION_DELETE,
336 USER_ACTION_RENAME,
337 USER_ACTION_CREATE_DIR,
338 USER_ACTION_SELECT_ALL,
339 USER_ACTION_SHARE,
340 USER_ACTION_OPEN,
341 USER_ACTION_SHOW_ADVANCED,
342 USER_ACTION_HIDE_ADVANCED,
343 USER_ACTION_NEW_WINDOW,
344 USER_ACTION_PASTE_CLIPBOARD,
345 USER_ACTION_COPY_CLIPBOARD,
346 USER_ACTION_DRAG_N_DROP,
Ben Linff4d5842016-04-18 14:35:28 -0700347 USER_ACTION_DRAG_N_DROP_MULTI_WINDOW,
Jon Mann253a9922017-03-21 18:53:27 -0700348 USER_ACTION_CUT_CLIPBOARD,
Garfield Tan8d1443a2017-04-20 15:27:38 -0700349 USER_ACTION_COMPRESS,
350 USER_ACTION_EXTRACT_TO,
Julian Mancini4e242f72017-07-06 11:08:09 -0700351 USER_ACTION_VIEW_IN_APPLICATION,
352 USER_ACTION_INSPECTOR
Aga Wronska4972d712016-03-30 13:55:19 -0700353 })
354 @Retention(RetentionPolicy.SOURCE)
Aga Wronska94e53e42016-04-07 13:09:58 -0700355 public @interface UserAction {}
Aga Wronska4972d712016-03-30 13:55:19 -0700356
Garfield Tan331de982017-04-19 16:22:00 -0700357 // Codes representing different approaches to copy/move a document. OPMODE_PROVIDER indicates
358 // it's an optimized operation provided by providers; OPMODE_CONVERTED means it's converted from
359 // a virtual file; and OPMODE_CONVENTIONAL means it's byte copied.
360 public static final int OPMODE_PROVIDER = 1;
361 public static final int OPMODE_CONVERTED = 2;
362 public static final int OPMODE_CONVENTIONAL = 3;
363 @IntDef({OPMODE_PROVIDER, OPMODE_CONVERTED, OPMODE_CONVENTIONAL})
364 @Retention(RetentionPolicy.SOURCE)
365 public @interface FileOpMode {}
366
Aga Wronska4972d712016-03-30 13:55:19 -0700367 // Codes representing different menu actions. These are used for bucketing stats in the
368 // COUNT_MENU_ACTION histogram.
Ben Kwab41a5ed2016-02-17 16:06:22 -0800369 // Do not change or rearrange these values, that will break historical data. Only add to the
370 // list.
371 // Do not use negative numbers or zero; clearcut only handles positive integers.
372 private static final int ACTION_OTHER = 1;
373 private static final int ACTION_OPEN = 2;
374 private static final int ACTION_CREATE = 3;
375 private static final int ACTION_GET_CONTENT = 4;
376 private static final int ACTION_OPEN_TREE = 5;
Steve McKay15b92782016-03-09 15:20:00 -0800377 @Deprecated private static final int ACTION_MANAGE = 6;
Ben Kwab41a5ed2016-02-17 16:06:22 -0800378 private static final int ACTION_BROWSE = 7;
379 private static final int ACTION_PICK_COPY_DESTINATION = 8;
380
381 @IntDef(flag = true, value = {
382 ACTION_OTHER,
383 ACTION_OPEN,
384 ACTION_CREATE,
385 ACTION_GET_CONTENT,
386 ACTION_OPEN_TREE,
387 ACTION_MANAGE,
388 ACTION_BROWSE,
389 ACTION_PICK_COPY_DESTINATION
390 })
391 @Retention(RetentionPolicy.SOURCE)
392 public @interface MetricsAction {}
393
Aga Wronska441b9be2016-03-29 16:57:10 -0700394 // Codes representing different actions to open the drawer. They are used for bucketing stats in
395 // the COUNT_DRAWER_OPENED histogram.
396 // Do not change or rearrange these values, that will break historical data. Only add to the
397 // list.
398 // Do not use negative numbers or zero; clearcut only handles positive integers.
399 private static final int DRAWER_OPENED_HAMBURGER = 1;
400 private static final int DRAWER_OPENED_SWIPE = 2;
401
402 @IntDef(flag = true, value = {
403 DRAWER_OPENED_HAMBURGER,
404 DRAWER_OPENED_SWIPE
405 })
406 @Retention(RetentionPolicy.SOURCE)
407 public @interface DrawerTrigger {}
408
Ben Kwa1c0a3892016-01-26 11:50:03 -0800409 /**
410 * Logs when DocumentsUI is started, and how. Call this when DocumentsUI first starts up.
411 *
412 * @param context
413 * @param state
414 * @param intent
415 */
416 public static void logActivityLaunch(Context context, State state, Intent intent) {
417 // Log the launch action.
Ben Kwab41a5ed2016-02-17 16:06:22 -0800418 logHistogram(context, COUNT_LAUNCH_ACTION, toMetricsAction(state.action));
Ben Kwa1c0a3892016-01-26 11:50:03 -0800419 // Then log auxiliary data (roots/mime types) associated with some actions.
420 Uri uri = intent.getData();
421 switch (state.action) {
422 case State.ACTION_OPEN:
423 logHistogram(context, COUNT_OPEN_MIME, sanitizeMime(intent.getType()));
424 break;
425 case State.ACTION_CREATE:
426 logHistogram(context, COUNT_CREATE_MIME, sanitizeMime(intent.getType()));
427 break;
428 case State.ACTION_GET_CONTENT:
429 logHistogram(context, COUNT_GET_CONTENT_MIME, sanitizeMime(intent.getType()));
430 break;
Ben Kwa1c0a3892016-01-26 11:50:03 -0800431 case State.ACTION_BROWSE:
432 logHistogram(context, COUNT_BROWSE_ROOT, sanitizeRoot(uri));
433 break;
434 default:
435 break;
436 }
437 }
438
439 /**
Garfield Tan935c5132017-01-12 14:16:08 -0800440 * Logs when DocumentsUI are launched with {@link DocumentsContract#EXTRA_INITIAL_URI}.
441 *
442 * @param context
443 * @param state used to resolve action
444 * @param rootUri the resolved rootUri, or {@code null} if the provider doesn't
445 * support {@link DocumentsProvider#findDocumentPath(String, String)}
446 */
447 public static void logLaunchAtLocation(Context context, State state, @Nullable Uri rootUri) {
448 switch (state.action) {
Garfield Tanf8969d62017-02-02 16:55:55 -0800449 case State.ACTION_BROWSE:
450 logHistogram(context, COUNT_BROWSE_AT_LOCATION, sanitizeRoot(rootUri));
451 break;
Garfield Tan935c5132017-01-12 14:16:08 -0800452 case State.ACTION_CREATE:
453 logHistogram(context, COUNT_CREATE_AT_LOCATION, sanitizeRoot(rootUri));
454 break;
455 case State.ACTION_GET_CONTENT:
456 logHistogram(context, COUNT_GET_CONTENT_AT_LOCATION, sanitizeRoot(rootUri));
457 break;
458 case State.ACTION_OPEN:
459 logHistogram(context, COUNT_OPEN_AT_LOCATION, sanitizeRoot(rootUri));
460 break;
461 }
462 }
463
464 /**
Garfield Tan045ce6b2017-01-19 16:17:04 -0800465 * Logs a root visited event in file managers. Call this when the user
466 * taps on a root in {@link com.android.documentsui.sidebar.RootsFragment}.
Ben Kwa1c0a3892016-01-26 11:50:03 -0800467 *
468 * @param context
Garfield Tan045ce6b2017-01-19 16:17:04 -0800469 * @param scope
Ben Kwa1c0a3892016-01-26 11:50:03 -0800470 * @param info
471 */
Garfield Tan045ce6b2017-01-19 16:17:04 -0800472 public static void logRootVisited(
473 Context context, @ContextScope int scope, RootInfo info) {
474 switch (scope) {
475 case FILES_SCOPE:
476 logHistogram(context, COUNT_ROOT_VISITED_IN_MANAGER,
477 sanitizeRoot(info));
478 break;
479 case PICKER_SCOPE:
480 logHistogram(context, COUNT_ROOT_VISITED_IN_PICKER,
481 sanitizeRoot(info));
482 break;
483 }
Ben Kwa1c0a3892016-01-26 11:50:03 -0800484 }
485
486 /**
Garfield Tan045ce6b2017-01-19 16:17:04 -0800487 * Logs an app visited event in file pickers. Call this when the user visits
488 * on an app in the RootsFragment.
Ben Kwa1c0a3892016-01-26 11:50:03 -0800489 *
490 * @param context
491 * @param info
492 */
493 public static void logAppVisited(Context context, ResolveInfo info) {
Garfield Tan045ce6b2017-01-19 16:17:04 -0800494 logHistogram(context, COUNT_ROOT_VISITED_IN_PICKER, sanitizeRoot(info));
Ben Kwa1c0a3892016-01-26 11:50:03 -0800495 }
496
497 /**
Ben Kwafaa27202016-01-28 16:39:57 -0800498 * Logs file operation stats. Call this when a file operation has completed. The given
499 * DocumentInfo is only used to distinguish broad categories of actions (e.g. copying from one
500 * provider to another vs copying within a given provider). No PII is logged.
501 *
502 * @param context
503 * @param operationType
504 * @param srcs
505 * @param dst
506 */
507 public static void logFileOperation(
508 Context context,
509 @OpType int operationType,
510 List<DocumentInfo> srcs,
511 @Nullable DocumentInfo dst) {
Steve McKay99f1dc32016-12-29 16:02:01 -0800512
513 ProviderCounts counts = new ProviderCounts();
514 countProviders(counts, srcs, dst);
Ben Kwafaa27202016-01-28 16:39:57 -0800515
516 if (counts.intraProvider > 0) {
517 logIntraProviderFileOps(context, dst.authority, operationType);
518 }
519 if (counts.systemProvider > 0) {
520 // Log file operations on system providers.
521 logInterProviderFileOps(context, COUNT_FILEOP_SYSTEM, dst, operationType);
522 }
523 if (counts.externalProvider > 0) {
524 // Log file operations on external providers.
525 logInterProviderFileOps(context, COUNT_FILEOP_EXTERNAL, dst, operationType);
526 }
527 }
528
Garfield Tan331de982017-04-19 16:22:00 -0700529 public static void logFileOperated(
530 Context context, @OpType int operationType, @FileOpMode int approach) {
531 switch (operationType) {
532 case FileOperationService.OPERATION_COPY:
533 logHistogram(context, COUNT_FILE_COPIED, approach);
534 break;
535 case FileOperationService.OPERATION_MOVE:
536 logHistogram(context, COUNT_FILE_MOVED, approach);
537 break;
538 }
539 }
540
Ben Kwafaa27202016-01-28 16:39:57 -0800541 /**
Aga Wronska46a868a2016-03-30 10:57:04 -0700542 * Logs create directory operation. It is a part of file operation stats. We do not
543 * differentiate between internal and external locations, all create directory operations are
544 * logged under COUNT_FILEOP_SYSTEM. Call this when a create directory operation has completed.
545 *
546 * @param context
547 */
548 public static void logCreateDirOperation(Context context) {
549 logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_CREATE_DIR);
550 }
551
552 /**
553 * Logs rename file operation. It is a part of file operation stats. We do not differentiate
554 * between internal and external locations, all rename operations are logged under
555 * COUNT_FILEOP_SYSTEM. Call this when a rename file operation has completed.
556 *
557 * @param context
558 */
559 public static void logRenameFileOperation(Context context) {
560 logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_RENAME);
561 }
562
563 /**
Ben Kwafaa27202016-01-28 16:39:57 -0800564 * Logs some kind of file operation error. Call this when a file operation (e.g. copy, delete)
565 * fails.
566 *
567 * @param context
568 * @param operationType
569 * @param failedFiles
570 */
571 public static void logFileOperationErrors(Context context, @OpType int operationType,
Steve McKay99f1dc32016-12-29 16:02:01 -0800572 List<DocumentInfo> failedFiles, List<Uri> failedUris) {
573
574 ProviderCounts counts = new ProviderCounts();
575 countProviders(counts, failedFiles, null);
576
577 // TODO: Report URI errors separate from file operation errors.
578 countProviders(counts, failedUris);
Ben Kwafaa27202016-01-28 16:39:57 -0800579
580 @FileOp int opCode = FILEOP_OTHER_ERROR;
581 switch (operationType) {
582 case FileOperationService.OPERATION_COPY:
583 opCode = FILEOP_COPY_ERROR;
584 break;
Tomasz Mikolajewski4f225492017-01-27 16:29:30 +0900585 case FileOperationService.OPERATION_COMPRESS:
586 opCode = FILEOP_COMPRESS_ERROR;
587 break;
588 case FileOperationService.OPERATION_EXTRACT:
589 opCode = FILEOP_EXTRACT_ERROR;
590 break;
Ben Kwafaa27202016-01-28 16:39:57 -0800591 case FileOperationService.OPERATION_DELETE:
592 opCode = FILEOP_DELETE_ERROR;
593 break;
594 case FileOperationService.OPERATION_MOVE:
595 opCode = FILEOP_MOVE_ERROR;
596 break;
597 }
598 if (counts.systemProvider > 0) {
599 logHistogram(context, COUNT_FILEOP_SYSTEM, opCode);
600 }
601 if (counts.externalProvider > 0) {
602 logHistogram(context, COUNT_FILEOP_EXTERNAL, opCode);
603 }
604 }
605
Garfield Tan02fd92f2017-01-13 15:28:30 -0800606 public static void logFileOperationFailure(
607 Context context, @SubFileOp int subFileOp, Uri docUri) {
608 final String authority = docUri.getAuthority();
609 switch (authority) {
610 case Providers.AUTHORITY_MEDIA:
611 logHistogram(context, COUNT_MEDIA_FILEOP_FAILURE, subFileOp);
612 break;
613 case Providers.AUTHORITY_STORAGE:
614 logStorageFileOperationFailure(context, subFileOp, docUri);
615 break;
616 case Providers.AUTHORITY_DOWNLOADS:
617 logHistogram(context, COUNT_DOWNLOADS_FILEOP_FAILURE, subFileOp);
618 break;
619 case Providers.AUTHORITY_MTP:
620 logHistogram(context, COUNT_MTP_FILEOP_FAILURE, subFileOp);
621 break;
622 default:
623 logHistogram(context, COUNT_OTHER_FILEOP_FAILURE, subFileOp);
624 break;
625 }
626 }
627
Ben Kwafaa27202016-01-28 16:39:57 -0800628 /**
Aga Wronska46a868a2016-03-30 10:57:04 -0700629 * Logs create directory operation error. We do not differentiate between internal and external
630 * locations, all create directory errors are logged under COUNT_FILEOP_SYSTEM. Call this when a
631 * create directory operation fails.
632 *
633 * @param context
634 */
635 public static void logCreateDirError(Context context) {
Aga Wronska94e53e42016-04-07 13:09:58 -0700636 logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_CREATE_DIR_ERROR);
Aga Wronska46a868a2016-03-30 10:57:04 -0700637 }
638
639 /**
640 * Logs rename file operation error. We do not differentiate between internal and external
641 * locations, all rename errors are logged under COUNT_FILEOP_SYSTEM. Call this
642 * when a rename file operation fails.
643 *
644 * @param context
645 */
646 public static void logRenameFileError(Context context) {
647 logHistogram(context, COUNT_FILEOP_SYSTEM, FILEOP_RENAME_ERROR);
648 }
649
650 /**
Daichi Hirono320a08f2016-03-25 19:04:39 +0900651 * Logs the cancellation of a file operation. Call this when a Job is canceled.
Ben Kwafaa27202016-01-28 16:39:57 -0800652 * @param context
653 * @param operationType
654 */
655 public static void logFileOperationCancelled(Context context, @OpType int operationType) {
Ben Kwab41a5ed2016-02-17 16:06:22 -0800656 logHistogram(context, COUNT_FILEOP_CANCELED, toMetricsOpType(operationType));
Ben Kwafaa27202016-01-28 16:39:57 -0800657 }
658
Daichi Hirono320a08f2016-03-25 19:04:39 +0900659 /**
660 * Logs startup time in milliseconds.
661 * @param context
662 * @param startupMs Startup time in milliseconds.
663 */
664 public static void logStartupMs(Context context, int startupMs) {
665 logHistogram(context, COUNT_STARTUP_MS, startupMs);
666 }
667
Ben Kwafaa27202016-01-28 16:39:57 -0800668 private static void logInterProviderFileOps(
669 Context context,
670 String histogram,
671 DocumentInfo dst,
672 @OpType int operationType) {
673 if (operationType == FileOperationService.OPERATION_DELETE) {
674 logHistogram(context, histogram, FILEOP_DELETE);
675 } else {
Steve McKay0af8afd2016-02-25 13:34:03 -0800676 assert(dst != null);
Ben Kwafaa27202016-01-28 16:39:57 -0800677 @Provider int providerType =
678 isSystemProvider(dst.authority) ? PROVIDER_SYSTEM : PROVIDER_EXTERNAL;
679 logHistogram(context, histogram, getOpCode(operationType, providerType));
680 }
681 }
682
683 private static void logIntraProviderFileOps(
684 Context context, String authority, @OpType int operationType) {
685 // Find the right histogram to log to, then log the operation.
686 String histogram = isSystemProvider(authority) ? COUNT_FILEOP_SYSTEM : COUNT_FILEOP_EXTERNAL;
687 logHistogram(context, histogram, getOpCode(operationType, PROVIDER_INTRA));
688 }
689
690 /**
Aga Wronska94e53e42016-04-07 13:09:58 -0700691 * Logs the action that was started by user.
Aga Wronska4972d712016-03-30 13:55:19 -0700692 * @param context
Aga Wronska94e53e42016-04-07 13:09:58 -0700693 * @param userAction
Aga Wronska4972d712016-03-30 13:55:19 -0700694 */
Aga Wronska94e53e42016-04-07 13:09:58 -0700695 public static void logUserAction(Context context, @UserAction int userAction) {
696 logHistogram(context, COUNT_USER_ACTION, userAction);
Aga Wronska4972d712016-03-30 13:55:19 -0700697 }
698
Garfield Tan02fd92f2017-01-13 15:28:30 -0800699 private static void logStorageFileOperationFailure(
700 Context context, @SubFileOp int subFileOp, Uri docUri) {
701 assert(Providers.AUTHORITY_STORAGE.equals(docUri.getAuthority()));
702
703 boolean isInternal;
704 try (ContentProviderClient client = acquireUnstableProviderOrThrow(
705 context.getContentResolver(), Providers.AUTHORITY_STORAGE)) {
706 final Path path = DocumentsContract.findDocumentPath(client, docUri);
707
Jon Mann9bd40992017-03-24 12:34:34 -0700708 final ProvidersAccess providers = DocumentsApplication.getProvidersCache(context);
709 final RootInfo root = providers.getRootOneshot(
Garfield Tan02fd92f2017-01-13 15:28:30 -0800710 Providers.AUTHORITY_STORAGE, path.getRootId());
711 isInternal = !root.supportsEject();
712 } catch (RemoteException | RuntimeException e) {
713 Log.e(TAG, "Failed to obtain its root info. Log the metrics as internal.", e);
714 // It's not very likely to have an external storage so log it as internal.
715 isInternal = true;
716 }
717
718 final String histogram = isInternal
719 ? COUNT_INTERNAL_STORAGE_FILEOP_FAILURE
720 : COUNT_EXTERNAL_STORAGE_FILEOP_FAILURE;
721 logHistogram(context, histogram, subFileOp);
722 }
723
Aga Wronska4972d712016-03-30 13:55:19 -0700724 /**
Ben Kwa1c0a3892016-01-26 11:50:03 -0800725 * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
726 *
727 * @param context
728 * @param name The counter to increment.
729 */
730 private static void logCount(Context context, String name) {
731 if (DEBUG) Log.d(TAG, name + ": " + 1);
732 MetricsLogger.count(context, name, 1);
733 }
734
735 /**
736 * Internal method for making a MetricsLogger.histogram call.
737 *
738 * @param context
739 * @param name The name of the histogram.
740 * @param bucket The bucket to increment.
741 */
Aga Wronska6d50bcc2016-03-28 17:27:02 -0700742 private static void logHistogram(Context context, String name, @ActionType int bucket) {
Ben Kwa1c0a3892016-01-26 11:50:03 -0800743 if (DEBUG) Log.d(TAG, name + ": " + bucket);
744 MetricsLogger.histogram(context, name, bucket);
745 }
746
747 /**
748 * Generates an integer identifying the given root. For privacy, this function only recognizes a
749 * small set of hard-coded roots (ones provided by the system). Other roots are all grouped into
750 * a single ROOT_OTHER bucket.
751 */
Ben Kwafaa27202016-01-28 16:39:57 -0800752 private static @Root int sanitizeRoot(Uri uri) {
Tomasz Mikolajewski63e2aae2016-02-01 12:01:14 +0900753 if (uri == null || uri.getAuthority() == null || LauncherActivity.isLaunchUri(uri)) {
Ben Kwa1c0a3892016-01-26 11:50:03 -0800754 return ROOT_NONE;
755 }
756
757 switch (uri.getAuthority()) {
Steve McKay8659cbc2016-10-31 13:13:36 -0700758 case Providers.AUTHORITY_MEDIA:
Ben Kwa1c0a3892016-01-26 11:50:03 -0800759 switch (DocumentsContract.getRootId(uri)) {
Steve McKay8659cbc2016-10-31 13:13:36 -0700760 case Providers.ROOT_ID_AUDIO:
Ben Kwa1c0a3892016-01-26 11:50:03 -0800761 return ROOT_AUDIO;
Steve McKay8659cbc2016-10-31 13:13:36 -0700762 case Providers.ROOT_ID_IMAGES:
Ben Kwa1c0a3892016-01-26 11:50:03 -0800763 return ROOT_IMAGES;
Steve McKay8659cbc2016-10-31 13:13:36 -0700764 case Providers.ROOT_ID_VIDEOS:
Ben Kwa1c0a3892016-01-26 11:50:03 -0800765 return ROOT_VIDEOS;
766 default:
767 return ROOT_OTHER;
768 }
Steve McKay8659cbc2016-10-31 13:13:36 -0700769 case Providers.AUTHORITY_STORAGE:
770 if (Providers.ROOT_ID_HOME.equals(DocumentsContract.getRootId(uri))) {
Ben Kwa1c0a3892016-01-26 11:50:03 -0800771 return ROOT_HOME;
772 } else {
773 return ROOT_DEVICE_STORAGE;
774 }
Steve McKay8659cbc2016-10-31 13:13:36 -0700775 case Providers.AUTHORITY_DOWNLOADS:
Ben Kwa1c0a3892016-01-26 11:50:03 -0800776 return ROOT_DOWNLOADS;
Steve McKay8659cbc2016-10-31 13:13:36 -0700777 case Providers.AUTHORITY_MTP:
Ben Kwaebaaea42016-01-28 18:15:07 -0800778 return ROOT_MTP;
Ben Kwa1c0a3892016-01-26 11:50:03 -0800779 default:
780 return ROOT_OTHER;
781 }
782 }
783
784 /** @see #sanitizeRoot(Uri) */
Ben Kwafaa27202016-01-28 16:39:57 -0800785 private static @Root int sanitizeRoot(RootInfo root) {
Ben Kwa1c0a3892016-01-26 11:50:03 -0800786 if (root.isRecents()) {
787 // Recents root is special and only identifiable via this method call. Other roots are
788 // identified by URI.
789 return ROOT_RECENTS;
790 } else {
791 return sanitizeRoot(root.getUri());
792 }
793 }
794
795 /** @see #sanitizeRoot(Uri) */
Ben Kwafaa27202016-01-28 16:39:57 -0800796 private static @Root int sanitizeRoot(ResolveInfo info) {
Ben Kwa1c0a3892016-01-26 11:50:03 -0800797 // Log all apps under a single bucket in the roots histogram.
798 return ROOT_THIRD_PARTY_APP;
799 }
800
801 /**
802 * Generates an int identifying a mime type. For privacy, this function only recognizes a small
803 * set of hard-coded types. For any other type, this function returns "other".
804 *
805 * @param mimeType
806 * @return
807 */
Ben Kwafaa27202016-01-28 16:39:57 -0800808 private static @Mime int sanitizeMime(String mimeType) {
Ben Kwa1c0a3892016-01-26 11:50:03 -0800809 if (mimeType == null) {
810 return MIME_NONE;
811 } else if ("*/*".equals(mimeType)) {
812 return MIME_ANY;
813 } else {
814 String type = mimeType.substring(0, mimeType.indexOf('/'));
815 switch (type) {
816 case "application":
817 return MIME_APPLICATION;
818 case "audio":
819 return MIME_AUDIO;
820 case "image":
821 return MIME_IMAGE;
822 case "message":
823 return MIME_MESSAGE;
824 case "multipart":
825 return MIME_MULTIPART;
826 case "text":
827 return MIME_TEXT;
828 case "video":
829 return MIME_VIDEO;
830 }
831 }
832 // Bucket all other types into one bucket.
833 return MIME_OTHER;
834 }
Ben Kwafaa27202016-01-28 16:39:57 -0800835
836 private static boolean isSystemProvider(String authority) {
837 switch (authority) {
Steve McKay8659cbc2016-10-31 13:13:36 -0700838 case Providers.AUTHORITY_MEDIA:
839 case Providers.AUTHORITY_STORAGE:
840 case Providers.AUTHORITY_DOWNLOADS:
Ben Kwafaa27202016-01-28 16:39:57 -0800841 return true;
842 default:
843 return false;
844 }
845 }
846
847 /**
848 * @param operation
849 * @param providerType
850 * @return An opcode, suitable for use as histogram bucket, for the given operation/provider
851 * combination.
852 */
853 private static @FileOp int getOpCode(@OpType int operation, @Provider int providerType) {
854 switch (operation) {
855 case FileOperationService.OPERATION_COPY:
856 switch (providerType) {
857 case PROVIDER_INTRA:
858 return FILEOP_COPY_INTRA_PROVIDER;
859 case PROVIDER_SYSTEM:
860 return FILEOP_COPY_SYSTEM_PROVIDER;
861 case PROVIDER_EXTERNAL:
862 return FILEOP_COPY_EXTERNAL_PROVIDER;
863 }
Tomasz Mikolajewski4f225492017-01-27 16:29:30 +0900864 case FileOperationService.OPERATION_COMPRESS:
865 switch (providerType) {
866 case PROVIDER_INTRA:
867 return FILEOP_COMPRESS_INTRA_PROVIDER;
868 case PROVIDER_SYSTEM:
869 return FILEOP_COMPRESS_SYSTEM_PROVIDER;
870 case PROVIDER_EXTERNAL:
871 return FILEOP_COMPRESS_EXTERNAL_PROVIDER;
872 }
873 case FileOperationService.OPERATION_EXTRACT:
874 switch (providerType) {
875 case PROVIDER_INTRA:
876 return FILEOP_EXTRACT_INTRA_PROVIDER;
877 case PROVIDER_SYSTEM:
878 return FILEOP_EXTRACT_SYSTEM_PROVIDER;
879 case PROVIDER_EXTERNAL:
880 return FILEOP_EXTRACT_EXTERNAL_PROVIDER;
881 }
Ben Kwafaa27202016-01-28 16:39:57 -0800882 case FileOperationService.OPERATION_MOVE:
883 switch (providerType) {
884 case PROVIDER_INTRA:
885 return FILEOP_MOVE_INTRA_PROVIDER;
886 case PROVIDER_SYSTEM:
887 return FILEOP_MOVE_SYSTEM_PROVIDER;
888 case PROVIDER_EXTERNAL:
889 return FILEOP_MOVE_EXTERNAL_PROVIDER;
890 }
891 case FileOperationService.OPERATION_DELETE:
892 return FILEOP_DELETE;
893 default:
894 Log.w(TAG, "Unrecognized operation type when logging a file operation");
895 return FILEOP_OTHER;
896 }
897 }
898
899 /**
Ben Kwab41a5ed2016-02-17 16:06:22 -0800900 * Maps FileOperationService OpType values, to MetricsOpType values.
901 */
902 private static @MetricsOpType int toMetricsOpType(@OpType int operation) {
903 switch (operation) {
904 case FileOperationService.OPERATION_COPY:
905 return OPERATION_COPY;
906 case FileOperationService.OPERATION_MOVE:
907 return OPERATION_MOVE;
908 case FileOperationService.OPERATION_DELETE:
909 return OPERATION_DELETE;
910 case FileOperationService.OPERATION_UNKNOWN:
911 default:
912 return OPERATION_UNKNOWN;
913 }
914 }
915
916 private static @MetricsAction int toMetricsAction(int action) {
917 switch(action) {
918 case State.ACTION_OPEN:
919 return ACTION_OPEN;
920 case State.ACTION_CREATE:
921 return ACTION_CREATE;
922 case State.ACTION_GET_CONTENT:
923 return ACTION_GET_CONTENT;
924 case State.ACTION_OPEN_TREE:
925 return ACTION_OPEN_TREE;
Ben Kwab41a5ed2016-02-17 16:06:22 -0800926 case State.ACTION_BROWSE:
927 return ACTION_BROWSE;
928 case State.ACTION_PICK_COPY_DESTINATION:
929 return ACTION_PICK_COPY_DESTINATION;
930 default:
931 return ACTION_OTHER;
932 }
933 }
934
935 /**
Ben Kwafaa27202016-01-28 16:39:57 -0800936 * Count the given src documents and provide a tally of how many come from the same provider as
937 * the dst document (if a dst is provided), how many come from system providers, and how many
938 * come from external 3rd-party providers.
939 */
Steve McKay99f1dc32016-12-29 16:02:01 -0800940 private static void countProviders(
941 ProviderCounts counts, List<DocumentInfo> srcs, @Nullable DocumentInfo dst) {
Ben Kwafaa27202016-01-28 16:39:57 -0800942 for (DocumentInfo doc: srcs) {
Steve McKay99f1dc32016-12-29 16:02:01 -0800943 countForAuthority(counts, doc.authority, dst);
Ben Kwafaa27202016-01-28 16:39:57 -0800944 }
Steve McKay99f1dc32016-12-29 16:02:01 -0800945 }
946
947 /**
948 * Count the given uris and provide a tally of how many come from the same provider as
949 * the dst document (if a dst is provided), how many come from system providers, and how many
950 * come from external 3rd-party providers.
951 */
952 private static void countProviders(ProviderCounts counts, List<Uri> uris) {
953 for (Uri uri: uris) {
954 countForAuthority(counts, uri.getAuthority(), null);
955 }
956 }
957
958 private static void countForAuthority(
959 ProviderCounts counts, String authority, @Nullable DocumentInfo dst) {
960 if (dst != null && authority.equals(dst.authority)) {
961 counts.intraProvider++;
962 } else if (isSystemProvider(authority)){
963 counts.systemProvider++;
964 } else {
965 counts.externalProvider++;
966 }
Ben Kwafaa27202016-01-28 16:39:57 -0800967 }
968
969 private static class ProviderCounts {
970 int intraProvider;
971 int systemProvider;
972 int externalProvider;
973 }
Ben Kwa1c0a3892016-01-26 11:50:03 -0800974}