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 com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_COPY_ACCOUNT_TASK_MS; 20 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_CREATE_PROFILE_TASK_MS; 21 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_DOWNLOAD_PACKAGE_TASK_MS; 22 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENCRYPT_DEVICE_ACTIVITY_TIME_MS; 23 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_INSTALL_PACKAGE_TASK_MS; 24 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS; 25 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_PROVISIONING_ACTIVITY_TIME_MS; 26 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_START_PROFILE_TASK_MS; 27 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TERMS_ACTIVITY_TIME_MS; 28 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_TOTAL_TASK_TIME_MS; 29 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_WEB_ACTIVITY_TIME_MS; 30 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.VIEW_UNKNOWN; 31 import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING; 32 33 import android.content.Context; 34 import android.content.Intent; 35 import android.os.SystemClock; 36 import android.stats.devicepolicy.DevicePolicyEnums; 37 38 import androidx.annotation.NonNull; 39 import androidx.annotation.Nullable; 40 41 import com.android.internal.annotations.VisibleForTesting; 42 import com.android.managedprovisioning.analytics.TimeLogger.TimeCategory; 43 import com.android.managedprovisioning.common.ManagedProvisioningSharedPreferences; 44 import com.android.managedprovisioning.task.AbstractProvisioningTask; 45 46 import java.util.ArrayList; 47 import java.util.List; 48 import java.util.Set; 49 import java.util.function.LongSupplier; 50 51 /** 52 * Class containing various auxiliary methods used by provisioning analytics tracker. 53 */ 54 public class AnalyticsUtils { 55 56 final static int CATEGORY_VIEW_UNKNOWN = -1; 57 AnalyticsUtils()58 public AnalyticsUtils() {} 59 60 private static final String PROVISIONING_EXTRA_PREFIX = "android.app.extra.PROVISIONING_"; 61 62 /** 63 * Returns package name of the installer package, null if package is not present on the device 64 * and empty string if installer package is not present on the device. 65 * 66 * @param context Context used to get package manager 67 * @param packageName Package name of the installed package 68 */ 69 @Nullable getInstallerPackageName(Context context, String packageName)70 public static String getInstallerPackageName(Context context, String packageName) { 71 try { 72 return context.getPackageManager().getInstallerPackageName(packageName); 73 } catch (IllegalArgumentException e) { 74 return null; 75 } 76 } 77 78 /** 79 * Returns elapsed real time. 80 */ elapsedRealTime()81 public Long elapsedRealTime() { 82 return SystemClock.elapsedRealtime(); 83 } 84 85 /** 86 * Returns list of all valid provisioning extras sent by the dpc. 87 * 88 * @param intent Intent that started provisioning 89 */ 90 @NonNull getAllProvisioningExtras(Intent intent)91 public static List<String> getAllProvisioningExtras(Intent intent) { 92 if (intent == null || ACTION_RESUME_PROVISIONING.equals(intent.getAction())) { 93 // Provisioning extras should have already been logged for resume case. 94 return new ArrayList<String>(); 95 } else { 96 return getExtrasFromBundle(intent); 97 } 98 } 99 100 /** 101 * Returns unique string for all provisioning task errors. 102 * 103 * @param task Provisioning task which threw error 104 * @param errorCode Unique code from class indicating the error 105 */ 106 @Nullable getErrorString(AbstractProvisioningTask task, int errorCode)107 public static String getErrorString(AbstractProvisioningTask task, int errorCode) { 108 if (task == null) { 109 return null; 110 } 111 // We do not have definite codes for all provisioning errors yet. We just pass the task's 112 // class name and the internal task's error code to generate a unique error code. 113 return task.getClass().getSimpleName() + ":" + errorCode; 114 } 115 116 @NonNull getExtrasFromBundle(Intent intent)117 private static List<String> getExtrasFromBundle(Intent intent) { 118 List<String> provisioningExtras = new ArrayList<String>(); 119 if (intent != null && intent.getExtras() != null) { 120 final Set<String> keys = intent.getExtras().keySet(); 121 for (String key : keys) { 122 if (isValidProvisioningExtra(key)) { 123 provisioningExtras.add(key); 124 } 125 } 126 } 127 return provisioningExtras; 128 } 129 130 /** 131 * Returns if a string is a valid provisioning extra. 132 */ isValidProvisioningExtra(String provisioningExtra)133 private static boolean isValidProvisioningExtra(String provisioningExtra) { 134 // Currently it verifies using the prefix. We should further change this to verify using the 135 // actual DPM extras. 136 return provisioningExtra != null && provisioningExtra.startsWith(PROVISIONING_EXTRA_PREFIX); 137 } 138 139 /** 140 * Converts from {@link MetricsEvent} constants to {@link DevicePolicyEnums} constants. 141 * <p>If such a {@link MetricsEvent} does not exist, the metric is assumed 142 * to belong to {@link DevicePolicyEnums}. 143 */ getDevicePolicyEventForCategory(@imeCategory int metricsEvent)144 static int getDevicePolicyEventForCategory(@TimeCategory int metricsEvent) { 145 switch (metricsEvent) { 146 case PROVISIONING_COPY_ACCOUNT_TASK_MS: 147 return DevicePolicyEnums.PROVISIONING_COPY_ACCOUNT_TASK_MS; 148 case PROVISIONING_CREATE_PROFILE_TASK_MS: 149 return DevicePolicyEnums.PROVISIONING_CREATE_PROFILE_TASK_MS; 150 case PROVISIONING_DOWNLOAD_PACKAGE_TASK_MS: 151 return DevicePolicyEnums.PROVISIONING_DOWNLOAD_PACKAGE_TASK_MS; 152 case PROVISIONING_ENCRYPT_DEVICE_ACTIVITY_TIME_MS: 153 return DevicePolicyEnums.PROVISIONING_ENCRYPT_DEVICE_ACTIVITY_TIME_MS; 154 case PROVISIONING_INSTALL_PACKAGE_TASK_MS: 155 return DevicePolicyEnums.PROVISIONING_INSTALL_PACKAGE_TASK_MS; 156 case PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS: 157 return DevicePolicyEnums.PROVISIONING_PREPROVISIONING_ACTIVITY_TIME_MS; 158 case PROVISIONING_PROVISIONING_ACTIVITY_TIME_MS: 159 return DevicePolicyEnums.PROVISIONING_PROVISIONING_ACTIVITY_TIME_MS; 160 case PROVISIONING_START_PROFILE_TASK_MS: 161 return DevicePolicyEnums.PROVISIONING_START_PROFILE_TASK_MS; 162 case PROVISIONING_WEB_ACTIVITY_TIME_MS: 163 return DevicePolicyEnums.PROVISIONING_WEB_ACTIVITY_TIME_MS; 164 case PROVISIONING_TERMS_ACTIVITY_TIME_MS: 165 return DevicePolicyEnums.PROVISIONING_TERMS_ACTIVITY_TIME_MS; 166 case PROVISIONING_TOTAL_TASK_TIME_MS: 167 return DevicePolicyEnums.PROVISIONING_TOTAL_TASK_TIME_MS; 168 case VIEW_UNKNOWN: 169 return -1; 170 default: 171 return metricsEvent; 172 } 173 } 174 175 /** 176 * Returns the time passed since provisioning started, in milliseconds. 177 * Returns <code>-1</code> if the provisioning start time was not specified via 178 * {@link ManagedProvisioningSharedPreferences#writeProvisioningStartedTimestamp(long)}. 179 */ getProvisioningTime(ManagedProvisioningSharedPreferences sharedPreferences)180 static long getProvisioningTime(ManagedProvisioningSharedPreferences sharedPreferences) { 181 return getProvisioningTime(sharedPreferences, SystemClock::elapsedRealtime); 182 } 183 184 @VisibleForTesting getProvisioningTime(ManagedProvisioningSharedPreferences sharedPreferences, LongSupplier getTimeFunction)185 static long getProvisioningTime(ManagedProvisioningSharedPreferences sharedPreferences, 186 LongSupplier getTimeFunction) { 187 if (sharedPreferences.getProvisioningStartedTimestamp() == 0) { 188 return -1; 189 } 190 return getTimeFunction.getAsLong() - sharedPreferences.getProvisioningStartedTimestamp(); 191 } 192 } 193