1 /* 2 * Copyright 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.managedprovisioning.analytics; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; 20 import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED; 21 22 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ACTION; 23 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_CANCELLED; 24 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_COPY_ACCOUNT_STATUS; 25 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_DPC_INSTALLED_BY_PACKAGE; 26 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_DPC_PACKAGE_NAME; 27 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_NFC; 28 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE; 29 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ERROR; 30 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_EXTRA; 31 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_SESSION_COMPLETED; 32 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_SESSION_STARTED; 33 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TERMS_COUNT; 34 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TERMS_READ; 35 36 import android.annotation.IntDef; 37 import android.content.Context; 38 import android.content.Intent; 39 40 import com.android.managedprovisioning.model.ProvisioningParams; 41 import com.android.managedprovisioning.task.AbstractProvisioningTask; 42 43 import java.util.List; 44 45 /** 46 * Utility class to log metrics. 47 */ 48 public class ProvisioningAnalyticsTracker { 49 private static final ProvisioningAnalyticsTracker sInstance = 50 new ProvisioningAnalyticsTracker(); 51 52 private final MetricsLoggerWrapper mMetricsLoggerWrapper = new MetricsLoggerWrapper(); 53 54 // Only add to the end of the list. Do not change or rearrange these values, that will break 55 // historical data. Do not use negative numbers or zero, logger only handles positive 56 // integers. 57 public static final int CANCELLED_BEFORE_PROVISIONING = 1; 58 public static final int CANCELLED_DURING_PROVISIONING = 2; 59 60 @IntDef({ 61 CANCELLED_BEFORE_PROVISIONING, 62 CANCELLED_DURING_PROVISIONING}) 63 public @interface CancelState {} 64 65 // Only add to the end of the list. Do not change or rearrange these values, that will break 66 // historical data. Do not use negative numbers or zero, logger only handles positive 67 // integers. 68 public static final int COPY_ACCOUNT_SUCCEEDED = 1; 69 public static final int COPY_ACCOUNT_FAILED = 2; 70 public static final int COPY_ACCOUNT_TIMED_OUT = 3; 71 public static final int COPY_ACCOUNT_EXCEPTION = 4; 72 73 @IntDef({ 74 COPY_ACCOUNT_SUCCEEDED, 75 COPY_ACCOUNT_FAILED, 76 COPY_ACCOUNT_TIMED_OUT, 77 COPY_ACCOUNT_EXCEPTION}) 78 public @interface CopyAccountStatus {} 79 getInstance()80 public static ProvisioningAnalyticsTracker getInstance() { 81 return sInstance; 82 } 83 ProvisioningAnalyticsTracker()84 private ProvisioningAnalyticsTracker() { 85 // Disables instantiation. Use getInstance() instead. 86 } 87 88 /** 89 * Logs some metrics when the provisioning starts. 90 * 91 * @param context Context passed to MetricsLogger 92 * @param params Provisioning params 93 */ logProvisioningStarted(Context context, ProvisioningParams params)94 public void logProvisioningStarted(Context context, ProvisioningParams params) { 95 logDpcPackageInformation(context, params.inferDeviceAdminPackageName()); 96 logNetworkType(context); 97 logProvisioningAction(context, params.provisioningAction); 98 } 99 100 /** 101 * Logs some metrics when the preprovisioning starts. 102 * 103 * @param context Context passed to MetricsLogger 104 * @param intent Intent that started provisioning 105 */ logPreProvisioningStarted(Context context, Intent intent)106 public void logPreProvisioningStarted(Context context, Intent intent) { 107 logProvisioningExtras(context, intent); 108 maybeLogEntryPoint(context, intent); 109 } 110 111 /** 112 * Logs status of copy account to user task. 113 * 114 * @param context Context passed to MetricsLogger 115 * @param status Status of copy account to user task 116 */ logCopyAccountStatus(Context context, @CopyAccountStatus int status)117 public void logCopyAccountStatus(Context context, @CopyAccountStatus int status) { 118 mMetricsLoggerWrapper.logAction(context, PROVISIONING_COPY_ACCOUNT_STATUS, status); 119 } 120 121 /** 122 * Logs when provisioning is cancelled. 123 * 124 * @param context Context passed to MetricsLogger 125 * @param cancelState State when provisioning was cancelled 126 */ logProvisioningCancelled(Context context, @CancelState int cancelState)127 public void logProvisioningCancelled(Context context, @CancelState int cancelState) { 128 mMetricsLoggerWrapper.logAction(context, PROVISIONING_CANCELLED, cancelState); 129 } 130 131 /** 132 * Logs error during provisioning tasks. 133 * 134 * @param context Context passed to MetricsLogger 135 * @param task Provisioning task which threw error 136 * @param errorCode Code indicating the type of error that happened. 137 */ logProvisioningError(Context context, AbstractProvisioningTask task, int errorCode)138 public void logProvisioningError(Context context, AbstractProvisioningTask task, 139 int errorCode) { 140 mMetricsLoggerWrapper.logAction(context, PROVISIONING_ERROR, 141 AnalyticsUtils.getErrorString(task, errorCode)); 142 } 143 144 /** 145 * Logs error code, when provisioning is not allowed. 146 * 147 * @param context Context passed to MetricsLogger 148 * @param provisioningErrorCode Code indicating why provisioning is not allowed. 149 */ logProvisioningNotAllowed(Context context, int provisioningErrorCode)150 public void logProvisioningNotAllowed(Context context, int provisioningErrorCode) { 151 mMetricsLoggerWrapper.logAction(context, PROVISIONING_ERROR, provisioningErrorCode); 152 } 153 154 /** 155 * logs when a provisioning session has started. 156 * 157 * @param context Context passed to MetricsLogger 158 */ logProvisioningSessionStarted(Context context)159 public void logProvisioningSessionStarted(Context context) { 160 mMetricsLoggerWrapper.logAction(context, PROVISIONING_SESSION_STARTED); 161 } 162 163 /** 164 * logs when a provisioning session has completed. 165 * 166 * @param context Context passed to MetricsLogger 167 */ logProvisioningSessionCompleted(Context context)168 public void logProvisioningSessionCompleted(Context context) { 169 mMetricsLoggerWrapper.logAction(context, PROVISIONING_SESSION_COMPLETED); 170 } 171 172 /** 173 * logs number of terms displayed on the terms screen. 174 * 175 * @param context Context passed to MetricsLogger 176 * @param count Number of terms displayed 177 */ logNumberOfTermsDisplayed(Context context, int count)178 public void logNumberOfTermsDisplayed(Context context, int count) { 179 mMetricsLoggerWrapper.logAction(context, PROVISIONING_TERMS_COUNT, count); 180 } 181 182 /** 183 * logs number of terms read on the terms screen. 184 * 185 * @param context Context passed to MetricsLogger 186 * @param count Number of terms read 187 */ logNumberOfTermsRead(Context context, int count)188 public void logNumberOfTermsRead(Context context, int count) { 189 mMetricsLoggerWrapper.logAction(context, PROVISIONING_TERMS_READ, count); 190 } 191 192 /** 193 * Logs all the provisioning extras passed by the dpc. 194 * 195 * @param context Context passed to MetricsLogger 196 * @param intent Intent that started provisioning 197 */ logProvisioningExtras(Context context, Intent intent)198 private void logProvisioningExtras(Context context, Intent intent) { 199 final List<String> provisioningExtras = AnalyticsUtils.getAllProvisioningExtras(intent); 200 for (String extra : provisioningExtras) { 201 mMetricsLoggerWrapper.logAction(context, PROVISIONING_EXTRA, extra); 202 } 203 } 204 205 /** 206 * Logs some entry points to provisioning. 207 * 208 * @param context Context passed to MetricsLogger 209 * @param intent Intent that started provisioning 210 */ maybeLogEntryPoint(Context context, Intent intent)211 private void maybeLogEntryPoint(Context context, Intent intent) { 212 if (intent == null || intent.getAction() == null) { 213 return; 214 } 215 switch (intent.getAction()) { 216 case ACTION_NDEF_DISCOVERED: 217 mMetricsLoggerWrapper.logAction(context, PROVISIONING_ENTRY_POINT_NFC); 218 break; 219 case ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE: 220 mMetricsLoggerWrapper.logAction(context, PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE); 221 break; 222 } 223 } 224 225 /** 226 * Logs package information of the dpc. 227 * 228 * @param context Context passed to MetricsLogger 229 * @param dpcPackageName Package name of the dpc 230 */ logDpcPackageInformation(Context context, String dpcPackageName)231 private void logDpcPackageInformation(Context context, String dpcPackageName) { 232 // Logs package name of the dpc. 233 mMetricsLoggerWrapper.logAction(context, PROVISIONING_DPC_PACKAGE_NAME, dpcPackageName); 234 235 // Logs package name of the package which installed dpc. 236 final String dpcInstallerPackage = 237 AnalyticsUtils.getInstallerPackageName(context, dpcPackageName); 238 mMetricsLoggerWrapper.logAction(context, PROVISIONING_DPC_INSTALLED_BY_PACKAGE, 239 dpcInstallerPackage); 240 } 241 242 /** 243 * Logs the network type to which the device is connected. 244 * 245 * @param context Context passed to MetricsLogger 246 */ logNetworkType(Context context)247 private void logNetworkType(Context context) { 248 NetworkTypeLogger networkTypeLogger = new NetworkTypeLogger(context); 249 networkTypeLogger.log(); 250 } 251 252 /** 253 * Logs the provisioning action. 254 * 255 * @param context Context passed to MetricsLogger 256 * @param provisioningAction Action that triggered provisioning 257 */ logProvisioningAction(Context context, String provisioningAction)258 private void logProvisioningAction(Context context, String provisioningAction) { 259 mMetricsLoggerWrapper.logAction(context, PROVISIONING_ACTION, provisioningAction); 260 } 261 } 262