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.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER;
22 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE;
23 import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_UNSPECIFIED;
24 import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
25 import static android.stats.devicepolicy.DevicePolicyEnums.PROVISIONING_DPC_SETUP_COMPLETED;
26 import static android.stats.devicepolicy.DevicePolicyEnums.PROVISIONING_DPC_SETUP_STARTED;
27 import static android.stats.devicepolicy.DevicePolicyEnums.PROVISIONING_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE;
28 
29 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ACTION;
30 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_CANCELLED;
31 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_COPY_ACCOUNT_STATUS;
32 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_DPC_INSTALLED_BY_PACKAGE;
33 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_DPC_PACKAGE_NAME;
34 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_NFC;
35 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_QR_CODE;
36 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE;
37 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ERROR;
38 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_EXTRA;
39 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_SESSION_COMPLETED;
40 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_SESSION_STARTED;
41 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TERMS_COUNT;
42 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TERMS_READ;
43 
44 import android.annotation.IntDef;
45 import android.app.admin.DevicePolicyEventLogger;
46 import android.app.admin.DevicePolicyManager;
47 import android.content.ComponentName;
48 import android.content.Context;
49 import android.content.Intent;
50 import android.stats.devicepolicy.DevicePolicyEnums;
51 
52 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences;
53 import com.android.managedprovisioning.common.Utils;
54 import com.android.managedprovisioning.model.ProvisioningParams;
55 import com.android.managedprovisioning.task.AbstractProvisioningTask;
56 import java.util.List;
57 
58 /**
59  * Utility class to log metrics.
60  */
61 public class ProvisioningAnalyticsTracker {
62 
63     private final MetricsLoggerWrapper mMetricsLoggerWrapper = new MetricsLoggerWrapper();
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 CANCELLED_BEFORE_PROVISIONING = 1;
69     public static final int CANCELLED_DURING_PROVISIONING = 2;
70     public static final int CANCELLED_DURING_PROVISIONING_PREPARE = 3;
71     private final ManagedProvisioningSharedPreferences mSharedPreferences;
72 
73     @IntDef({
74         CANCELLED_BEFORE_PROVISIONING,
75         CANCELLED_DURING_PROVISIONING,
76         CANCELLED_DURING_PROVISIONING_PREPARE})
77     public @interface CancelState {}
78 
79     // Only add to the end of the list. Do not change or rearrange these values, that will break
80     // historical data. Do not use negative numbers or zero, logger only handles positive
81     // integers.
82     public static final int COPY_ACCOUNT_SUCCEEDED = 1;
83     public static final int COPY_ACCOUNT_FAILED = 2;
84     public static final int COPY_ACCOUNT_TIMED_OUT = 3;
85     public static final int COPY_ACCOUNT_EXCEPTION = 4;
86 
87     @IntDef({
88         COPY_ACCOUNT_SUCCEEDED,
89         COPY_ACCOUNT_FAILED,
90         COPY_ACCOUNT_TIMED_OUT,
91         COPY_ACCOUNT_EXCEPTION})
92     public @interface CopyAccountStatus {}
93 
94     private static final int PROVISIONING_FLOW_TYPE_ADMIN_INTEGRATED = 1;
95     private static final int PROVISIONING_FLOW_TYPE_LEGACY = 2;
96 
97     private static final int DPC_SETUP_ACTION_UNKNOWN = 1;
98     private static final int DPC_SETUP_ACTION_PROVISIONING_SUCCESSFUL = 2;
99     private static final int DPC_SETUP_ACTION_ADMIN_POLICY_COMPLIANCE = 3;
100 
101     private final MetricsWriter mMetricsWriter;
102 
ProvisioningAnalyticsTracker(MetricsWriter metricsWriter, ManagedProvisioningSharedPreferences prefs)103     public ProvisioningAnalyticsTracker(MetricsWriter metricsWriter,
104             ManagedProvisioningSharedPreferences prefs) {
105         // Disables instantiation. Use getInstance() instead.
106         mMetricsWriter = metricsWriter;
107         mSharedPreferences = prefs;
108     }
109 
110     /**
111      * Logs some metrics when the provisioning starts.
112      *
113      * @param context Context passed to MetricsLogger
114      * @param params Provisioning params
115      */
logProvisioningStarted(Context context, ProvisioningParams params)116     public void logProvisioningStarted(Context context, ProvisioningParams params) {
117         logDpcPackageInformation(context, params.inferDeviceAdminPackageName());
118         logNetworkType(context);
119         maybeLogProvisioningFlowType(params);
120     }
121 
122     /**
123      * Logs some metrics when the preprovisioning starts.
124      *
125      * @param context Context passed to MetricsLogger
126      * @param intent Intent that started provisioning
127      */
logPreProvisioningStarted(Context context, Intent intent)128     public void logPreProvisioningStarted(Context context, Intent intent) {
129         logProvisioningExtras(context, intent);
130         maybeLogEntryPoint(context, intent);
131     }
132 
133     /**
134      * Logs status of copy account to user task.
135      *
136      * @param context Context passed to MetricsLogger
137      * @param status Status of copy account to user task
138      */
logCopyAccountStatus(Context context, @CopyAccountStatus int status)139     public void logCopyAccountStatus(Context context, @CopyAccountStatus int status) {
140         mMetricsLoggerWrapper.logAction(context, PROVISIONING_COPY_ACCOUNT_STATUS, status);
141         mMetricsWriter.write(DevicePolicyEventLogger
142                 .createEvent(DevicePolicyEnums.PROVISIONING_COPY_ACCOUNT_STATUS)
143                 .setInt(status)
144                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
145     }
146 
147     /**
148      * Logs when provisioning is cancelled.
149      *
150      * @param context Context passed to MetricsLogger
151      * @param cancelState State when provisioning was cancelled
152      */
logProvisioningCancelled(Context context, @CancelState int cancelState)153     public void logProvisioningCancelled(Context context, @CancelState int cancelState) {
154         mMetricsLoggerWrapper.logAction(context, PROVISIONING_CANCELLED, cancelState);
155         mMetricsWriter.write(DevicePolicyEventLogger
156                 .createEvent(DevicePolicyEnums.PROVISIONING_CANCELLED)
157                 .setInt(cancelState)
158                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
159     }
160 
161     /**
162      * Logs error during provisioning tasks.
163      *
164      * @param context Context passed to MetricsLogger
165      * @param task Provisioning task which threw error
166      * @param errorCode Code indicating the type of error that happened.
167      */
logProvisioningError(Context context, AbstractProvisioningTask task, int errorCode)168     public void logProvisioningError(Context context, AbstractProvisioningTask task,
169             int errorCode) {
170         mMetricsLoggerWrapper.logAction(context, PROVISIONING_ERROR,
171                 AnalyticsUtils.getErrorString(task, errorCode));
172         mMetricsWriter.write(DevicePolicyEventLogger
173                 .createEvent(DevicePolicyEnums.PROVISIONING_ERROR)
174                 .setStrings(AnalyticsUtils.getErrorString(task, errorCode))
175                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
176     }
177 
178     /**
179      * Logs error code, when provisioning is not allowed.
180      *
181      * @param context Context passed to MetricsLogger
182      * @param provisioningErrorCode Code indicating why provisioning is not allowed.
183      */
logProvisioningNotAllowed(Context context, int provisioningErrorCode)184     public void logProvisioningNotAllowed(Context context, int provisioningErrorCode) {
185         mMetricsLoggerWrapper.logAction(context, PROVISIONING_ERROR, provisioningErrorCode);
186         mMetricsWriter.write(DevicePolicyEventLogger
187                 .createEvent(DevicePolicyEnums.PROVISIONING_ERROR)
188                 .setStrings(String.valueOf(provisioningErrorCode))
189                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
190     }
191 
192     /**
193      * logs when a provisioning session has started.
194      *
195      * @param context Context passed to MetricsLogger
196      */
logProvisioningSessionStarted(Context context)197     public void logProvisioningSessionStarted(Context context) {
198         mMetricsLoggerWrapper.logAction(context, PROVISIONING_SESSION_STARTED);
199         mMetricsWriter.write(DevicePolicyEventLogger
200                 .createEvent(DevicePolicyEnums.PROVISIONING_SESSION_STARTED)
201                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
202     }
203 
204     /**
205      * logs when a provisioning session has completed.
206      *
207      * @param context Context passed to MetricsLogger
208      */
logProvisioningSessionCompleted(Context context)209     public void logProvisioningSessionCompleted(Context context) {
210         mMetricsLoggerWrapper.logAction(context, PROVISIONING_SESSION_COMPLETED);
211         mMetricsWriter.write(DevicePolicyEventLogger
212                 .createEvent(DevicePolicyEnums.PROVISIONING_SESSION_COMPLETED)
213                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
214     }
215 
216     /**
217      * logs number of terms displayed on the terms screen.
218      *
219      * @param context Context passed to MetricsLogger
220      * @param count Number of terms displayed
221      */
logNumberOfTermsDisplayed(Context context, int count)222     public void logNumberOfTermsDisplayed(Context context, int count) {
223         mMetricsLoggerWrapper.logAction(context, PROVISIONING_TERMS_COUNT, count);
224         mMetricsWriter.write(DevicePolicyEventLogger
225                 .createEvent(DevicePolicyEnums.PROVISIONING_TERMS_COUNT)
226                 .setInt(count)
227                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
228     }
229 
230     /**
231      * logs number of terms read on the terms screen.
232      *
233      * @param context Context passed to MetricsLogger
234      * @param count Number of terms read
235      */
logNumberOfTermsRead(Context context, int count)236     public void logNumberOfTermsRead(Context context, int count) {
237         mMetricsLoggerWrapper.logAction(context, PROVISIONING_TERMS_READ, count);
238         mMetricsWriter.write(DevicePolicyEventLogger
239                 .createEvent(DevicePolicyEnums.PROVISIONING_TERMS_READ)
240                 .setInt(count)
241                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
242     }
243 
244     /**
245      * Logs when the provisioning preparation has started.
246      * <p>The preparation includes network setup, downloading, verifying and installing the
247      * admin app.
248      */
logProvisioningPrepareStarted()249     public void logProvisioningPrepareStarted() {
250         mMetricsWriter.write(DevicePolicyEventLogger
251                 .createEvent(DevicePolicyEnums.PROVISIONING_PREPARE_STARTED)
252                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
253     }
254 
255     /**
256      * Logs when the provisioning preparation has completed.
257      * <p>The preparation includes network setup, downloading, verifying and installing the
258      * admin app.
259      */
logProvisioningPrepareCompleted()260     public void logProvisioningPrepareCompleted() {
261         mMetricsWriter.write(DevicePolicyEventLogger
262                 .createEvent(DevicePolicyEnums.PROVISIONING_PREPARE_COMPLETED)
263                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
264     }
265 
logTimeLoggerEvent(int devicePolicyEvent, int time)266     public void logTimeLoggerEvent(int devicePolicyEvent, int time) {
267         mMetricsWriter.write(DevicePolicyEventLogger
268                 .createEvent(devicePolicyEvent)
269                 .setInt(time)
270                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
271     }
272 
273     /**
274      * Logs the provisioning action.
275      *  @param context Context passed to MetricsLogger
276      * @param provisioningAction Action that triggered provisioning
277      */
logProvisioningAction(Context context, String provisioningAction)278     public void logProvisioningAction(Context context, String provisioningAction) {
279         mMetricsLoggerWrapper.logAction(context, PROVISIONING_ACTION, provisioningAction);
280         mMetricsWriter.write(DevicePolicyEventLogger
281                 .createEvent(DevicePolicyEnums.PROVISIONING_ACTION)
282                 .setStrings(provisioningAction)
283                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
284         maybeLogManagedProfileOnFullyManagedDevice(context, provisioningAction);
285     }
286 
287     /**
288      * Logs organization owned managed profile provisioning.
289      */
logOrganizationOwnedManagedProfileProvisioning()290     public void logOrganizationOwnedManagedProfileProvisioning() {
291         mMetricsWriter.write(DevicePolicyEventLogger
292                 .createEvent(DevicePolicyEnums.PROVISIONING_ORGANIZATION_OWNED_MANAGED_PROFILE)
293                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
294     }
295 
296     /**
297      * Logs when the DPC is started, for the purpose of enterprise setup.  Note that in the admin-
298      * integrated flow, this is when {@link DevicePolicyManager#ACTION_ADMIN_POLICY_COMPLIANCE} is
299      * sent to the DPC, not {@link DevicePolicyManager#ACTION_GET_PROVISIONING_MODE}.
300      *  @param context Context passed to MetricsLogger
301      * @param intentAction Action that was sent to the DPC
302      */
logDpcSetupStarted(Context context, String intentAction)303     public void logDpcSetupStarted(Context context, String intentAction) {
304         mMetricsLoggerWrapper.logAction(context, PROVISIONING_DPC_SETUP_STARTED);
305 
306         int intentActionCode;
307         switch(intentAction) {
308             case DevicePolicyManager.ACTION_PROVISIONING_SUCCESSFUL:
309                 intentActionCode = DPC_SETUP_ACTION_PROVISIONING_SUCCESSFUL;
310                 break;
311             case DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE:
312                 intentActionCode = DPC_SETUP_ACTION_ADMIN_POLICY_COMPLIANCE;
313                 break;
314             default:
315                 intentActionCode = DPC_SETUP_ACTION_UNKNOWN;
316                 break;
317         }
318 
319         mMetricsWriter.write(DevicePolicyEventLogger
320                 .createEvent(PROVISIONING_DPC_SETUP_STARTED)
321                 .setInt(intentActionCode)
322                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
323     }
324 
325     /**
326      * Logs when the DPC finishes with enterprise setup.  Note that this is only logged when setup
327      * happens inside Setup Wizard; if it happens after Setup Wizard, we never find out when the
328      * DPC finishes.
329      *  @param context Context passed to MetricsLogger
330      * @param resultCode The result code that is returned by the DPC
331      */
logDpcSetupCompleted(Context context, int resultCode)332     public void logDpcSetupCompleted(Context context, int resultCode) {
333         mMetricsLoggerWrapper.logAction(context, PROVISIONING_DPC_SETUP_COMPLETED);
334         mMetricsWriter.write(DevicePolicyEventLogger
335                 .createEvent(PROVISIONING_DPC_SETUP_COMPLETED)
336                 .setInt(resultCode)
337                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
338     }
339 
340     /**
341      * Logs the type of provisioning flow if this is organization owned provisioning.
342      * <p>It would be either admin integrated flow or legacy.
343      *
344      * @param params Used to extract whether this is the admin integrated flow
345      */
maybeLogProvisioningFlowType(ProvisioningParams params)346     private void maybeLogProvisioningFlowType(ProvisioningParams params) {
347         if (!params.isOrganizationOwnedProvisioning) {
348             return;
349         }
350         final boolean isAdminIntegratedFlow = new Utils().isAdminIntegratedFlow(params);
351         mMetricsWriter.write(DevicePolicyEventLogger
352                 .createEvent(DevicePolicyEnums.PROVISIONING_FLOW_TYPE)
353                 .setInt(isAdminIntegratedFlow
354                         ? PROVISIONING_FLOW_TYPE_ADMIN_INTEGRATED
355                         : PROVISIONING_FLOW_TYPE_LEGACY)
356                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
357     }
358 
359     /**
360      * Logs all the provisioning extras passed by the dpc.
361      *
362      * @param context Context passed to MetricsLogger
363      * @param intent Intent that started provisioning
364      */
logProvisioningExtras(Context context, Intent intent)365     private void logProvisioningExtras(Context context, Intent intent) {
366         final List<String> provisioningExtras = AnalyticsUtils.getAllProvisioningExtras(intent);
367         for (String extra : provisioningExtras) {
368             mMetricsLoggerWrapper.logAction(context, PROVISIONING_EXTRA, extra);
369         }
370         mMetricsWriter.write(DevicePolicyEventLogger
371                 .createEvent(DevicePolicyEnums.PROVISIONING_EXTRAS)
372                 .setStrings(provisioningExtras.toArray(new String[0]))
373                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
374     }
375 
376     /**
377      * Logs some entry points to provisioning.
378      *
379      * @param context Context passed to MetricsLogger
380      * @param intent Intent that started provisioning
381      */
maybeLogEntryPoint(Context context, Intent intent)382     private void maybeLogEntryPoint(Context context, Intent intent) {
383         if (intent == null || intent.getAction() == null) {
384             return;
385         }
386         switch (intent.getAction()) {
387             case ACTION_NDEF_DISCOVERED:
388                 mMetricsLoggerWrapper.logAction(context, PROVISIONING_ENTRY_POINT_NFC);
389                 mMetricsWriter.write(DevicePolicyEventLogger
390                         .createEvent(DevicePolicyEnums.PROVISIONING_ENTRY_POINT_NFC)
391                         .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
392                 break;
393             case ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE:
394                 logProvisionedFromTrustedSource(context, intent);
395                 break;
396         }
397     }
398 
logProvisionedFromTrustedSource(Context context, Intent intent)399     private void logProvisionedFromTrustedSource(Context context, Intent intent) {
400         mMetricsLoggerWrapper.logAction(context, PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE);
401         final int provisioningTrigger = intent.getIntExtra(EXTRA_PROVISIONING_TRIGGER,
402                 PROVISIONING_TRIGGER_UNSPECIFIED);
403         if (provisioningTrigger == PROVISIONING_TRIGGER_QR_CODE) {
404             mMetricsLoggerWrapper.logAction(context, PROVISIONING_ENTRY_POINT_QR_CODE);
405         }
406         mMetricsWriter.write(DevicePolicyEventLogger
407                 .createEvent(DevicePolicyEnums.PROVISIONING_ENTRY_POINT_TRUSTED_SOURCE)
408                 .setInt(provisioningTrigger)
409                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
410     }
411 
412     /**
413      * Logs package information of the dpc.
414      *
415      * @param context Context passed to MetricsLogger
416      * @param dpcPackageName Package name of the dpc
417      */
logDpcPackageInformation(Context context, String dpcPackageName)418     private void logDpcPackageInformation(Context context, String dpcPackageName) {
419         // Logs package name of the dpc.
420         mMetricsLoggerWrapper.logAction(context, PROVISIONING_DPC_PACKAGE_NAME, dpcPackageName);
421         mMetricsWriter.write(DevicePolicyEventLogger
422                 .createEvent(DevicePolicyEnums.PROVISIONING_DPC_PACKAGE_NAME)
423                 .setStrings(dpcPackageName)
424                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
425 
426         // Logs package name of the package which installed dpc.
427         final String dpcInstallerPackage =
428                 AnalyticsUtils.getInstallerPackageName(context, dpcPackageName);
429         mMetricsLoggerWrapper.logAction(context, PROVISIONING_DPC_INSTALLED_BY_PACKAGE,
430                 dpcInstallerPackage);
431         mMetricsWriter.write(DevicePolicyEventLogger
432                 .createEvent(DevicePolicyEnums.PROVISIONING_DPC_INSTALLED_BY_PACKAGE)
433                 .setStrings(dpcInstallerPackage)
434                 .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
435     }
436 
437     /**
438      * Logs the network type to which the device is connected.
439      *
440      * @param context Context passed to MetricsLogger
441      */
logNetworkType(Context context)442     private void logNetworkType(Context context) {
443         NetworkTypeLogger networkTypeLogger = new NetworkTypeLogger(context);
444         networkTypeLogger.log();
445     }
446 
maybeLogManagedProfileOnFullyManagedDevice(Context context, String provisioningAction)447     private void maybeLogManagedProfileOnFullyManagedDevice(Context context,
448             String provisioningAction) {
449         final DevicePolicyManager dpm =
450                 (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
451         final ComponentName currentDeviceOwner = dpm.getDeviceOwnerComponentOnAnyUser();
452         if (currentDeviceOwner != null
453                 && ACTION_PROVISION_MANAGED_PROFILE.equals(provisioningAction)) {
454             mMetricsWriter.write(DevicePolicyEventLogger
455                     .createEvent(PROVISIONING_MANAGED_PROFILE_ON_FULLY_MANAGED_DEVICE)
456                     .setTimePeriod(AnalyticsUtils.getProvisioningTime(mSharedPreferences)));
457         }
458     }
459 }
460