Home | History | Annotate | Download | only in analytics
      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.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
     20 import static com.android.managedprovisioning.common.Globals.ACTION_RESUME_PROVISIONING;
     21 import static java.nio.charset.StandardCharsets.UTF_8;
     22 
     23 import android.content.Context;
     24 import android.content.Intent;
     25 import android.nfc.NdefRecord;
     26 import android.os.SystemClock;
     27 import android.support.annotation.NonNull;
     28 import android.support.annotation.Nullable;
     29 
     30 import com.android.managedprovisioning.parser.PropertiesProvisioningDataParser;
     31 import com.android.managedprovisioning.task.AbstractProvisioningTask;
     32 
     33 import java.io.IOException;
     34 import java.io.StringReader;
     35 import java.util.ArrayList;
     36 import java.util.List;
     37 import java.util.Set;
     38 import java.util.Properties;
     39 
     40 /**
     41  * Class containing various auxiliary methods used by provisioning analytics tracker.
     42  */
     43 public class AnalyticsUtils {
     44 
     45     public AnalyticsUtils() {}
     46 
     47     private static final String PROVISIONING_EXTRA_PREFIX = "android.app.extra.PROVISIONING_";
     48 
     49     /**
     50      * Returns package name of the installer package, null if package is not present on the device
     51      * and empty string if installer package is not present on the device.
     52      *
     53      * @param context Context used to get package manager
     54      * @param packageName Package name of the installed package
     55      */
     56     @Nullable
     57     public static String getInstallerPackageName(Context context, String packageName) {
     58         try {
     59             return context.getPackageManager().getInstallerPackageName(packageName);
     60         } catch (IllegalArgumentException e) {
     61             return null;
     62         }
     63     }
     64 
     65     /**
     66      * Returns elapsed real time.
     67      */
     68     public Long elapsedRealTime() {
     69         return SystemClock.elapsedRealtime();
     70     }
     71 
     72     /**
     73      * Returns list of all valid provisioning extras sent by the dpc.
     74      *
     75      * @param intent Intent that started provisioning
     76      */
     77     @NonNull
     78     public static List<String> getAllProvisioningExtras(Intent intent) {
     79         if (intent == null || ACTION_RESUME_PROVISIONING.equals(intent.getAction())) {
     80             // Provisioning extras should have already been logged for resume case.
     81             return new ArrayList<String>();
     82         } else if (ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
     83             return getExtrasFromProperties(intent);
     84         } else {
     85             return getExtrasFromBundle(intent);
     86         }
     87     }
     88 
     89     /**
     90      * Returns unique string for all provisioning task errors.
     91      *
     92      * @param task Provisioning task which threw error
     93      * @param errorCode Unique code from class indicating the error
     94      */
     95     @Nullable
     96     public static String getErrorString(AbstractProvisioningTask task, int errorCode) {
     97         if (task == null) {
     98             return null;
     99         }
    100         // We do not have definite codes for all provisioning errors yet. We just pass the task's
    101         // class name and the internal task's error code to generate a unique error code.
    102         return task.getClass().getSimpleName() + ":" + errorCode;
    103     }
    104 
    105     @NonNull
    106     private static List<String> getExtrasFromBundle(Intent intent) {
    107         List<String> provisioningExtras = new ArrayList<String>();
    108         if (intent != null && intent.getExtras() != null) {
    109             final Set<String> keys = intent.getExtras().keySet();
    110             for (String key : keys) {
    111                 if (isValidProvisioningExtra(key)) {
    112                     provisioningExtras.add(key);
    113                 }
    114             }
    115         }
    116         return provisioningExtras;
    117     }
    118 
    119     @NonNull
    120     private static List<String> getExtrasFromProperties(Intent intent) {
    121         List<String> provisioningExtras = new ArrayList<String>();
    122         NdefRecord firstRecord = PropertiesProvisioningDataParser.getFirstNdefRecord(intent);
    123         if (firstRecord != null) {
    124             try {
    125                 Properties props = new Properties();
    126                 props.load(new StringReader(new String(firstRecord.getPayload(), UTF_8)));
    127                 final Set<String> keys = props.stringPropertyNames();
    128                 for (String key : keys) {
    129                     if (isValidProvisioningExtra(key)) {
    130                         provisioningExtras.add(key);
    131                     }
    132                 }
    133             } catch (IOException e) {
    134             }
    135         }
    136         return provisioningExtras;
    137     }
    138 
    139     /**
    140      * Returns if a string is a valid provisioning extra.
    141      */
    142     private static boolean isValidProvisioningExtra(String provisioningExtra) {
    143         // Currently it verifies using the prefix. We should further change this to verify using the
    144         // actual DPM extras.
    145         return provisioningExtra != null && provisioningExtra.startsWith(PROVISIONING_EXTRA_PREFIX);
    146     }
    147 }
    148