/*
 * Copyright 2014, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.managedprovisioning.common;

import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
import static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_CLOUD_ENROLLMENT;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_QR_CODE;
import static android.app.admin.DevicePolicyManager.PROVISIONING_TRIGGER_UNSPECIFIED;
import static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;

import static com.android.managedprovisioning.common.Globals.ACTION_PROVISION_MANAGED_DEVICE_SILENTLY;
import static com.android.managedprovisioning.model.ProvisioningParams.PROVISIONING_MODE_FULLY_MANAGED_DEVICE;
import static com.android.managedprovisioning.model.ProvisioningParams.PROVISIONING_MODE_MANAGED_PROFILE;
import static com.android.managedprovisioning.model.ProvisioningParams.PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_NAMAGED_DEVICE;

import android.annotation.WorkerThread;
import android.os.Handler;
import android.os.Looper;
import com.android.managedprovisioning.R;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.view.View.OnClickListener;
import android.widget.TextView;

import com.android.internal.annotations.VisibleForTesting;
import com.android.managedprovisioning.TrampolineActivity;
import com.android.managedprovisioning.model.CustomizationParams;
import com.android.managedprovisioning.model.PackageDownloadInfo;
import com.android.managedprovisioning.model.ProvisioningParams;
import com.android.managedprovisioning.preprovisioning.WebActivity;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.android.setupdesign.GlifLayout;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupcompat.template.FooterButton.ButtonType;

/**
 * Class containing various auxiliary methods.
 */
public class Utils {
    public static final String SHA256_TYPE = "SHA-256";

    // value chosen to match UX designs; when updating check status bar icon colors
    private static final int THRESHOLD_BRIGHT_COLOR = 190;

    public Utils() {}

