Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 1 | /* |
| 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 | |
| 17 | package com.android.documentsui; |
| 18 | |
Jeff Sharkey | 2c0b485 | 2019-02-15 15:53:47 -0700 | [diff] [blame] | 19 | import static android.content.ContentResolver.wrap; |
| 20 | |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 21 | import static com.android.documentsui.DocumentsApplication.acquireUnstableProviderOrThrow; |
Steve McKay | 15b9278 | 2016-03-09 15:20:00 -0800 | [diff] [blame] | 22 | |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 23 | import android.content.ContentProviderClient; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 24 | import android.content.Context; |
| 25 | import android.content.Intent; |
| 26 | import android.content.pm.ResolveInfo; |
| 27 | import android.net.Uri; |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 28 | import android.os.RemoteException; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 29 | import android.provider.DocumentsContract; |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 30 | import android.provider.DocumentsContract.Path; |
Garfield Tan | 935c513 | 2017-01-12 14:16:08 -0800 | [diff] [blame] | 31 | import android.provider.DocumentsProvider; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 32 | import android.util.Log; |
| 33 | |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 34 | import androidx.annotation.Nullable; |
| 35 | |
Steve McKay | d080506 | 2016-09-15 14:30:38 -0700 | [diff] [blame] | 36 | import com.android.documentsui.base.DocumentInfo; |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 37 | import com.android.documentsui.base.Providers; |
Steve McKay | d080506 | 2016-09-15 14:30:38 -0700 | [diff] [blame] | 38 | import com.android.documentsui.base.RootInfo; |
Steve McKay | d9caa6a | 2016-09-15 16:36:45 -0700 | [diff] [blame] | 39 | import com.android.documentsui.base.State; |
Steve McKay | b6006b2 | 2016-09-29 09:23:45 -0700 | [diff] [blame] | 40 | import com.android.documentsui.files.LauncherActivity; |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 41 | import com.android.documentsui.picker.PickResult; |
Jon Mann | 9bd4099 | 2017-03-24 12:34:34 -0700 | [diff] [blame] | 42 | import com.android.documentsui.roots.ProvidersAccess; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 43 | import com.android.documentsui.services.FileOperationService; |
| 44 | import com.android.documentsui.services.FileOperationService.OpType; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 45 | |
Jeff Sharkey | 844989e | 2018-12-07 15:16:08 -0700 | [diff] [blame] | 46 | import java.io.FileNotFoundException; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 47 | import java.util.List; |
| 48 | |
Leif Hendrik Wilden | 4205349 | 2018-01-03 11:16:09 -0800 | [diff] [blame] | 49 | /** |
| 50 | * Methods for logging metrics. |
| 51 | */ |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 52 | public final class Metrics { |
| 53 | private static final String TAG = "Metrics"; |
| 54 | |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 55 | /** |
| 56 | * Logs when DocumentsUI is started, and how. Call this when DocumentsUI first starts up. |
| 57 | * |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 58 | * @param state |
| 59 | * @param intent |
| 60 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 61 | public static void logActivityLaunch(State state, Intent intent) { |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 62 | Uri uri = intent.getData(); |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 63 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_LAUNCH_REPORTED, |
| 64 | toMetricsAction(state.action), false, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 65 | sanitizeMime(intent.getType()), sanitizeRoot(uri)); |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | /** |
Garfield Tan | 935c513 | 2017-01-12 14:16:08 -0800 | [diff] [blame] | 69 | * Logs when DocumentsUI are launched with {@link DocumentsContract#EXTRA_INITIAL_URI}. |
| 70 | * |
Garfield Tan | 935c513 | 2017-01-12 14:16:08 -0800 | [diff] [blame] | 71 | * @param state used to resolve action |
| 72 | * @param rootUri the resolved rootUri, or {@code null} if the provider doesn't |
| 73 | * support {@link DocumentsProvider#findDocumentPath(String, String)} |
| 74 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 75 | public static void logLaunchAtLocation(State state, @Nullable Uri rootUri) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 76 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_LAUNCH_REPORTED, |
| 77 | toMetricsAction(state.action), true, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 78 | MetricConsts.MIME_UNKNOWN, sanitizeRoot(rootUri)); |
Garfield Tan | 935c513 | 2017-01-12 14:16:08 -0800 | [diff] [blame] | 79 | } |
| 80 | |
| 81 | /** |
Garfield Tan | 045ce6b | 2017-01-19 16:17:04 -0800 | [diff] [blame] | 82 | * Logs a root visited event in file managers. Call this when the user |
| 83 | * taps on a root in {@link com.android.documentsui.sidebar.RootsFragment}. |
Garfield Tan | 045ce6b | 2017-01-19 16:17:04 -0800 | [diff] [blame] | 84 | * @param scope |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 85 | * @param info |
| 86 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 87 | public static void logRootVisited(@MetricConsts.ContextScope int scope, RootInfo info) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 88 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_ROOT_VISITED, scope, sanitizeRoot(info)); |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | /** |
Garfield Tan | 045ce6b | 2017-01-19 16:17:04 -0800 | [diff] [blame] | 92 | * Logs an app visited event in file pickers. Call this when the user visits |
| 93 | * on an app in the RootsFragment. |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 94 | * |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 95 | * @param info |
| 96 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 97 | public static void logAppVisited(ResolveInfo info) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 98 | DocumentsStatsLog.write( |
| 99 | DocumentsStatsLog.DOCS_UI_ROOT_VISITED, |
| 100 | MetricConsts.PICKER_SCOPE, sanitizeRoot(info)); |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | /** |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 104 | * Logs file operation stats. Call this when a file operation has completed. The given |
| 105 | * DocumentInfo is only used to distinguish broad categories of actions (e.g. copying from one |
| 106 | * provider to another vs copying within a given provider). No PII is logged. |
| 107 | * |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 108 | * @param operationType |
| 109 | * @param srcs |
| 110 | * @param dst |
| 111 | */ |
| 112 | public static void logFileOperation( |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 113 | @OpType int operationType, |
| 114 | List<DocumentInfo> srcs, |
| 115 | @Nullable DocumentInfo dst) { |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 116 | ProviderCounts counts = new ProviderCounts(); |
| 117 | countProviders(counts, srcs, dst); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 118 | if (counts.intraProvider > 0) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 119 | logIntraProviderFileOps(dst.authority, operationType); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 120 | } |
| 121 | if (counts.systemProvider > 0) { |
| 122 | // Log file operations on system providers. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 123 | logInterProviderFileOps(MetricConsts.PROVIDER_SYSTEM, dst, operationType); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 124 | } |
| 125 | if (counts.externalProvider > 0) { |
| 126 | // Log file operations on external providers. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 127 | logInterProviderFileOps(MetricConsts.PROVIDER_EXTERNAL, dst, operationType); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 128 | } |
| 129 | } |
| 130 | |
Garfield Tan | 331de98 | 2017-04-19 16:22:00 -0700 | [diff] [blame] | 131 | public static void logFileOperated( |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 132 | @OpType int operationType, @MetricConsts.FileOpMode int approach) { |
Garfield Tan | 331de98 | 2017-04-19 16:22:00 -0700 | [diff] [blame] | 133 | switch (operationType) { |
| 134 | case FileOperationService.OPERATION_COPY: |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 135 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 136 | MetricConsts.FILEOP_COPY, approach); |
Garfield Tan | 331de98 | 2017-04-19 16:22:00 -0700 | [diff] [blame] | 137 | break; |
| 138 | case FileOperationService.OPERATION_MOVE: |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 139 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_FILE_OP_COPY_MOVE_MODE_REPORTED, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 140 | MetricConsts.FILEOP_MOVE, approach); |
Garfield Tan | 331de98 | 2017-04-19 16:22:00 -0700 | [diff] [blame] | 141 | break; |
| 142 | } |
| 143 | } |
| 144 | |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 145 | /** |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 146 | * Logs create directory operation. It is a part of file operation stats. We do not |
| 147 | * differentiate between internal and external locations, all create directory operations are |
| 148 | * logged under COUNT_FILEOP_SYSTEM. Call this when a create directory operation has completed. |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 149 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 150 | public static void logCreateDirOperation() { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 151 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 152 | MetricConsts.PROVIDER_SYSTEM, MetricConsts.FILEOP_CREATE_DIR); |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | /** |
| 156 | * Logs rename file operation. It is a part of file operation stats. We do not differentiate |
| 157 | * between internal and external locations, all rename operations are logged under |
| 158 | * COUNT_FILEOP_SYSTEM. Call this when a rename file operation has completed. |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 159 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 160 | public static void logRenameFileOperation() { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 161 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 162 | MetricConsts.PROVIDER_SYSTEM, MetricConsts.FILEOP_RENAME); |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | /** |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 166 | * Logs some kind of file operation error. Call this when a file operation (e.g. copy, delete) |
| 167 | * fails. |
| 168 | * |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 169 | * @param operationType |
| 170 | * @param failedFiles |
| 171 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 172 | public static void logFileOperationErrors(@OpType int operationType, |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 173 | List<DocumentInfo> failedFiles, List<Uri> failedUris) { |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 174 | ProviderCounts counts = new ProviderCounts(); |
| 175 | countProviders(counts, failedFiles, null); |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 176 | // TODO: Report URI errors separate from file operation errors. |
| 177 | countProviders(counts, failedUris); |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 178 | @MetricConsts.FileOp int opCode = MetricConsts.FILEOP_OTHER_ERROR; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 179 | switch (operationType) { |
| 180 | case FileOperationService.OPERATION_COPY: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 181 | opCode = MetricConsts.FILEOP_COPY_ERROR; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 182 | break; |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 183 | case FileOperationService.OPERATION_COMPRESS: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 184 | opCode = MetricConsts.FILEOP_COMPRESS_ERROR; |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 185 | break; |
| 186 | case FileOperationService.OPERATION_EXTRACT: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 187 | opCode = MetricConsts.FILEOP_EXTRACT_ERROR; |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 188 | break; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 189 | case FileOperationService.OPERATION_DELETE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 190 | opCode = MetricConsts.FILEOP_DELETE_ERROR; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 191 | break; |
| 192 | case FileOperationService.OPERATION_MOVE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 193 | opCode = MetricConsts.FILEOP_MOVE_ERROR; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 194 | break; |
| 195 | } |
| 196 | if (counts.systemProvider > 0) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 197 | DocumentsStatsLog.write( |
| 198 | DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
| 199 | MetricConsts.PROVIDER_SYSTEM, opCode); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 200 | } |
| 201 | if (counts.externalProvider > 0) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 202 | DocumentsStatsLog.write( |
| 203 | DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
| 204 | MetricConsts.PROVIDER_EXTERNAL, opCode); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 205 | } |
| 206 | } |
| 207 | |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 208 | public static void logFileOperationFailure( |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 209 | Context context, @MetricConsts.SubFileOp int subFileOp, Uri docUri) { |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 210 | final String authority = docUri.getAuthority(); |
| 211 | switch (authority) { |
| 212 | case Providers.AUTHORITY_MEDIA: |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 213 | DocumentsStatsLog.write( |
| 214 | DocumentsStatsLog.DOCS_UI_FILE_OP_FAILURE, |
| 215 | MetricConsts.AUTH_MEDIA, subFileOp); |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 216 | break; |
| 217 | case Providers.AUTHORITY_STORAGE: |
| 218 | logStorageFileOperationFailure(context, subFileOp, docUri); |
| 219 | break; |
| 220 | case Providers.AUTHORITY_DOWNLOADS: |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 221 | DocumentsStatsLog.write( |
| 222 | DocumentsStatsLog.DOCS_UI_FILE_OP_FAILURE, |
| 223 | MetricConsts.AUTH_DOWNLOADS, subFileOp); |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 224 | break; |
| 225 | case Providers.AUTHORITY_MTP: |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 226 | DocumentsStatsLog.write( |
| 227 | DocumentsStatsLog.DOCS_UI_FILE_OP_FAILURE, |
| 228 | MetricConsts.AUTH_MTP, subFileOp); |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 229 | break; |
| 230 | default: |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 231 | DocumentsStatsLog.write( |
| 232 | DocumentsStatsLog.DOCS_UI_FILE_OP_FAILURE, |
| 233 | MetricConsts.AUTH_OTHER, subFileOp); |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 234 | break; |
| 235 | } |
| 236 | } |
| 237 | |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 238 | /** |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 239 | * Logs create directory operation error. We do not differentiate between internal and external |
| 240 | * locations, all create directory errors are logged under COUNT_FILEOP_SYSTEM. Call this when a |
| 241 | * create directory operation fails. |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 242 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 243 | public static void logCreateDirError() { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 244 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 245 | MetricConsts.PROVIDER_SYSTEM, MetricConsts.FILEOP_CREATE_DIR_ERROR); |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 246 | } |
| 247 | |
| 248 | /** |
| 249 | * Logs rename file operation error. We do not differentiate between internal and external |
| 250 | * locations, all rename errors are logged under COUNT_FILEOP_SYSTEM. Call this |
| 251 | * when a rename file operation fails. |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 252 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 253 | public static void logRenameFileError() { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 254 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 255 | MetricConsts.PROVIDER_SYSTEM, MetricConsts.FILEOP_RENAME_ERROR); |
Aga Wronska | 46a868a | 2016-03-30 10:57:04 -0700 | [diff] [blame] | 256 | } |
| 257 | |
| 258 | /** |
Daichi Hirono | 320a08f | 2016-03-25 19:04:39 +0900 | [diff] [blame] | 259 | * Logs the cancellation of a file operation. Call this when a Job is canceled. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 260 | * |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 261 | * @param operationType |
| 262 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 263 | public static void logFileOperationCancelled(@OpType int operationType) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 264 | DocumentsStatsLog.write( |
| 265 | DocumentsStatsLog.DOCS_UI_FILE_OP_CANCELED, toMetricsOpType(operationType)); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 266 | } |
| 267 | |
Daichi Hirono | 320a08f | 2016-03-25 19:04:39 +0900 | [diff] [blame] | 268 | /** |
| 269 | * Logs startup time in milliseconds. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 270 | * |
Daichi Hirono | 320a08f | 2016-03-25 19:04:39 +0900 | [diff] [blame] | 271 | * @param startupMs Startup time in milliseconds. |
| 272 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 273 | public static void logStartupMs(int startupMs) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 274 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_STARTUP_MS, startupMs); |
Daichi Hirono | 320a08f | 2016-03-25 19:04:39 +0900 | [diff] [blame] | 275 | } |
| 276 | |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 277 | private static void logInterProviderFileOps( |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 278 | @MetricConsts.Provider int providerType, |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 279 | DocumentInfo dst, |
| 280 | @OpType int operationType) { |
| 281 | if (operationType == FileOperationService.OPERATION_DELETE) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 282 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
| 283 | providerType, MetricConsts.FILEOP_DELETE); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 284 | } else { |
Steve McKay | 0af8afd | 2016-02-25 13:34:03 -0800 | [diff] [blame] | 285 | assert(dst != null); |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 286 | @MetricConsts.Provider int opProviderType = isSystemProvider(dst.authority) |
| 287 | ? MetricConsts.PROVIDER_SYSTEM : MetricConsts.PROVIDER_EXTERNAL; |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 288 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 289 | providerType, getOpCode(operationType, opProviderType)); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 290 | } |
| 291 | } |
| 292 | |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 293 | private static void logIntraProviderFileOps(String authority, @OpType int operationType) { |
| 294 | @MetricConsts.Provider int providerType = isSystemProvider(authority) |
| 295 | ? MetricConsts.PROVIDER_SYSTEM : MetricConsts.PROVIDER_EXTERNAL; |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 296 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_PROVIDER_FILE_OP, |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 297 | providerType, getOpCode(operationType, MetricConsts.PROVIDER_INTRA)); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 298 | } |
| 299 | |
| 300 | /** |
Aga Wronska | 94e53e4 | 2016-04-07 13:09:58 -0700 | [diff] [blame] | 301 | * Logs the action that was started by user. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 302 | * |
Aga Wronska | 94e53e4 | 2016-04-07 13:09:58 -0700 | [diff] [blame] | 303 | * @param userAction |
Aga Wronska | 4972d71 | 2016-03-30 13:55:19 -0700 | [diff] [blame] | 304 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 305 | public static void logUserAction(@MetricConsts.UserAction int userAction) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 306 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_USER_ACTION_REPORTED, userAction); |
Aga Wronska | 4972d71 | 2016-03-30 13:55:19 -0700 | [diff] [blame] | 307 | } |
| 308 | |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 309 | public static void logPickerLaunchedFrom(String packgeName) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 310 | DocumentsStatsLog.write( |
| 311 | DocumentsStatsLog.DOCS_UI_PICKER_LAUNCHED_FROM_REPORTED, packgeName); |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 312 | } |
| 313 | |
| 314 | public static void logSearchType(int searchType) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 315 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_SEARCH_TYPE_REPORTED, searchType); |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 316 | } |
| 317 | |
| 318 | public static void logSearchMode(boolean isKeywordSearch, boolean isChipsSearch) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 319 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_SEARCH_MODE_REPORTED, |
| 320 | getSearchMode(isKeywordSearch, isChipsSearch)); |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 321 | } |
| 322 | |
| 323 | public static void logPickResult(PickResult result) { |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 324 | DocumentsStatsLog.write( |
| 325 | DocumentsStatsLog.DOCS_UI_PICK_RESULT_REPORTED, |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 326 | result.getActionCount(), |
| 327 | result.getDuration(), |
| 328 | result.getFileCount(), |
| 329 | result.isSearching(), |
| 330 | result.getRoot(), |
| 331 | result.getMimeType(), |
| 332 | result.getRepeatedPickTimes()); |
| 333 | } |
| 334 | |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 335 | private static void logStorageFileOperationFailure( |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 336 | Context context, @MetricConsts.SubFileOp int subFileOp, Uri docUri) { |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 337 | assert(Providers.AUTHORITY_STORAGE.equals(docUri.getAuthority())); |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 338 | boolean isInternal; |
| 339 | try (ContentProviderClient client = acquireUnstableProviderOrThrow( |
| 340 | context.getContentResolver(), Providers.AUTHORITY_STORAGE)) { |
Jeff Sharkey | 2c0b485 | 2019-02-15 15:53:47 -0700 | [diff] [blame] | 341 | final Path path = DocumentsContract.findDocumentPath(wrap(client), docUri); |
Jon Mann | 9bd4099 | 2017-03-24 12:34:34 -0700 | [diff] [blame] | 342 | final ProvidersAccess providers = DocumentsApplication.getProvidersCache(context); |
| 343 | final RootInfo root = providers.getRootOneshot( |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 344 | Providers.AUTHORITY_STORAGE, path.getRootId()); |
| 345 | isInternal = !root.supportsEject(); |
Jeff Sharkey | 844989e | 2018-12-07 15:16:08 -0700 | [diff] [blame] | 346 | } catch (FileNotFoundException | RemoteException | RuntimeException e) { |
Garfield Tan | 02fd92f | 2017-01-13 15:28:30 -0800 | [diff] [blame] | 347 | Log.e(TAG, "Failed to obtain its root info. Log the metrics as internal.", e); |
| 348 | // It's not very likely to have an external storage so log it as internal. |
| 349 | isInternal = true; |
| 350 | } |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 351 | @MetricConsts.MetricsAuth final int authority = isInternal |
| 352 | ? MetricConsts.AUTH_STORAGE_INTERNAL : MetricConsts.AUTH_STORAGE_EXTERNAL; |
shawnlin | a06573a | 2019-04-09 15:48:43 +0800 | [diff] [blame] | 353 | DocumentsStatsLog.write(DocumentsStatsLog.DOCS_UI_FILE_OP_FAILURE, authority, subFileOp); |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | /** |
| 357 | * Generates an integer identifying the given root. For privacy, this function only recognizes a |
| 358 | * small set of hard-coded roots (ones provided by the system). Other roots are all grouped into |
| 359 | * a single ROOT_OTHER bucket. |
| 360 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 361 | private static @MetricConsts.Root int sanitizeRoot(Uri uri) { |
Tomasz Mikolajewski | 63e2aae | 2016-02-01 12:01:14 +0900 | [diff] [blame] | 362 | if (uri == null || uri.getAuthority() == null || LauncherActivity.isLaunchUri(uri)) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 363 | return MetricConsts.ROOT_NONE; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 364 | } |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 365 | switch (uri.getAuthority()) { |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 366 | case Providers.AUTHORITY_MEDIA: |
felkachang | ec40c5c | 2018-05-14 18:01:11 +0800 | [diff] [blame] | 367 | String rootId = getRootIdSafely(uri); |
| 368 | if (rootId == null) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 369 | return MetricConsts.ROOT_NONE; |
felkachang | ec40c5c | 2018-05-14 18:01:11 +0800 | [diff] [blame] | 370 | } |
| 371 | switch (rootId) { |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 372 | case Providers.ROOT_ID_AUDIO: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 373 | return MetricConsts.ROOT_AUDIO; |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 374 | case Providers.ROOT_ID_IMAGES: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 375 | return MetricConsts.ROOT_IMAGES; |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 376 | case Providers.ROOT_ID_VIDEOS: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 377 | return MetricConsts.ROOT_VIDEOS; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 378 | default: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 379 | return MetricConsts.ROOT_OTHER_DOCS_PROVIDER; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 380 | } |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 381 | case Providers.AUTHORITY_STORAGE: |
felkachang | ec40c5c | 2018-05-14 18:01:11 +0800 | [diff] [blame] | 382 | rootId = getRootIdSafely(uri); |
| 383 | if (rootId == null) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 384 | return MetricConsts.ROOT_NONE; |
felkachang | ec40c5c | 2018-05-14 18:01:11 +0800 | [diff] [blame] | 385 | } |
| 386 | if (Providers.ROOT_ID_HOME.equals(rootId)) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 387 | return MetricConsts.ROOT_HOME; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 388 | } else { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 389 | return MetricConsts.ROOT_DEVICE_STORAGE; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 390 | } |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 391 | case Providers.AUTHORITY_DOWNLOADS: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 392 | return MetricConsts.ROOT_DOWNLOADS; |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 393 | case Providers.AUTHORITY_MTP: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 394 | return MetricConsts.ROOT_MTP; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 395 | default: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 396 | return MetricConsts.ROOT_OTHER_DOCS_PROVIDER; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 397 | } |
| 398 | } |
| 399 | |
| 400 | /** @see #sanitizeRoot(Uri) */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 401 | public static @MetricConsts.Root int sanitizeRoot(RootInfo root) { |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 402 | if (root.isRecents()) { |
| 403 | // Recents root is special and only identifiable via this method call. Other roots are |
| 404 | // identified by URI. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 405 | return MetricConsts.ROOT_RECENTS; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 406 | } else { |
| 407 | return sanitizeRoot(root.getUri()); |
| 408 | } |
| 409 | } |
| 410 | |
| 411 | /** @see #sanitizeRoot(Uri) */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 412 | public static @MetricConsts.Root int sanitizeRoot(ResolveInfo info) { |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 413 | // Log all apps under a single bucket in the roots histogram. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 414 | return MetricConsts.ROOT_THIRD_PARTY_APP; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 415 | } |
| 416 | |
| 417 | /** |
| 418 | * Generates an int identifying a mime type. For privacy, this function only recognizes a small |
| 419 | * set of hard-coded types. For any other type, this function returns "other". |
| 420 | * |
| 421 | * @param mimeType |
| 422 | * @return |
| 423 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 424 | public static @MetricConsts.Mime int sanitizeMime(String mimeType) { |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 425 | if (mimeType == null) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 426 | return MetricConsts.MIME_NONE; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 427 | } else if ("*/*".equals(mimeType)) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 428 | return MetricConsts.MIME_ANY; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 429 | } else { |
| 430 | String type = mimeType.substring(0, mimeType.indexOf('/')); |
| 431 | switch (type) { |
| 432 | case "application": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 433 | return MetricConsts.MIME_APPLICATION; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 434 | case "audio": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 435 | return MetricConsts.MIME_AUDIO; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 436 | case "image": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 437 | return MetricConsts.MIME_IMAGE; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 438 | case "message": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 439 | return MetricConsts.MIME_MESSAGE; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 440 | case "multipart": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 441 | return MetricConsts.MIME_MULTIPART; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 442 | case "text": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 443 | return MetricConsts.MIME_TEXT; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 444 | case "video": |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 445 | return MetricConsts.MIME_VIDEO; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 446 | } |
| 447 | } |
| 448 | // Bucket all other types into one bucket. |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 449 | return MetricConsts.MIME_OTHER; |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 450 | } |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 451 | |
| 452 | private static boolean isSystemProvider(String authority) { |
| 453 | switch (authority) { |
Steve McKay | 8659cbc | 2016-10-31 13:13:36 -0700 | [diff] [blame] | 454 | case Providers.AUTHORITY_MEDIA: |
| 455 | case Providers.AUTHORITY_STORAGE: |
| 456 | case Providers.AUTHORITY_DOWNLOADS: |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 457 | return true; |
| 458 | default: |
| 459 | return false; |
| 460 | } |
| 461 | } |
| 462 | |
| 463 | /** |
| 464 | * @param operation |
| 465 | * @param providerType |
| 466 | * @return An opcode, suitable for use as histogram bucket, for the given operation/provider |
| 467 | * combination. |
| 468 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 469 | private static @MetricConsts.FileOp int getOpCode( |
| 470 | @OpType int operation, @MetricConsts.Provider int providerType) { |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 471 | switch (operation) { |
| 472 | case FileOperationService.OPERATION_COPY: |
| 473 | switch (providerType) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 474 | case MetricConsts.PROVIDER_INTRA: |
| 475 | return MetricConsts.FILEOP_COPY_INTRA_PROVIDER; |
| 476 | case MetricConsts.PROVIDER_SYSTEM: |
| 477 | return MetricConsts.FILEOP_COPY_SYSTEM_PROVIDER; |
| 478 | case MetricConsts.PROVIDER_EXTERNAL: |
| 479 | return MetricConsts.FILEOP_COPY_EXTERNAL_PROVIDER; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 480 | } |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 481 | case FileOperationService.OPERATION_COMPRESS: |
| 482 | switch (providerType) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 483 | case MetricConsts.PROVIDER_INTRA: |
| 484 | return MetricConsts.FILEOP_COMPRESS_INTRA_PROVIDER; |
| 485 | case MetricConsts.PROVIDER_SYSTEM: |
| 486 | return MetricConsts.FILEOP_COMPRESS_SYSTEM_PROVIDER; |
| 487 | case MetricConsts.PROVIDER_EXTERNAL: |
| 488 | return MetricConsts.FILEOP_COMPRESS_EXTERNAL_PROVIDER; |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 489 | } |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 490 | case FileOperationService.OPERATION_EXTRACT: |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 491 | switch (providerType) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 492 | case MetricConsts.PROVIDER_INTRA: |
| 493 | return MetricConsts.FILEOP_EXTRACT_INTRA_PROVIDER; |
| 494 | case MetricConsts.PROVIDER_SYSTEM: |
| 495 | return MetricConsts.FILEOP_EXTRACT_SYSTEM_PROVIDER; |
| 496 | case MetricConsts.PROVIDER_EXTERNAL: |
| 497 | return MetricConsts.FILEOP_EXTRACT_EXTERNAL_PROVIDER; |
Tomasz Mikolajewski | 4f22549 | 2017-01-27 16:29:30 +0900 | [diff] [blame] | 498 | } |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 499 | case FileOperationService.OPERATION_MOVE: |
| 500 | switch (providerType) { |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 501 | case MetricConsts.PROVIDER_INTRA: |
| 502 | return MetricConsts.FILEOP_MOVE_INTRA_PROVIDER; |
| 503 | case MetricConsts.PROVIDER_SYSTEM: |
| 504 | return MetricConsts.FILEOP_MOVE_SYSTEM_PROVIDER; |
| 505 | case MetricConsts.PROVIDER_EXTERNAL: |
| 506 | return MetricConsts.FILEOP_MOVE_EXTERNAL_PROVIDER; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 507 | } |
| 508 | case FileOperationService.OPERATION_DELETE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 509 | return MetricConsts.FILEOP_DELETE; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 510 | default: |
| 511 | Log.w(TAG, "Unrecognized operation type when logging a file operation"); |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 512 | return MetricConsts.FILEOP_OTHER; |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 513 | } |
| 514 | } |
| 515 | |
| 516 | /** |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 517 | * Maps FileOperationService OpType values, to MetricsOpType values. |
| 518 | */ |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 519 | private static @MetricConsts.FileOp int toMetricsOpType(@OpType int operation) { |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 520 | switch (operation) { |
| 521 | case FileOperationService.OPERATION_COPY: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 522 | return MetricConsts.FILEOP_COPY; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 523 | case FileOperationService.OPERATION_MOVE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 524 | return MetricConsts.FILEOP_MOVE; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 525 | case FileOperationService.OPERATION_DELETE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 526 | return MetricConsts.FILEOP_DELETE; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 527 | case FileOperationService.OPERATION_UNKNOWN: |
| 528 | default: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 529 | return MetricConsts.FILEOP_UNKNOWN; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 530 | } |
| 531 | } |
| 532 | |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 533 | private static @MetricConsts.MetricsAction int toMetricsAction(int action) { |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 534 | switch(action) { |
| 535 | case State.ACTION_OPEN: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 536 | return MetricConsts.ACTION_OPEN; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 537 | case State.ACTION_CREATE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 538 | return MetricConsts.ACTION_CREATE; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 539 | case State.ACTION_GET_CONTENT: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 540 | return MetricConsts.ACTION_GET_CONTENT; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 541 | case State.ACTION_OPEN_TREE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 542 | return MetricConsts.ACTION_OPEN_TREE; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 543 | case State.ACTION_BROWSE: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 544 | return MetricConsts.ACTION_BROWSE; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 545 | case State.ACTION_PICK_COPY_DESTINATION: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 546 | return MetricConsts.ACTION_PICK_COPY_DESTINATION; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 547 | default: |
shawnlin | 9cee68f | 2019-01-25 11:20:18 +0800 | [diff] [blame] | 548 | return MetricConsts.ACTION_OTHER; |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 549 | } |
| 550 | } |
| 551 | |
shawnlin | e0ba46d | 2019-01-25 15:21:26 +0800 | [diff] [blame] | 552 | private static int getSearchMode(boolean isKeyword, boolean isChip) { |
| 553 | if (isKeyword && isChip) { |
| 554 | return MetricConsts.SEARCH_KEYWORD_N_CHIPS; |
| 555 | } else if (isKeyword) { |
| 556 | return MetricConsts.SEARCH_KEYWORD; |
| 557 | } else if (isChip) { |
| 558 | return MetricConsts.SEARCH_CHIPS; |
| 559 | } else { |
| 560 | return MetricConsts.SEARCH_UNKNOWN; |
| 561 | } |
| 562 | } |
| 563 | |
Ben Kwa | b41a5ed | 2016-02-17 16:06:22 -0800 | [diff] [blame] | 564 | /** |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 565 | * Count the given src documents and provide a tally of how many come from the same provider as |
| 566 | * the dst document (if a dst is provided), how many come from system providers, and how many |
| 567 | * come from external 3rd-party providers. |
| 568 | */ |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 569 | private static void countProviders( |
| 570 | ProviderCounts counts, List<DocumentInfo> srcs, @Nullable DocumentInfo dst) { |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 571 | for (DocumentInfo doc: srcs) { |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 572 | countForAuthority(counts, doc.authority, dst); |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 573 | } |
Steve McKay | 99f1dc3 | 2016-12-29 16:02:01 -0800 | [diff] [blame] | 574 | } |
| 575 | |
| 576 | /** |
| 577 | * Count the given uris and provide a tally of how many come from the same provider as |
| 578 | * the dst document (if a dst is provided), how many come from system providers, and how many |
| 579 | * come from external 3rd-party providers. |
| 580 | */ |
| 581 | private static void countProviders(ProviderCounts counts, List<Uri> uris) { |
| 582 | for (Uri uri: uris) { |
| 583 | countForAuthority(counts, uri.getAuthority(), null); |
| 584 | } |
| 585 | } |
| 586 | |
| 587 | private static void countForAuthority( |
| 588 | ProviderCounts counts, String authority, @Nullable DocumentInfo dst) { |
| 589 | if (dst != null && authority.equals(dst.authority)) { |
| 590 | counts.intraProvider++; |
| 591 | } else if (isSystemProvider(authority)){ |
| 592 | counts.systemProvider++; |
| 593 | } else { |
| 594 | counts.externalProvider++; |
| 595 | } |
Ben Kwa | faa2720 | 2016-01-28 16:39:57 -0800 | [diff] [blame] | 596 | } |
| 597 | |
| 598 | private static class ProviderCounts { |
| 599 | int intraProvider; |
| 600 | int systemProvider; |
| 601 | int externalProvider; |
| 602 | } |
felkachang | ec40c5c | 2018-05-14 18:01:11 +0800 | [diff] [blame] | 603 | |
| 604 | private static String getRootIdSafely(Uri uri) { |
| 605 | try { |
| 606 | return DocumentsContract.getRootId(uri); |
| 607 | } catch (IllegalArgumentException iae) { |
| 608 | Log.w(TAG, "Invalid root Uri " + uri.toSafeString()); |
| 609 | } |
| 610 | return null; |
| 611 | } |
Ben Kwa | 1c0a389 | 2016-01-26 11:50:03 -0800 | [diff] [blame] | 612 | } |