Utils.java revision e35cc9733194b380637728d39c14dcfc0adee84b
1d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse/*
2d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Copyright 2014, The Android Open Source Project
3d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse *
4d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Licensed under the Apache License, Version 2.0 (the "License");
5d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * you may not use this file except in compliance with the License.
6d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * You may obtain a copy of the License at
7d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse *
8d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse *     http://www.apache.org/licenses/LICENSE-2.0
9d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse *
10d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Unless required by applicable law or agreed to in writing, software
11d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * distributed under the License is distributed on an "AS IS" BASIS,
12d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * See the License for the specific language governing permissions and
14d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * limitations under the License.
15d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse */
16d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
17d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnsepackage com.android.managedprovisioning;
18d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
193128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE;
203128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
213128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE;
223128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
233128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC;
243128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED;
253128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static java.nio.charset.StandardCharsets.UTF_8;
263128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
273128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.Account;
283128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AccountManager;
293128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AccountManagerFuture;
303128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AuthenticatorException;
313128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.OperationCanceledException;
3284e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.app.admin.DevicePolicyManager;
339a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.ComponentName;
340b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.Context;
359a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.Intent;
360b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.ActivityInfo;
37d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.ApplicationInfo;
38d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.IPackageManager;
390b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageInfo;
40d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.PackageManager;
410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageManager.NameNotFoundException;
4284e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.content.pm.UserInfo;
439a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.graphics.drawable.Drawable;
443128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.nfc.NdefMessage;
453128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.nfc.NdefRecord;
463128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.nfc.NfcAdapter;
47a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.os.Bundle;
483128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.os.Parcelable;
49d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.RemoteException;
50d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.ServiceManager;
51d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfinoimport android.os.UserHandle;
5284e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.os.UserManager;
53a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.provider.Settings.Global;
54a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.provider.Settings.Secure;
550b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.text.TextUtils;
563efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnseimport android.util.Base64;
57d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
58a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport java.io.IOException;
593128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport java.lang.String;
603128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport java.nio.charset.StandardCharsets;
61d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.HashSet;
629a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport java.util.List;
63d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.Set;
64d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
65d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse/**
66d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Class containing various auxiliary methods.
67d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse */
68d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnsepublic class Utils {
699a42f2b64dada715248aec7c898f983375a395eeAlan Treadway    private Utils() {}
709a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
71e36926b4933d60a31858fd8c15249ac400d16752Nicolas Prevot    public static Set<String> getCurrentSystemApps(IPackageManager ipm, int userId) {
72d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        Set<String> apps = new HashSet<String>();
73d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        List<ApplicationInfo> aInfos = null;
74d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        try {
75d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            aInfos = ipm.getInstalledApplications(
76d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                    PackageManager.GET_UNINSTALLED_PACKAGES, userId).getList();
77d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        } catch (RemoteException neverThrown) {
78d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            ProvisionLogger.loge("This should not happen.", neverThrown);
79d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        }
80d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        for (ApplicationInfo aInfo : aInfos) {
81d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
82d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                apps.add(aInfo.packageName);
83d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            }
84d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        }
85d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        return apps;
86d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse    }
87d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
88d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse    public static void disableComponent(ComponentName toDisable, int userId) {
89d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        try {
90d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            IPackageManager ipm = IPackageManager.Stub.asInterface(ServiceManager
91d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                .getService("package"));
92d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse
93d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            ipm.setComponentEnabledSetting(toDisable,
94d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                    PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP,
95d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                    userId);
96d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        } catch (RemoteException neverThrown) {
97d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            ProvisionLogger.loge("This should not happen.", neverThrown);
98d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        } catch (Exception e) {
99d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse            ProvisionLogger.logw("Component not found, not disabling it: "
100d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse                + toDisable.toShortString());
101d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse        }
102d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse    }
1030b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot
1040b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    /**
1050b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * Exception thrown when the provisioning has failed completely.
1060b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     *
1070b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * We're using a custom exception to avoid catching subsequent exceptions that might be
1080b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * significant.
1090b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     */
1100b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    public static class IllegalProvisioningArgumentException extends Exception {
1110b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        public IllegalProvisioningArgumentException(String message) {
1120b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            super(message);
1130b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1140b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot
1150b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        public IllegalProvisioningArgumentException(String message, Throwable t) {
1160b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            super(message, t);
1170b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1180b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    }
1190b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot
1200b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    /**
1210b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * Check the validity of the admin component name supplied, or try to infer this componentName
1220b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * from the package.
1230b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     *
1240b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * We are supporting lookup by package name for legacy reasons.
1250b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     *
1260b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * If mdmComponentName is supplied (not null):
1270b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * mdmPackageName is ignored.
1280b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * Check that the package of mdmComponentName is installed, that mdmComponentName is a
1290b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * receiver in this package, and return it.
1300b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     *
1310b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * Otherwise:
1320b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * mdmPackageName must be supplied (not null).
1330b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * Check that this package is installed, try to infer a potential device admin in this package,
1340b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     * and return it.
1350b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot     */
1360b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    public static ComponentName findDeviceAdmin(String mdmPackageName,
1370b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            ComponentName mdmComponentName, Context c) throws IllegalProvisioningArgumentException {
1380b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        if (mdmComponentName != null) {
1390b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            mdmPackageName = mdmComponentName.getPackageName();
1400b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        if (mdmPackageName == null) {
1420b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            throw new IllegalProvisioningArgumentException("Neither the package name nor the"
1430b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    + " component name of the admin are supplied");
1440b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1450b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        PackageInfo pi;
1460b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        try {
1470b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            pi = c.getPackageManager().getPackageInfo(mdmPackageName,
1480b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    PackageManager.GET_RECEIVERS);
1490b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        } catch (NameNotFoundException e) {
1500b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            throw new IllegalProvisioningArgumentException("Mdm "+ mdmPackageName
1510b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    + " is not installed. ", e);
1520b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1530b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        if (mdmComponentName != null) {
1540b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            // If the component was specified in the intent: check that it is in the manifest.
1550b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            checkAdminComponent(mdmComponentName, pi);
1560b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            return mdmComponentName;
1570b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        } else {
1580b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            // Otherwise: try to find a potential device admin in the manifest.
1590b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            return findDeviceAdminInPackage(mdmPackageName, pi);
1600b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1610b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    }
1620b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot
1630b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    private static void checkAdminComponent(ComponentName mdmComponentName, PackageInfo pi)
1640b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            throws IllegalProvisioningArgumentException{
1650b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        for (ActivityInfo ai : pi.receivers) {
1660b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            if (mdmComponentName.getClassName().equals(ai.name)) {
1670b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                return;
1680b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            }
1690b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1700b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        throw new IllegalProvisioningArgumentException("The component " + mdmComponentName
1710b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                + " cannot be found");
1720b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    }
1730b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot
1740b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    private static ComponentName findDeviceAdminInPackage(String mdmPackageName, PackageInfo pi)
1750b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            throws IllegalProvisioningArgumentException {
1760b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        ComponentName mdmComponentName = null;
1770b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        for (ActivityInfo ai : pi.receivers) {
1780b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            if (!TextUtils.isEmpty(ai.permission) &&
1790b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    ai.permission.equals(android.Manifest.permission.BIND_DEVICE_ADMIN)) {
1800b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                if (mdmComponentName != null) {
1810b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    throw new IllegalProvisioningArgumentException("There are several "
1820b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                            + "device admins in " + mdmPackageName + " but no one in specified");
1830b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                } else {
1840b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    mdmComponentName = new ComponentName(mdmPackageName, ai.name);
1850b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                }
1860b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            }
1870b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1880b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        if (mdmComponentName == null) {
1890b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot            throw new IllegalProvisioningArgumentException("There are no device admins in"
1900b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot                    + mdmPackageName);
1910b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        }
1920b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot        return mdmComponentName;
1930b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot    }
1949a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
1959a42f2b64dada715248aec7c898f983375a395eeAlan Treadway    public static MdmPackageInfo getMdmPackageInfo(PackageManager pm, String packageName) {
1969a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        if (packageName != null) {
1979a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            try {
1989a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                ApplicationInfo ai = pm.getApplicationInfo(packageName, /* default flags */ 0);
1999a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                if (ai != null) {
2009a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                    return new MdmPackageInfo(pm.getApplicationIcon(packageName),
2019a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                            pm.getApplicationLabel(ai).toString());
2029a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                }
2039a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            } catch (PackageManager.NameNotFoundException e) {
2049a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                // Package does not exist, ignore. Should never happen.
2059a42f2b64dada715248aec7c898f983375a395eeAlan Treadway                ProvisionLogger.loge("Package does not exist. Should never happen.");
2069a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            }
2079a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        }
2089a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
2099a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        return null;
2109a42f2b64dada715248aec7c898f983375a395eeAlan Treadway    }
2119a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
2129a42f2b64dada715248aec7c898f983375a395eeAlan Treadway    /**
2139a42f2b64dada715248aec7c898f983375a395eeAlan Treadway     * Information relating to the currently installed MDM package manager.
2149a42f2b64dada715248aec7c898f983375a395eeAlan Treadway     */
2159a42f2b64dada715248aec7c898f983375a395eeAlan Treadway    public static final class MdmPackageInfo {
2169a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        private final Drawable packageIcon;
2179a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        private final String appLabel;
2189a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
2199a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        private MdmPackageInfo(Drawable packageIcon, String appLabel) {
2209a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            this.packageIcon = packageIcon;
2219a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            this.appLabel = appLabel;
2229a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        }
2239a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
2249a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        public String getAppLabel() {
2259a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            return appLabel;
2269a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        }
2279a42f2b64dada715248aec7c898f983375a395eeAlan Treadway
2289a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        public Drawable getPackageIcon() {
2299a42f2b64dada715248aec7c898f983375a395eeAlan Treadway            return packageIcon;
2309a42f2b64dada715248aec7c898f983375a395eeAlan Treadway        }
2319a42f2b64dada715248aec7c898f983375a395eeAlan Treadway    }
232d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino
2332a71ac51b3ae8cf0f284d69e57c763cbce8423d7Xiaohui Chen    public static boolean isCurrentUserSystem() {
2342a71ac51b3ae8cf0f284d69e57c763cbce8423d7Xiaohui Chen        return UserHandle.myUserId() == UserHandle.USER_SYSTEM;
235d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino    }
23684e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino
237981e55496221c55a77c0fe01031624cfecf75a54Makoto Onuki    public static boolean isDeviceManaged(Context context) {
23884e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino        DevicePolicyManager dpm =
23984e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino                (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
240981e55496221c55a77c0fe01031624cfecf75a54Makoto Onuki        return dpm.isDeviceManaged();
24184e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino    }
24284e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino
24384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino    public static boolean isManagedProfile(Context context) {
24484e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
24584e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino        UserInfo user = um.getUserInfo(UserHandle.myUserId());
24684e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino        return user != null ? user.isManagedProfile() : false;
24784e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino    }
24884e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino
24974d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse    /**
25074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse     * Returns true if the given package does not exist on the device or if its version code is less
25174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse     * than the given version, and false otherwise.
25274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse     */
25374d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse    public static boolean packageRequiresUpdate(String packageName, int minSupportedVersion,
25474d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse            Context context) {
25574d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse        try {
25674d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);
25774d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse            if (packageInfo.versionCode >= minSupportedVersion) {
25874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse                return false;
25974d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse            }
26074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse        } catch (NameNotFoundException e) {
26174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse            // Package not on device.
26274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse        }
26374d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse
26474d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse        return true;
26574d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse    }
26674d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse
2673efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse    public static byte[] stringToByteArray(String s)
2683efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse        throws NumberFormatException {
2693efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse        try {
2703efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse            return Base64.decode(s, Base64.URL_SAFE);
2713efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse        } catch (IllegalArgumentException e) {
2723efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse            throw new NumberFormatException("Incorrect format. Should be Url-safe Base64 encoded.");
2733efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse        }
2743efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse    }
2753efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse
2763efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse    public static String byteArrayToString(byte[] bytes) {
2773efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse        return Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP);
2783efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse    }
279a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka
280a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    public static void markDeviceProvisioned(Context context) {
281c78162c71e63903c6f544544cc81d1128acb6eb0Craig Lafayette        Global.putInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
282a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka
283a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        // Setting this flag will either cause Setup Wizard to finish immediately when it starts (if
284a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        // it is not already running), or when its next activity starts (if it is already running,
285a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        // e.g. the non-NFC flow).
286a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        // When either of these things happen, a home intent is fired. We catch that in
287a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        // HomeReceiverActivity before sending the intent to notify the mdm that provisioning is
288a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        // complete.
289bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot        markUserSetupComplete(context, UserHandle.myUserId());
290bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot    }
291bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot
292bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot    public static void markUserSetupComplete(Context context, int userId) {
293bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot        Secure.putIntForUser(context.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, userId);
294a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    }
295a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka
296a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    public static boolean isUserSetupCompleted(Context context) {
297a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        return Secure.getInt(context.getContentResolver(), Secure.USER_SETUP_COMPLETE, 0) != 0;
298a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    }
299a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka
300a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    public static UserHandle getManagedProfile(Context context) {
301a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
302a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        int currentUserId = userManager.getUserHandle();
303a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        List<UserInfo> userProfiles = userManager.getProfiles(currentUserId);
304a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        for (UserInfo profile : userProfiles) {
305a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            if (profile.isManagedProfile()) {
306a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                return new UserHandle(profile.id);
307a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            }
308a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        }
309a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        return null;
310a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    }
311a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka
312a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    /**
313a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka     * @return The User id of an already existing managed profile or -1 if none
314a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka     * exists
315a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka     */
316a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    public static int alreadyHasManagedProfile(Context context) {
317a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        UserHandle managedUser = getManagedProfile(context);
318a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        if (managedUser != null) {
319a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            return managedUser.getIdentifier();
320a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        } else {
321a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            return -1;
322a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        }
323a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    }
324a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka
325a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    public static void removeAccount(Context context, Account account) {
326a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        try {
327a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            AccountManager accountManager =
328a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                    (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
329a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account,
330a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                    null, null /* callback */, null /* handler */);
331a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            // Block to get the result of the removeAccount operation
332a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            if (bundle.getResult().getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
333a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                ProvisionLogger.logw("Account removed from the primary user.");
334a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            } else {
335a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                Intent removeIntent = (Intent) bundle.getResult().getParcelable(
336a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                        AccountManager.KEY_INTENT);
337a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                if (removeIntent != null) {
338a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                    ProvisionLogger.logi("Starting activity to remove account");
3390ed8f62fcb0c35402ccee0b93679ace2dc96a03bRubin Xu                    TrampolineActivity.startActivity(context, removeIntent);
340a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                } else {
341a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                    ProvisionLogger.logw("Could not remove account from the primary user.");
342a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka                }
343a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            }
344a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        } catch (OperationCanceledException | AuthenticatorException | IOException e) {
345a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka            ProvisionLogger.logw("Exception removing account from the primary user.", e);
346a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka        }
347a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka    }
3486f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu
3496f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu    public static boolean isFrpSupported(Context context) {
3506f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu        Object pdbManager = context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
3516f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu        return pdbManager != null;
3526f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu    }
3536f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu
3543128ba4542f3c4c90790af0564e75950c8900961Alan Treadway    /**
3553128ba4542f3c4c90790af0564e75950c8900961Alan Treadway     * @return the appropriate DevicePolicyManager declared action for the given incoming intent
3563128ba4542f3c4c90790af0564e75950c8900961Alan Treadway     * @throws IllegalProvisioningArgumentException if intent is malformed
3573128ba4542f3c4c90790af0564e75950c8900961Alan Treadway     */
3583128ba4542f3c4c90790af0564e75950c8900961Alan Treadway    public static String mapIntentToDpmAction(Intent intent)
3593128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            throws IllegalProvisioningArgumentException {
3603128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        if (intent == null || intent.getAction() == null) {
3613128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            throw new IllegalProvisioningArgumentException("Null intent action.");
3623128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        }
3633128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
3643128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        // Map the incoming intent to a DevicePolicyManager.ACTION_*, as there is a N:1 mapping in
3653128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        // some cases.
3663128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        String dpmProvisioningAction;
3673128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        switch (intent.getAction()) {
3683128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            // Trivial cases.
3693128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            case ACTION_PROVISION_MANAGED_DEVICE:
3703128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE:
3713128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            case ACTION_PROVISION_MANAGED_USER:
3723128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            case ACTION_PROVISION_MANAGED_PROFILE:
3733128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                dpmProvisioningAction = intent.getAction();
3743128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                break;
3753128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
3763128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            // NFC cases which need to take mime-type into account.
3773128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            case ACTION_NDEF_DISCOVERED:
3783128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                String mimeType = intent.getType();
3793128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                switch (mimeType) {
3803128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                    case MIME_TYPE_PROVISIONING_NFC:
3813128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                        dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE;
3823128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                        break;
3833128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
3843128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                    default:
3853128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                        throw new IllegalProvisioningArgumentException(
3863128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                                "Unknown NFC bump mime-type: " + mimeType);
3873128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                }
3883128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                break;
3893128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
3903128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            default:
3913128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                throw new IllegalProvisioningArgumentException("Unknown intent action "
3923128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                        + intent.getAction());
3933128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        }
3943128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        return dpmProvisioningAction;
3953128ba4542f3c4c90790af0564e75950c8900961Alan Treadway    }
3963128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
3973128ba4542f3c4c90790af0564e75950c8900961Alan Treadway    /**
3983128ba4542f3c4c90790af0564e75950c8900961Alan Treadway     * @return the first {@link NdefRecord} found with a recognized MIME-type
3993128ba4542f3c4c90790af0564e75950c8900961Alan Treadway     */
4003128ba4542f3c4c90790af0564e75950c8900961Alan Treadway    public static NdefRecord firstNdefRecord(Intent nfcIntent) {
4013128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        // Only one first message with NFC_MIME_TYPE is used.
4023128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        for (Parcelable rawMsg : nfcIntent.getParcelableArrayExtra(
4033128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                NfcAdapter.EXTRA_NDEF_MESSAGES)) {
4043128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            NdefMessage msg = (NdefMessage) rawMsg;
4053128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            for (NdefRecord record : msg.getRecords()) {
4063128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                String mimeType = new String(record.getType(), UTF_8);
4073128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
4083128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                if (MIME_TYPE_PROVISIONING_NFC.equals(mimeType)) {
4093128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                    return record;
4103128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                }
4113128ba4542f3c4c90790af0564e75950c8900961Alan Treadway
4123128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                // Assume only first record of message is used.
4133128ba4542f3c4c90790af0564e75950c8900961Alan Treadway                break;
4143128ba4542f3c4c90790af0564e75950c8900961Alan Treadway            }
4153128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        }
4163128ba4542f3c4c90790af0564e75950c8900961Alan Treadway        return null;
4173128ba4542f3c4c90790af0564e75950c8900961Alan Treadway    }
418aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka
419aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka    public static void sendFactoryResetBroadcast(Context context, String reason) {
420aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka        Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
421aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
422aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka        intent.putExtra(Intent.EXTRA_REASON, reason);
423aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka        context.sendBroadcast(intent);
424aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka    }
425e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot
426e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot    public static boolean isProfileOwnerAction(String action) {
427e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot        return action.equals(ACTION_PROVISION_MANAGED_PROFILE)
428e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot                || action.equals(ACTION_PROVISION_MANAGED_USER);
429e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot    }
430e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot
431e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot    public static boolean isDeviceOwnerAction(String action) {
432e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot        return action.equals(ACTION_PROVISION_MANAGED_DEVICE)
433e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot                || action.equals(ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE);
434e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot    }
435e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot
436d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse}
437