    /**
     * Returns the system apps currently available to a given user.
     *
     * <p>Calls the {@link IPackageManager} to retrieve all system apps available to a user and
     * returns their package names.
     *
     * @param ipm an {@link IPackageManager} object
     * @param userId the id of the user to check the apps for
     */
    public Set<String> getCurrentSystemApps(IPackageManager ipm, int userId) {
        Set<String> apps = new HashSet<>();
        List<ApplicationInfo> aInfos = null;
        try {
            aInfos = ipm.getInstalledApplications(
                    PackageManager.MATCH_UNINSTALLED_PACKAGES, userId).getList();
        } catch (RemoteException neverThrown) {
            ProvisionLogger.loge("This should not happen.", neverThrown);
        }
        for (ApplicationInfo aInfo : aInfos) {
            if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
                apps.add(aInfo.packageName);
            }
        }
        return apps;
    }

    /**
     * Disables a given component in a given user.
     *
     * @param toDisable the component that should be disabled
     * @param userId the id of the user where the component should be disabled.
     */
    public void disableComponent(ComponentName toDisable, int userId) {
        setComponentEnabledSetting(
                IPackageManager.Stub.asInterface(ServiceManager.getService("package")),
                toDisable,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                userId);
    }

    /**
     * Enables a given component in a given user.
     *
     * @param toEnable the component that should be enabled
     * @param userId the id of the user where the component should be disabled.
     */
    public void enableComponent(ComponentName toEnable, int userId) {
        setComponentEnabledSetting(
                IPackageManager.Stub.asInterface(ServiceManager.getService("package")),
                toEnable,
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                userId);
    }

    /**
     * Disables a given component in a given user.
     *
     * @param ipm an {@link IPackageManager} object
     * @param toDisable the component that should be disabled
     * @param userId the id of the user where the component should be disabled.
     */
    @VisibleForTesting
    void setComponentEnabledSetting(IPackageManager ipm, ComponentName toDisable,
            int enabledSetting, int userId) {
        try {
            ipm.setComponentEnabledSetting(toDisable,
                    enabledSetting, PackageManager.DONT_KILL_APP,
                    userId);
        } catch (RemoteException neverThrown) {
            ProvisionLogger.loge("This should not happen.", neverThrown);
        } catch (Exception e) {
            ProvisionLogger.logw("Component not found, not changing enabled setting: "
                + toDisable.toShortString());
        }
    }

    /**
     * Check the validity of the admin component name supplied, or try to infer this componentName
     * from the package.
     *
     * We are supporting lookup by package name for legacy reasons.
     *
     * If dpcComponentName is supplied (not null): dpcPackageName is ignored.
     * Check that the package of dpcComponentName is installed, that dpcComponentName is a
     * receiver in this package, and return it. The receiver can be in disabled state.
     *
     * Otherwise: dpcPackageName must be supplied (not null).
     * Check that this package is installed, try to infer a potential device admin in this package,
     * and return it.
     */
    @NonNull
    public ComponentName findDeviceAdmin(String dpcPackageName, ComponentName dpcComponentName,
            Context context, int userId) throws IllegalProvisioningArgumentException {
        if (dpcComponentName != null) {
            dpcPackageName = dpcComponentName.getPackageName();
        }
        if (dpcPackageName == null) {
            throw new IllegalProvisioningArgumentException("Neither the package name nor the"
                    + " component name of the admin are supplied");
        }
        PackageInfo pi;
        try {
            pi = context.getPackageManager().getPackageInfoAsUser(dpcPackageName,
                    PackageManager.GET_RECEIVERS | PackageManager.MATCH_DISABLED_COMPONENTS,
                    userId);
        } catch (NameNotFoundException e) {
            throw new IllegalProvisioningArgumentException("Dpc " + dpcPackageName
                    + " is not installed. ", e);
        }

        final ComponentName componentName = findDeviceAdminInPackageInfo(dpcPackageName,
                dpcComponentName, pi);
        if (componentName == null) {
            throw new IllegalProvisioningArgumentException("Cannot find any admin receiver in "
                    + "package " + dpcPackageName + " with component " + dpcComponentName);
        }
        return componentName;
    }

    /**
     * If dpcComponentName is not null: dpcPackageName is ignored.
     * Check that the package of dpcComponentName is installed, that dpcComponentName is a
     * receiver in this package, and return it. The receiver can be in disabled state.
     *
     * Otherwise, try to infer a potential device admin component in this package info.
     *
     * @return infered device admin component in package info. Otherwise, null
     */
    @Nullable
    public ComponentName findDeviceAdminInPackageInfo(@NonNull String dpcPackageName,
            @Nullable ComponentName dpcComponentName, @NonNull PackageInfo pi) {
        if (dpcComponentName != null) {
            if (!isComponentInPackageInfo(dpcComponentName, pi)) {
                ProvisionLogger.logw("The component " + dpcComponentName + " isn't registered in "
                        + "the apk");
                return null;
            }
            return dpcComponentName;
        } else {
            return findDeviceAdminInPackage(dpcPackageName, pi);
        }
    }

    /**
     * Finds a device admin in a given {@link PackageInfo} object.
     *
     * <p>This function returns {@code null} if no or multiple admin receivers were found, and if
     * the package name does not match dpcPackageName.</p>
     * @param packageName packge name that should match the {@link PackageInfo} object.
     * @param packageInfo package info to be examined.
     * @return admin receiver or null in case of error.
     */
    @Nullable
    private ComponentName findDeviceAdminInPackage(String packageName, PackageInfo packageInfo) {
        if (packageInfo == null || !TextUtils.equals(packageInfo.packageName, packageName)) {
            return null;
        }

        ComponentName mdmComponentName = null;
        for (ActivityInfo ai : packageInfo.receivers) {
            if (TextUtils.equals(ai.permission, android.Manifest.permission.BIND_DEVICE_ADMIN)) {
                if (mdmComponentName != null) {
                    ProvisionLogger.logw("more than 1 device admin component are found");
                    return null;
                } else {
                    mdmComponentName = new ComponentName(packageName, ai.name);
                }
            }
        }
        return mdmComponentName;
    }

    private boolean isComponentInPackageInfo(ComponentName dpcComponentName,
            PackageInfo pi) {
        for (ActivityInfo ai : pi.receivers) {
            if (dpcComponentName.getClassName().equals(ai.name)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return if a given package has testOnly="true", in which case we'll relax certain rules
     * for CTS.
     *
     * The system allows this flag to be changed when an app is updated. But
     * {@link DevicePolicyManager} uses the persisted version to do actual checks for relevant
     * dpm command.
     *
     * @see DevicePolicyManagerService#isPackageTestOnly for more info
     */
    public static boolean isPackageTestOnly(PackageManager pm, String packageName, int userHandle) {
        if (TextUtils.isEmpty(packageName)) {
            return false;
        }

        try {
            final ApplicationInfo ai = pm.getApplicationInfoAsUser(packageName,
                    PackageManager.MATCH_DIRECT_BOOT_AWARE
                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
            return ai != null && (ai.flags & ApplicationInfo.FLAG_TEST_ONLY) != 0;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }

    }

    /**
     * Returns whether the current user is the system user.
     */
    public boolean isCurrentUserSystem() {
        return UserHandle.myUserId() == UserHandle.USER_SYSTEM;
    }

    /**
     * Returns whether the device is currently managed.
     */
    public boolean isDeviceManaged(Context context) {
        DevicePolicyManager dpm =
                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        return dpm.isDeviceManaged();
    }

    /**
     * Returns true if the given package requires an update.
     *
     * <p>There are two cases where an update is required:
     * 1. The package is not currently present on the device.
     * 2. The package is present, but the version is below the minimum supported version.
     *
     * @param packageName the package to be checked for updates
     * @param minSupportedVersion the minimum supported version
     * @param context a {@link Context} object
     */
    public boolean packageRequiresUpdate(String packageName, int minSupportedVersion,
            Context context) {
        try {
            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
            // Always download packages if no minimum version given.
            if (minSupportedVersion != PackageDownloadInfo.DEFAULT_MINIMUM_VERSION
                    && packageInfo.versionCode >= minSupportedVersion) {
                return false;
            }
        } catch (NameNotFoundException e) {
            // Package not on device.
        }

        return true;
    }

    /**
     * Returns the first existing managed profile if any present, null otherwise.
     *
     * <p>Note that we currently only support one managed profile per device.
     */
    // TODO: Add unit tests
    public UserHandle getManagedProfile(Context context) {
        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
        int currentUserId = userManager.getUserHandle();
        List<UserInfo> userProfiles = userManager.getProfiles(currentUserId);
        for (UserInfo profile : userProfiles) {
            if (profile.isManagedProfile()) {
                return new UserHandle(profile.id);
            }
        }
        return null;
    }

    /**
     * Returns the user id of an already existing managed profile or -1 if none exists.
     */
    // TODO: Add unit tests
    public int alreadyHasManagedProfile(Context context) {
        UserHandle managedUser = getManagedProfile(context);
        if (managedUser != null) {
            return managedUser.getIdentifier();
        } else {
            return -1;
        }
    }

    /**
     * Removes an account asynchronously.
     *
     * @see #removeAccount(Context, Account)
     */
    public void removeAccountAsync(Context context, Account accountToRemove,
            RemoveAccountListener callback) {
        new RemoveAccountAsyncTask(context, accountToRemove, this, callback).execute();
    }

    /**
     * Removes an account synchronously.
     *
     * This method is blocking and must never be called from the main thread.
     *
     * <p>This removes the given account from the calling user's list of accounts.
     *
     * @param context a {@link Context} object
     * @param account the account to be removed
     */
    // TODO: Add unit tests
    @WorkerThread
    void removeAccount(Context context, Account account) {
        final AccountManager accountManager =
                (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
        final AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account,
                null, null /* callback */, null /* handler */);
        // Block to get the result of the removeAccount operation
        try {
            final Bundle result = bundle.getResult();
            if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, /* default */ false)) {
                ProvisionLogger.logw("Account removed from the primary user.");
            } else {
                final Intent removeIntent = result.getParcelable(AccountManager.KEY_INTENT);
                if (removeIntent != null) {
                    ProvisionLogger.logi("Starting activity to remove account");
                    new Handler(Looper.getMainLooper()).post(() -> {
                        TrampolineActivity.startActivity(context, removeIntent);
                    });
                } else {
                    ProvisionLogger.logw("Could not remove account from the primary user.");
                }
            }
        } catch (OperationCanceledException | AuthenticatorException | IOException e) {
            ProvisionLogger.logw("Exception removing account from the primary user.", e);
        }
    }

    /**
     * Returns whether FRP is supported on the device.
     */
    public boolean isFrpSupported(Context context) {
        Object pdbManager = context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
        return pdbManager != null;
    }

    /**
     * Translates a given managed provisioning intent to its corresponding provisioning flow, using
     * the action from the intent.
     *
     * <p/>This is necessary because, unlike other provisioning actions which has 1:1 mapping, there
     * are multiple actions that can trigger the device owner provisioning flow. This includes
     * {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link ACTION_NDEF_DISCOVERED} and
     * {@link ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}. These 3 actions are equivalent
     * excepts they are sent from a different source.
     *
     * @return the appropriate DevicePolicyManager declared action for the given incoming intent.
     * @throws IllegalProvisioningArgumentException if intent is malformed
     */
    // TODO: Add unit tests
    public String mapIntentToDpmAction(Intent intent)
            throws IllegalProvisioningArgumentException {
        if (intent == null || intent.getAction() == null) {
            throw new IllegalProvisioningArgumentException("Null intent action.");
        }

        // Map the incoming intent to a DevicePolicyManager.ACTION_*, as there is a N:1 mapping in
        // some cases.
        String dpmProvisioningAction;
        switch (intent.getAction()) {
            // Trivial cases.
            case ACTION_PROVISION_MANAGED_DEVICE:
            case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE:
            case ACTION_PROVISION_MANAGED_USER:
            case ACTION_PROVISION_MANAGED_PROFILE:
                dpmProvisioningAction = intent.getAction();
                break;

            // Silent device owner is same as device owner.
            case ACTION_PROVISION_MANAGED_DEVICE_SILENTLY:
                dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE;
                break;

            // NFC cases which need to take mime-type into account.
            case ACTION_NDEF_DISCOVERED:
                String mimeType = intent.getType();
                if (mimeType == null) {
                    throw new IllegalProvisioningArgumentException(
                            "Unknown NFC bump mime-type: " + mimeType);
                }
                switch (mimeType) {
                    case MIME_TYPE_PROVISIONING_NFC:
                        dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE;
                        break;

                    default:
                        throw new IllegalProvisioningArgumentException(
                                "Unknown NFC bump mime-type: " + mimeType);
                }
                break;

            // Device owner provisioning from a trusted app.
            // TODO (b/27217042): review for new management modes in split system-user model
            case ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE:
                dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE;
                break;

            default:
                throw new IllegalProvisioningArgumentException("Unknown intent action "
                        + intent.getAction());
        }
        return dpmProvisioningAction;
    }

    public boolean isCloudEnrollment(Intent intent) {
        return PROVISIONING_TRIGGER_CLOUD_ENROLLMENT ==
                intent.getIntExtra(
                        DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER,
                        /* defValue= */ PROVISIONING_TRIGGER_UNSPECIFIED);
    }

    /**
     * Returns if the given intent for a organization owned provisioning.
     * Only QR, cloud enrollment and NFC are owned by organization.
     */
    public boolean isOrganizationOwnedProvisioning(Intent intent) {
        if (ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            return true;
        }
        if (!ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE.equals(intent.getAction())) {
            return false;
        }
        //  Do additional check under ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE
        // in order to exclude force DO.
        switch (intent.getIntExtra(DevicePolicyManager.EXTRA_PROVISIONING_TRIGGER,
                PROVISIONING_TRIGGER_UNSPECIFIED)) {
            case PROVISIONING_TRIGGER_CLOUD_ENROLLMENT:
            case PROVISIONING_TRIGGER_QR_CODE:
                return true;
            default:
                return false;
        }
    }

    /**
     * Returns if the given parameter is for provisioning the admin integrated flow.
     */
    public boolean isAdminIntegratedFlow(ProvisioningParams params) {
        if (!params.isOrganizationOwnedProvisioning) {
            return false;
        }
        return params.provisioningMode == PROVISIONING_MODE_FULLY_MANAGED_DEVICE
                || params.provisioningMode == PROVISIONING_MODE_MANAGED_PROFILE
                || params.provisioningMode
                    == PROVISIONING_MODE_MANAGED_PROFILE_ON_FULLY_NAMAGED_DEVICE;
    }

    /**
     * Sends an intent to trigger a factory reset.
     */
    // TODO: Move the FR intent into a Globals class.
    public void sendFactoryResetBroadcast(Context context, String reason) {
        Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
        // Send explicit broadcast due to Broadcast Limitations
        intent.setPackage("android");
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.putExtra(Intent.EXTRA_REASON, reason);
        context.sendBroadcast(intent);
    }

    /**
     * Returns whether the given provisioning action is a profile owner action.
     */
    // TODO: Move the list of device owner actions into a Globals class.
    public final boolean isProfileOwnerAction(String action) {
        return ACTION_PROVISION_MANAGED_PROFILE.equals(action)
                || ACTION_PROVISION_MANAGED_USER.equals(action);
    }

    /**
     * Returns whether the given provisioning action is a device owner action.
     */
    // TODO: Move the list of device owner actions into a Globals class.
    public final boolean isDeviceOwnerAction(String action) {
        return ACTION_PROVISION_MANAGED_DEVICE.equals(action)
                || ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE.equals(action);
    }

    /**
     * Returns whether the device currently has connectivity.
     */
    public boolean isConnectedToNetwork(Context context) {
        NetworkInfo info = getActiveNetworkInfo(context);
        return info != null && info.isConnected();
    }

    /**
     * Returns whether the device is currently connected to a wifi.
     */
    public boolean isConnectedToWifi(Context context) {
        NetworkInfo info = getActiveNetworkInfo(context);
        return info != null
                && info.isConnected()
                && info.getType() == ConnectivityManager.TYPE_WIFI;
    }

    /**
     * Returns the active network info of the device.
     */
    public NetworkInfo getActiveNetworkInfo(Context context) {
        ConnectivityManager cm =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getActiveNetworkInfo();
    }

    /**
     * Returns whether encryption is required on this device.
     *
     * <p>Encryption is required if the device is not currently encrypted and the persistent
     * system flag {@code persist.sys.no_req_encrypt} is not set.
     */
    public boolean isEncryptionRequired() {
        return !isPhysicalDeviceEncrypted()
                && !SystemProperties.getBoolean("persist.sys.no_req_encrypt", false);
    }

    /**
     * Returns whether the device is currently encrypted.
     */
    public boolean isPhysicalDeviceEncrypted() {
        return StorageManager.isEncrypted();
    }

    /**
     * Returns the wifi pick intent.
     */
    // TODO: Move this intent into a Globals class.
    public Intent getWifiPickIntent() {
        Intent wifiIntent = new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK);
        wifiIntent.putExtra("extra_prefs_show_button_bar", true);
        wifiIntent.putExtra("wifi_enable_next_on_connect", true);
        return wifiIntent;
    }

    /**
     * Returns whether the device has a split system user.
     *
     * <p>Split system user means that user 0 is system only and all meat users are separate from
     * the system user.
     */
    public boolean isSplitSystemUser() {
        return UserManager.isSplitSystemUser();
    }

    /**
     * Returns whether the currently chosen launcher supports managed profiles.
     *
     * <p>A launcher is deemed to support managed profiles when its target API version is at least
     * {@link Build.VERSION_CODES#LOLLIPOP}.
     */
    public boolean currentLauncherSupportsManagedProfiles(Context context) {
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);

        PackageManager pm = context.getPackageManager();
        ResolveInfo launcherResolveInfo = pm.resolveActivity(intent,
                PackageManager.MATCH_DEFAULT_ONLY);
        if (launcherResolveInfo == null) {
            return false;
        }
        try {
            // If the user has not chosen a default launcher, then launcherResolveInfo will be
            // referring to the resolver activity. It is fine to create a managed profile in
            // this case since there will always be at least one launcher on the device that
            // supports managed profile feature.
            ApplicationInfo launcherAppInfo = pm.getApplicationInfo(
                    launcherResolveInfo.activityInfo.packageName, 0 /* default flags */);
            return versionNumberAtLeastL(launcherAppInfo.targetSdkVersion);
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

    /**
     * Returns whether the given version number is at least lollipop.
     *
     * @param versionNumber the version number to be verified.
     */
    private boolean versionNumberAtLeastL(int versionNumber) {
        return versionNumber >= Build.VERSION_CODES.LOLLIPOP;
    }

    /**
     * Computes the sha 256 hash of a byte array.
     */
    @Nullable
    public byte[] computeHashOfByteArray(byte[] bytes) {
        try {
            MessageDigest md = MessageDigest.getInstance(SHA256_TYPE);
            md.update(bytes);
            return md.digest();
        } catch (NoSuchAlgorithmException e) {
            ProvisionLogger.loge("Hashing algorithm " + SHA256_TYPE + " not supported.", e);
            return null;
        }
    }

    /**
     * Computes a hash of a file with a spcific hash algorithm.
     */
    // TODO: Add unit tests
    @Nullable
    public byte[] computeHashOfFile(String fileLocation, String hashType) {
        InputStream fis = null;
        MessageDigest md;
        byte hash[] = null;
        try {
            md = MessageDigest.getInstance(hashType);
        } catch (NoSuchAlgorithmException e) {
            ProvisionLogger.loge("Hashing algorithm " + hashType + " not supported.", e);
            return null;
        }
        try {
            fis = new FileInputStream(fileLocation);

            byte[] buffer = new byte[256];
            int n = 0;
            while (n != -1) {
                n = fis.read(buffer);
                if (n > 0) {
                    md.update(buffer, 0, n);
                }
            }
            hash = md.digest();
        } catch (IOException e) {
            ProvisionLogger.loge("IO error.", e);
        } finally {
            // Close input stream quietly.
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException e) {
                // Ignore.
            }
        }
        return hash;
    }

    public boolean isBrightColor(int color) {
        // This comes from the YIQ transformation. We're using the formula:
        // Y = .299 * R + .587 * G + .114 * B
        return Color.red(color) * 299 + Color.green(color) * 587 + Color.blue(color) * 114
                >= 1000 * THRESHOLD_BRIGHT_COLOR;
    }

    /**
     * Returns whether given intent can be resolved for the user.
     */
    public boolean canResolveIntentAsUser(Context context, Intent intent, int userId) {
        return intent != null
                && context.getPackageManager().resolveActivityAsUser(intent, 0, userId) != null;
    }

    public boolean isPackageDeviceOwner(DevicePolicyManager dpm, String packageName) {
        final ComponentName deviceOwner = dpm.getDeviceOwnerComponentOnCallingUser();
        return deviceOwner != null && deviceOwner.getPackageName().equals(packageName);
    }

    public int getAccentColor(Context context) {
        return getAttrColor(context, android.R.attr.colorAccent);
    }

    private int getAttrColor(Context context, int attr) {
        TypedArray ta = context.obtainStyledAttributes(new int[]{attr});
        int attrColor = ta.getColor(0, 0);
        ta.recycle();
        return attrColor;
    }

    public void handleSupportUrl(Context context, CustomizationParams customizationParams,
                ClickableSpanFactory clickableSpanFactory,
                AccessibilityContextMenuMaker contextMenuMaker, TextView textView,
                String deviceProvider, String contactDeviceProvider) {
        if (customizationParams.supportUrl == null) {
            textView.setText(contactDeviceProvider);
            return;
        }
        final SpannableString spannableString = new SpannableString(contactDeviceProvider);
        final Intent intent = WebActivity.createIntent(
                context, customizationParams.supportUrl, customizationParams.statusBarColor);
        if (intent != null) {
            final ClickableSpan span = clickableSpanFactory.create(intent);
            final int startIx = contactDeviceProvider.indexOf(deviceProvider);
            final int endIx = startIx + deviceProvider.length();
            spannableString.setSpan(span, startIx, endIx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            textView.setMovementMethod(LinkMovementMethod.getInstance()); // make clicks work
        }

        textView.setText(spannableString);
        contextMenuMaker.registerWithActivity(textView);
    }

    public static boolean isSilentProvisioningForTestingDeviceOwner(
                Context context, ProvisioningParams params) {
        final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
        final ComponentName currentDeviceOwner =
                dpm.getDeviceOwnerComponentOnCallingUser();
        final ComponentName targetDeviceAdmin = params.deviceAdminComponentName;

        switch (params.provisioningAction) {
            case DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE:
                return isPackageTestOnly(context, params)
                        && currentDeviceOwner != null
                        && targetDeviceAdmin != null
                        && currentDeviceOwner.equals(targetDeviceAdmin);
            default:
                return false;
        }
    }

    private static boolean isSilentProvisioningForTestingManagedProfile(
        Context context, ProvisioningParams params) {
        return DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE.equals(
                params.provisioningAction) && isPackageTestOnly(context, params);
    }

    public static boolean isSilentProvisioning(Context context, ProvisioningParams params) {
        return isSilentProvisioningForTestingManagedProfile(context, params)
                || isSilentProvisioningForTestingDeviceOwner(context, params);
    }

    private static boolean isPackageTestOnly(Context context, ProvisioningParams params) {
        final UserManager userManager = context.getSystemService(UserManager.class);
        return isPackageTestOnly(context.getPackageManager(),
                params.inferDeviceAdminPackageName(), userManager.getUserHandle());
    }

    public static FooterButton addNextButton(GlifLayout layout, @NonNull OnClickListener listener) {
        return setPrimaryButton(layout, listener, ButtonType.NEXT, R.string.next);
    }

    public static FooterButton addDoneButton(GlifLayout layout, @NonNull OnClickListener listener) {
        return setPrimaryButton(layout, listener, ButtonType.DONE, R.string.done);
    }

    public static FooterButton addAcceptAndContinueButton(GlifLayout layout,
        @NonNull OnClickListener listener) {
        return setPrimaryButton(layout, listener, ButtonType.NEXT, R.string.accept_and_continue);
    }

    private static FooterButton setPrimaryButton(GlifLayout layout, OnClickListener listener,
        @ButtonType int buttonType, @StringRes int label) {
        final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
        final FooterButton primaryButton = new FooterButton.Builder(layout.getContext())
            .setText(label)
            .setListener(listener)
            .setButtonType(buttonType)
            .setTheme(R.style.SudGlifButton_Primary)
            .build();
        mixin.setPrimaryButton(primaryButton);
        return primaryButton;
    }

    public SimpleDialog.Builder createCancelProvisioningResetDialogBuilder() {
        final int positiveResId = R.string.reset;
        final int negativeResId = R.string.device_owner_cancel_cancel;
        final int dialogMsgResId = R.string.this_will_reset_take_back_first_screen;
        return getBaseDialogBuilder(positiveResId, negativeResId, dialogMsgResId)
                .setTitle(R.string.stop_setup_reset_device_question);
    }

    public SimpleDialog.Builder createCancelProvisioningDialogBuilder() {
        final int positiveResId = R.string.profile_owner_cancel_ok;
        final int negativeResId = R.string.profile_owner_cancel_cancel;
        final int dialogMsgResId = R.string.profile_owner_cancel_message;
        return getBaseDialogBuilder(positiveResId, negativeResId, dialogMsgResId);
    }

    private SimpleDialog.Builder getBaseDialogBuilder(
            int positiveResId, int negativeResId, int dialogMsgResId) {
        return new SimpleDialog.Builder()
                .setCancelable(false)
                .setMessage(dialogMsgResId)
                .setNegativeButtonMessage(negativeResId)
                .setPositiveButtonMessage(positiveResId);
    }
}
