Utils.java revision 72023ca7b7a818fa33e0303baf6f5baef05b5f1b
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 1772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzpackage com.android.managedprovisioning.common; 18d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 193128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 20eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ngimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE; 213128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 223128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE; 233128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; 243128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.app.admin.DevicePolicyManager.MIME_TYPE_PROVISIONING_NFC; 253128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static android.nfc.NfcAdapter.ACTION_NDEF_DISCOVERED; 263128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport static java.nio.charset.StandardCharsets.UTF_8; 273128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 283128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.Account; 293128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AccountManager; 303128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AccountManagerFuture; 313128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.AuthenticatorException; 323128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport android.accounts.OperationCanceledException; 3384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.app.admin.DevicePolicyManager; 349a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.ComponentName; 350b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.Context; 369a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport android.content.Intent; 370b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.ActivityInfo; 38d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.ApplicationInfo; 39d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.IPackageManager; 400b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageInfo; 41d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.content.pm.PackageManager; 420b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.content.pm.PackageManager.NameNotFoundException; 4384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.content.pm.UserInfo; 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; 49ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadwayimport android.os.Process; 50d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.RemoteException; 51d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport android.os.ServiceManager; 52d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfinoimport android.os.UserHandle; 5384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfinoimport android.os.UserManager; 54a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.provider.Settings.Global; 55a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport android.provider.Settings.Secure; 560b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevotimport android.text.TextUtils; 573efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnseimport android.util.Base64; 58d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 59a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shankaimport java.io.IOException; 60ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadwayimport java.lang.Integer; 613128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport java.lang.String; 623128ba4542f3c4c90790af0564e75950c8900961Alan Treadwayimport java.nio.charset.StandardCharsets; 63d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.HashSet; 649a42f2b64dada715248aec7c898f983375a395eeAlan Treadwayimport java.util.List; 65d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnseimport java.util.Set; 66ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadwayimport java.util.concurrent.TimeUnit; 67d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 6872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzimport com.android.managedprovisioning.FinalizationActivity; 6972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzimport com.android.managedprovisioning.ProvisionLogger; 7072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzimport com.android.managedprovisioning.ProvisioningParams; 7172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franzimport com.android.managedprovisioning.TrampolineActivity; 7272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz 73d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse/** 74d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse * Class containing various auxiliary methods. 75d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse */ 76d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnsepublic class Utils { 779f97ed0a3eb724b23f7322a0f425bc4f6e98e6d0Benjamin Franz private static final int ACCOUNT_COPY_TIMEOUT_SECONDS = 60 * 3; // 3 minutes 78ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway 7972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public Utils() {} 809a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 8172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 8272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns the currently installed system apps on a given user. 8372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 8472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>Calls into the {@link IPackageManager} to retrieve all installed packages on the given 8572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * user and returns the package names of all system apps. 8672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 8772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param ipm an {@link IPackageManager} object 8872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param userId the id of the user we are interested in 8972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 9072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public Set<String> getCurrentSystemApps(IPackageManager ipm, int userId) { 91d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse Set<String> apps = new HashSet<String>(); 92d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse List<ApplicationInfo> aInfos = null; 93d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse try { 94d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse aInfos = ipm.getInstalledApplications( 95d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse PackageManager.GET_UNINSTALLED_PACKAGES, userId).getList(); 96d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (RemoteException neverThrown) { 97d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.loge("This should not happen.", neverThrown); 98d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 99d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse for (ApplicationInfo aInfo : aInfos) { 100d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 101d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse apps.add(aInfo.packageName); 102d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 103d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 104d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse return apps; 105d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 106d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 10772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 10872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Disables a given component in a given user. 10972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 11072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param toDisable the component that should be disabled 11172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param userId the id of the user where the component should be disabled. 11272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 11372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void disableComponent(ComponentName toDisable, int userId) { 11472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz disableComponent(IPackageManager.Stub.asInterface(ServiceManager.getService("package")), 11572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz toDisable, userId); 11672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz } 117d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse 11872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 11972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Disables a given component in a given user. 12072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 12172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param ipm an {@link IPackageManager} object 12272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param toDisable the component that should be disabled 12372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param userId the id of the user where the component should be disabled. 12472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 12572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void disableComponent(IPackageManager ipm, ComponentName toDisable, int userId) { 12672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz try { 127d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ipm.setComponentEnabledSetting(toDisable, 128d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP, 129d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse userId); 130d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (RemoteException neverThrown) { 131d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.loge("This should not happen.", neverThrown); 132d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } catch (Exception e) { 133d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse ProvisionLogger.logw("Component not found, not disabling it: " 134d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse + toDisable.toShortString()); 135d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 136d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse } 1370b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 1380b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot /** 1390b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check the validity of the admin component name supplied, or try to infer this componentName 1400b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * from the package. 1410b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1420b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * We are supporting lookup by package name for legacy reasons. 1430b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1440b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * If mdmComponentName is supplied (not null): 1450b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * mdmPackageName is ignored. 1460b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check that the package of mdmComponentName is installed, that mdmComponentName is a 1470b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * receiver in this package, and return it. 1480b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * 1490b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Otherwise: 1500b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * mdmPackageName must be supplied (not null). 1510b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * Check that this package is installed, try to infer a potential device admin in this package, 1520b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot * and return it. 1530b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot */ 15472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 15572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public ComponentName findDeviceAdmin(String mdmPackageName, 1560b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ComponentName mdmComponentName, Context c) throws IllegalProvisioningArgumentException { 1570b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 1580b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot mdmPackageName = mdmComponentName.getPackageName(); 1590b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1600b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmPackageName == null) { 1610b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("Neither the package name nor the" 1620b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " component name of the admin are supplied"); 1630b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1640b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot PackageInfo pi; 1650b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot try { 1660b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot pi = c.getPackageManager().getPackageInfo(mdmPackageName, 1670b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot PackageManager.GET_RECEIVERS); 1680b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } catch (NameNotFoundException e) { 1690b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("Mdm "+ mdmPackageName 1700b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " is not installed. ", e); 1710b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1720b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 1730b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot // If the component was specified in the intent: check that it is in the manifest. 1740b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot checkAdminComponent(mdmComponentName, pi); 1750b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return mdmComponentName; 1760b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } else { 1770b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot // Otherwise: try to find a potential device admin in the manifest. 1780b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return findDeviceAdminInPackage(mdmPackageName, pi); 1790b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1800b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1810b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 18272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 18372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Verifies that an admin component is part of a given package. 18472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 18572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param mdmComponentName the admin component to be checked 18672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param pi the {@link PackageInfo} of the package to be checked. 18772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 18872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @throws IllegalProvisioningArgumentException if the given component is not part of the 18972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * package 19072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 19172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz private void checkAdminComponent(ComponentName mdmComponentName, PackageInfo pi) 1920b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throws IllegalProvisioningArgumentException{ 1930b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot for (ActivityInfo ai : pi.receivers) { 1940b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName.getClassName().equals(ai.name)) { 1950b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return; 1960b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1970b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 1980b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("The component " + mdmComponentName 1990b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + " cannot be found"); 2000b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2010b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot 20272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz private ComponentName findDeviceAdminInPackage(String mdmPackageName, PackageInfo pi) 2030b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throws IllegalProvisioningArgumentException { 2040b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ComponentName mdmComponentName = null; 2050b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot for (ActivityInfo ai : pi.receivers) { 2060b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (!TextUtils.isEmpty(ai.permission) && 2070b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot ai.permission.equals(android.Manifest.permission.BIND_DEVICE_ADMIN)) { 2080b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName != null) { 2090b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("There are several " 2100b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + "device admins in " + mdmPackageName + " but no one in specified"); 2110b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } else { 2120b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot mdmComponentName = new ComponentName(mdmPackageName, ai.name); 2130b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2140b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2150b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2160b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot if (mdmComponentName == null) { 2170b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot throw new IllegalProvisioningArgumentException("There are no device admins in" 2180b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot + mdmPackageName); 2190b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2200b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot return mdmComponentName; 2210b4472570d93aeeda5a33dc05c0dcf03f2d3538bNicolas Prevot } 2229a42f2b64dada715248aec7c898f983375a395eeAlan Treadway 2239a42f2b64dada715248aec7c898f983375a395eeAlan Treadway /** 22472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the current user is the system user. 2259a42f2b64dada715248aec7c898f983375a395eeAlan Treadway */ 22672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isCurrentUserSystem() { 2272a71ac51b3ae8cf0f284d69e57c763cbce8423d7Xiaohui Chen return UserHandle.myUserId() == UserHandle.USER_SYSTEM; 228d0f2928a28d38ce8344b7f15fbfec97aebec0db6Joe Delfino } 22984e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino 23072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 23172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the device is currently managed. 23272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 23372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isDeviceManaged(Context context) { 23484e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino DevicePolicyManager dpm = 23584e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE); 236981e55496221c55a77c0fe01031624cfecf75a54Makoto Onuki return dpm.isDeviceManaged(); 23784e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino } 23884e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino 23972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 24072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the calling user is a managed profile. 24172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 24272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isManagedProfile(Context context) { 24384e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); 24484e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino UserInfo user = um.getUserInfo(UserHandle.myUserId()); 24584e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino return user != null ? user.isManagedProfile() : false; 24684e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino } 24784e56f5cfc1d45b3983dd553096182e774d8cb2cJoe Delfino 24874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse /** 24972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns true if the given package requires an update. 25072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 25172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>There are two cases where an update is required: 25272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 1. The package is not currently present on the device. 25372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 2. The package is present, but the version is below the minimum supported version. 25472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 25572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param packageName the package to be checked for updates 25672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param minSupportedVersion the minimum supported version 25772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 25874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse */ 25972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean packageRequiresUpdate(String packageName, int minSupportedVersion, 26074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse Context context) { 26174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse try { 26274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0); 26374d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse if (packageInfo.versionCode >= minSupportedVersion) { 26474d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse return false; 26574d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 26674d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } catch (NameNotFoundException e) { 26774d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse // Package not on device. 26874d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 26974d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse 27074d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse return true; 27174d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse } 27274d6c14da5117ffd3458602f9f6946c531143436Sander Alewijnse 27372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 27472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Transforms a string into a byte array. 27572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 27672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param s the string to be transformed 27772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 27872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public byte[] stringToByteArray(String s) 2793efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse throws NumberFormatException { 2803efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse try { 2813efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse return Base64.decode(s, Base64.URL_SAFE); 2823efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } catch (IllegalArgumentException e) { 2833efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse throw new NumberFormatException("Incorrect format. Should be Url-safe Base64 encoded."); 2843efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } 2853efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } 2863efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse 28772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 28872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Transforms a byte array into a string. 28972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 29072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param bytes the byte array to be transformed 29172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 29272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public String byteArrayToString(byte[] bytes) { 2933efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse return Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_PADDING | Base64.NO_WRAP); 2943efa83ac5074f40be2e1f275d492cf4175e7eb4bSander Alewijnse } 295a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 29672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 29772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Marks the device as provisioning. 29872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 29972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>This will set the DEVICE_PROVISIONED to 1 as well as marking user setup complete 30072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * on the calling user. 30172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 30272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void markDeviceProvisioned(Context context) { 303a7c379a97ce785b918a10c137e636d63a8d50010Alan Treadway ProvisionLogger.logd("Setting DEVICE_PROVISIONED to 1"); 304c78162c71e63903c6f544544cc81d1128acb6eb0Craig Lafayette Global.putInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 1); 305a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 306a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // Setting this flag will either cause Setup Wizard to finish immediately when it starts (if 307a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // it is not already running), or when its next activity starts (if it is already running, 308a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // e.g. the non-NFC flow). 309a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // When either of these things happen, a home intent is fired. We catch that in 310a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // HomeReceiverActivity before sending the intent to notify the mdm that provisioning is 311a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // complete. 312bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot markUserSetupComplete(context, UserHandle.myUserId()); 313bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot } 314bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot 31572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 31672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Sets user setup complete on a given user. 31772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 31872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>This will set USER_SETUP_COMPLETE to 1 on the given user. 31972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 32072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void markUserSetupComplete(Context context, int userId) { 321a7c379a97ce785b918a10c137e636d63a8d50010Alan Treadway ProvisionLogger.logd("Setting USER_SETUP_COMPLETE to 1 for user " + userId); 322bf793102707971d77950ad1a20dd082ae9ec18bcNicolas Prevot Secure.putIntForUser(context.getContentResolver(), Secure.USER_SETUP_COMPLETE, 1, userId); 323a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 324a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 32572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 32672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether USER_SETUP_COMPLETE is set on the calling user. 32772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 32872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isUserSetupCompleted(Context context) { 329a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return Secure.getInt(context.getContentResolver(), Secure.USER_SETUP_COMPLETE, 0) != 0; 330a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 331a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 332ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway /** 333ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * Set the current users userProvisioningState depending on the following factors: 334ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * <ul> 335ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * <li>We're setting up a managed-profile - need to set state on two users.</li> 336ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * <li>User-setup is complete or not - skip states relating to communicating with 337ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * setup-wizard</li> 338ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * <li>DPC requested we skip the rest of setup-wizard.</li> 339ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * </ul> 340ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * 34172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 342ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * @param params configuration for current provisioning attempt 343ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway */ 34472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 34572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void markUserProvisioningStateInitiallyDone(Context context, 346ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway ProvisioningParams params) { 347ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway int currentUserId = UserHandle.myUserId(); 348ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway int managedProfileUserId = -1; 349ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 350ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway Integer newState = null; 351ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway Integer newProfileState = null; 352ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 353ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway boolean userSetupCompleted = isUserSetupCompleted(context); 354ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) { 355ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // Managed profiles are a special case as two users are involved. 356ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway managedProfileUserId = getManagedProfile(context).getIdentifier(); 357ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (userSetupCompleted) { 358ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // SUW on current user is complete, so nothing much to do beyond indicating we're 359ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // all done. 360ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newProfileState = DevicePolicyManager.STATE_USER_SETUP_FINALIZED; 361ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } else { 362ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // We're still in SUW, so indicate that a managed-profile was setup on current user, 363ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // and that we're awaiting finalization on both. 364ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newState = DevicePolicyManager.STATE_USER_PROFILE_COMPLETE; 365ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newProfileState = DevicePolicyManager.STATE_USER_SETUP_COMPLETE; 366ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 367ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } else if (userSetupCompleted) { 368ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // User setup was previously completed this is an unexpected case. 369ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway ProvisionLogger.logw("user_setup_complete set, but provisioning was started"); 370ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } else if (params.skipUserSetup) { 371ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // DPC requested setup-wizard is skipped, indicate this to SUW. 372ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newState = DevicePolicyManager.STATE_USER_SETUP_COMPLETE; 373ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } else { 374ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // DPC requested setup-wizard is not skipped, indicate this to SUW. 375ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newState = DevicePolicyManager.STATE_USER_SETUP_INCOMPLETE; 376ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 377ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 378ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (newState != null) { 379ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway setUserProvisioningState(dpm, newState, currentUserId); 380ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 381ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (newProfileState != null) { 382ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway setUserProvisioningState(dpm, newProfileState, managedProfileUserId); 383ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 384ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (!userSetupCompleted) { 385ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // We expect a PROVISIONING_FINALIZATION intent to finish setup if we're still in 386ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // user-setup. 387ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway FinalizationActivity.storeProvisioningParams(context, params); 388ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 389ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 390ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 391ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway /** 392ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * Finalize the current users userProvisioningState depending on the following factors: 393ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * <ul> 394ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * <li>We're setting up a managed-profile - need to set state on two users.</li> 395ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * </ul> 396ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * 39772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 398ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * @param params configuration for current provisioning attempt - if null (because 399ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * ManagedProvisioning wasn't used for first phase of provisioning) aassumes we 400ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway * can just mark current user as being in finalized provisioning state 401ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway */ 40272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 40372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void markUserProvisioningStateFinalized(Context context, 404ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway ProvisioningParams params) { 405ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway int currentUserId = UserHandle.myUserId(); 406ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway int managedProfileUserId = -1; 407ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); 408ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway Integer newState = null; 409ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway Integer newProfileState = null; 410ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 411ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (params != null && params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) { 412ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway // Managed profiles are a special case as two users are involved. 413ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway managedProfileUserId = getManagedProfile(context).getIdentifier(); 414ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 415ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newState = DevicePolicyManager.STATE_USER_UNMANAGED; 416ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newProfileState = DevicePolicyManager.STATE_USER_SETUP_FINALIZED; 417ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } else { 418ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway newState = DevicePolicyManager.STATE_USER_SETUP_FINALIZED; 419ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 420ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 421ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (newState != null) { 422ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway setUserProvisioningState(dpm, newState, currentUserId); 423ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 424ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway if (newProfileState != null) { 425ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway setUserProvisioningState(dpm, newProfileState, managedProfileUserId); 426ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 427ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 428ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 42972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz private void setUserProvisioningState(DevicePolicyManager dpm, int state, int userId) { 430ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway ProvisionLogger.logi("Setting userProvisioningState for user " + userId + " to: " + state); 431ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway dpm.setUserProvisioningState(state, userId); 432ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway } 433ba113214d1820f32e5132cd83a06fa1eaedd2866Alan Treadway 43472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 43572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns the first existing managed profile if any present, null otherwise. 43672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 43772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>Note that we currently only support one managed profile per device. 43872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 43972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 44072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public UserHandle getManagedProfile(Context context) { 441a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 442a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka int currentUserId = userManager.getUserHandle(); 443a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka List<UserInfo> userProfiles = userManager.getProfiles(currentUserId); 444a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka for (UserInfo profile : userProfiles) { 445a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (profile.isManagedProfile()) { 446a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return new UserHandle(profile.id); 447a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 448a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 449a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return null; 450a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 451a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 452a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka /** 45372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns the user id of an already existing managed profile or -1 if none exists. 454a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka */ 45572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 45672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public int alreadyHasManagedProfile(Context context) { 457a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka UserHandle managedUser = getManagedProfile(context); 458a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (managedUser != null) { 459a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return managedUser.getIdentifier(); 460a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 461a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka return -1; 462a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 463a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 464a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka 46572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 46672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Removes an account. 46772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 46872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>This removes the given account from the calling user's list of accounts. 46972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 47072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 47172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param account the account to be removed 47272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 47372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 47472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void removeAccount(Context context, Account account) { 475a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka try { 476a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManager accountManager = 477a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); 478a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account, 479a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka null, null /* callback */, null /* handler */); 480a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka // Block to get the result of the removeAccount operation 481a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (bundle.getResult().getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) { 482a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Account removed from the primary user."); 483a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 484a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka Intent removeIntent = (Intent) bundle.getResult().getParcelable( 485a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka AccountManager.KEY_INTENT); 486a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka if (removeIntent != null) { 487a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logi("Starting activity to remove account"); 4880ed8f62fcb0c35402ccee0b93679ace2dc96a03bRubin Xu TrampolineActivity.startActivity(context, removeIntent); 489a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } else { 490a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Could not remove account from the primary user."); 491a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 492a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 493a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } catch (OperationCanceledException | AuthenticatorException | IOException e) { 494a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka ProvisionLogger.logw("Exception removing account from the primary user.", e); 495a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 496a5daf2dfdbb7c1b1ea5b930cc7836cf67778dde4Sudheer Shanka } 4976f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu 49872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 49972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Copies an account to a given user. 50072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 50172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * <p>Copies a given account form {@code sourceUser} to {@code targetUser}. This call is 50272023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * blocking until the operation has succeeded. If within a timeout the account hasn't been 50372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * successfully copied to the new user, we give up. 50472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * 50572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param context a {@link Context} object 50672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param accountToMigrate the account to be migrated 50772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param sourceUser the {@link UserHandle} of the user to copy from 50872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @param targetUser the {@link UserHandle} of the user to copy to 50972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * @return whether account migration successfully completed 51072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 51172023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean maybeCopyAccount(Context context, Account accountToMigrate, 512ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway UserHandle sourceUser, UserHandle targetUser) { 513ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway if (accountToMigrate == null) { 514ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway ProvisionLogger.logd("No account to migrate."); 51572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz return false; 516ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } 517ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway if (sourceUser.equals(targetUser)) { 518ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway ProvisionLogger.logw("sourceUser and targetUser are the same, won't migrate account."); 51972023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz return false; 520ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } 521ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway ProvisionLogger.logd("Attempting to copy account from " + sourceUser + " to " + targetUser); 522ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway try { 523ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway AccountManager accountManager = 524ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE); 525ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway boolean copySucceeded = accountManager.copyAccountToUser( 526ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway accountToMigrate, 527ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway sourceUser, 528ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway targetUser, 529ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway /* callback= */ null, /* handler= */ null) 530ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway .getResult(ACCOUNT_COPY_TIMEOUT_SECONDS, TimeUnit.SECONDS); 531ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway if (copySucceeded) { 532ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway ProvisionLogger.logi("Copied account to " + targetUser); 53372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz return true; 534ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } else { 535ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway ProvisionLogger.loge("Could not copy account to " + targetUser); 536ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } 537ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } catch (OperationCanceledException | AuthenticatorException | IOException e) { 538ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway ProvisionLogger.loge("Exception copying account to " + targetUser, e); 539ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } 54072023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz return false; 541ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway } 542ca9c867e27a1af69960c6c91d90177ea45c78d09Alan Treadway 54372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 54472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether FRP is supported on the device. 54572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 54672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isFrpSupported(Context context) { 5476f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu Object pdbManager = context.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE); 5486f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu return pdbManager != null; 5496f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu } 5506f4ef25d4d1c3473b293e1de7f07dbbc55dc4616Rubin Xu 5513128ba4542f3c4c90790af0564e75950c8900961Alan Treadway /** 552eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * Translates a given managed provisioning intent to its corresponding provisioning flow, using 553eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * the action from the intent. 554eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * 555eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * <p/>This is necessary because, unlike other provisioning actions which has 1:1 mapping, there 556eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * are multiple actions that can trigger the device owner provisioning flow. This includes 557eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * {@link ACTION_PROVISION_MANAGED_DEVICE}, {@link ACTION_NDEF_DISCOVERED} and 558eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * {@link ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE}. These 3 actions are equivalent 559eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * excepts they are sent from a different source. 560eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * 561eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng * @return the appropriate DevicePolicyManager declared action for the given incoming intent. 5623128ba4542f3c4c90790af0564e75950c8900961Alan Treadway * @throws IllegalProvisioningArgumentException if intent is malformed 5633128ba4542f3c4c90790af0564e75950c8900961Alan Treadway */ 56472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 56572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public String mapIntentToDpmAction(Intent intent) 5663128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throws IllegalProvisioningArgumentException { 5673128ba4542f3c4c90790af0564e75950c8900961Alan Treadway if (intent == null || intent.getAction() == null) { 5683128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throw new IllegalProvisioningArgumentException("Null intent action."); 5693128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 5703128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 5713128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // Map the incoming intent to a DevicePolicyManager.ACTION_*, as there is a N:1 mapping in 5723128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // some cases. 5733128ba4542f3c4c90790af0564e75950c8900961Alan Treadway String dpmProvisioningAction; 5743128ba4542f3c4c90790af0564e75950c8900961Alan Treadway switch (intent.getAction()) { 5753128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // Trivial cases. 5763128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_DEVICE: 5773128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE: 5783128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_USER: 5793128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_PROVISION_MANAGED_PROFILE: 5803128ba4542f3c4c90790af0564e75950c8900961Alan Treadway dpmProvisioningAction = intent.getAction(); 5813128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 5823128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 5833128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // NFC cases which need to take mime-type into account. 5843128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case ACTION_NDEF_DISCOVERED: 5853128ba4542f3c4c90790af0564e75950c8900961Alan Treadway String mimeType = intent.getType(); 5863128ba4542f3c4c90790af0564e75950c8900961Alan Treadway switch (mimeType) { 5873128ba4542f3c4c90790af0564e75950c8900961Alan Treadway case MIME_TYPE_PROVISIONING_NFC: 5883128ba4542f3c4c90790af0564e75950c8900961Alan Treadway dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE; 5893128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 5903128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 5913128ba4542f3c4c90790af0564e75950c8900961Alan Treadway default: 5923128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throw new IllegalProvisioningArgumentException( 5933128ba4542f3c4c90790af0564e75950c8900961Alan Treadway "Unknown NFC bump mime-type: " + mimeType); 5943128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 5953128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 5963128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 597eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng // Device owner provisioning from a trusted app. 598eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng // TODO (b/27217042): review for new management modes in split system-user model 599eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng case ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE: 600eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng dpmProvisioningAction = ACTION_PROVISION_MANAGED_DEVICE; 601eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng break; 602eee36899e6a73cf7635b11bb1723a411f324ea91Steven Ng 6033128ba4542f3c4c90790af0564e75950c8900961Alan Treadway default: 6043128ba4542f3c4c90790af0564e75950c8900961Alan Treadway throw new IllegalProvisioningArgumentException("Unknown intent action " 6053128ba4542f3c4c90790af0564e75950c8900961Alan Treadway + intent.getAction()); 6063128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 6073128ba4542f3c4c90790af0564e75950c8900961Alan Treadway return dpmProvisioningAction; 6083128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 6093128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 6103128ba4542f3c4c90790af0564e75950c8900961Alan Treadway /** 6113128ba4542f3c4c90790af0564e75950c8900961Alan Treadway * @return the first {@link NdefRecord} found with a recognized MIME-type 6123128ba4542f3c4c90790af0564e75950c8900961Alan Treadway */ 61372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Add unit tests 61472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public NdefRecord firstNdefRecord(Intent nfcIntent) { 6153128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // Only one first message with NFC_MIME_TYPE is used. 6163128ba4542f3c4c90790af0564e75950c8900961Alan Treadway for (Parcelable rawMsg : nfcIntent.getParcelableArrayExtra( 6173128ba4542f3c4c90790af0564e75950c8900961Alan Treadway NfcAdapter.EXTRA_NDEF_MESSAGES)) { 6183128ba4542f3c4c90790af0564e75950c8900961Alan Treadway NdefMessage msg = (NdefMessage) rawMsg; 6193128ba4542f3c4c90790af0564e75950c8900961Alan Treadway for (NdefRecord record : msg.getRecords()) { 6203128ba4542f3c4c90790af0564e75950c8900961Alan Treadway String mimeType = new String(record.getType(), UTF_8); 6213128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 6223128ba4542f3c4c90790af0564e75950c8900961Alan Treadway if (MIME_TYPE_PROVISIONING_NFC.equals(mimeType)) { 6233128ba4542f3c4c90790af0564e75950c8900961Alan Treadway return record; 6243128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 6253128ba4542f3c4c90790af0564e75950c8900961Alan Treadway 6263128ba4542f3c4c90790af0564e75950c8900961Alan Treadway // Assume only first record of message is used. 6273128ba4542f3c4c90790af0564e75950c8900961Alan Treadway break; 6283128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 6293128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 6303128ba4542f3c4c90790af0564e75950c8900961Alan Treadway return null; 6313128ba4542f3c4c90790af0564e75950c8900961Alan Treadway } 632aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka 63372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 63472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Sends an intent to trigger a factory reset. 63572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 63672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Move the FR intent into a Globals class. 63772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public void sendFactoryResetBroadcast(Context context, String reason) { 638aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR); 639aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 640aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka intent.putExtra(Intent.EXTRA_REASON, reason); 641aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka context.sendBroadcast(intent); 642aa435a10268c541f7bd61a0a254ab934e48fc875Sudheer Shanka } 643e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot 64472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 64572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the given provisioning action is a profile owner action. 64672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 64772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Move the list of device owner actions into a Globals class. 64872023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isProfileOwnerAction(String action) { 649e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot return action.equals(ACTION_PROVISION_MANAGED_PROFILE) 650e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot || action.equals(ACTION_PROVISION_MANAGED_USER); 651e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot } 652e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot 65372023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz /** 65472023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz * Returns whether the given provisioning action is a device owner action. 65572023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz */ 65672023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz // ToDo: Move the list of device owner actions into a Globals class. 65772023ca7b7a818fa33e0303baf6f5baef05b5f1bBenjamin Franz public boolean isDeviceOwnerAction(String action) { 658e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot return action.equals(ACTION_PROVISION_MANAGED_DEVICE) 659e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot || action.equals(ACTION_PROVISION_MANAGED_SHAREABLE_DEVICE); 660e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot } 661e35cc9733194b380637728d39c14dcfc0adee84bNicolas Prevot 662d5e4c42542dd96d8940912cc20dff20fa48da0d9Sander Alewijnse} 663